From 9eeb0da0d364350f792986d1d176d8ccb1f04fdf Mon Sep 17 00:00:00 2001 From: Anton Davydov Date: Fri, 15 Oct 2021 18:29:51 +0300 Subject: [PATCH 01/33] swift-alt-gen init --- bin/configs/swift-alt-petstore-new.yaml | 6 +++ .../languages/SwiftAltClientCodegen.java | 46 +++++++++++++++++++ .../org.openapitools.codegen.CodegenConfig | 1 + .../main/resources/swift-alt/README.mustache | 0 .../src/main/resources/swift-alt/api.mustache | 0 .../main/resources/swift-alt/model.mustache | 0 .../SwiftAltClientCodegenOptionsProvider.java | 31 +++++++++++++ .../SwiftAltClientCodegenModelTest.java | 29 ++++++++++++ .../SwiftAltClientCodegenOptionsTest.java | 30 ++++++++++++ .../swift-alt/SwiftAltClientCodegenTest.java | 19 ++++++++ .../swift/alt/.openapi-generator-ignore | 23 ++++++++++ .../swift/alt/.openapi-generator/FILES | 10 ++++ .../swift/alt/.openapi-generator/VERSION | 1 + .../petstore/swift/alt/Apis/PetApi.swift | 0 .../petstore/swift/alt/Apis/StoreApi.swift | 0 .../petstore/swift/alt/Apis/UserApi.swift | 0 .../swift/alt/Models/ApiResponse.swift | 0 .../petstore/swift/alt/Models/Category.swift | 0 .../petstore/swift/alt/Models/Order.swift | 0 .../petstore/swift/alt/Models/Pet.swift | 0 .../petstore/swift/alt/Models/Tag.swift | 0 .../petstore/swift/alt/Models/User.swift | 0 samples/client/petstore/swift/alt/README.md | 0 23 files changed, 196 insertions(+) create mode 100644 bin/configs/swift-alt-petstore-new.yaml create mode 100644 modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java create mode 100644 modules/openapi-generator/src/main/resources/swift-alt/README.mustache create mode 100644 modules/openapi-generator/src/main/resources/swift-alt/api.mustache create mode 100644 modules/openapi-generator/src/main/resources/swift-alt/model.mustache create mode 100644 modules/openapi-generator/src/test/java/org/openapitools/codegen/options/SwiftAltClientCodegenOptionsProvider.java create mode 100644 modules/openapi-generator/src/test/java/org/openapitools/codegen/swift-alt/SwiftAltClientCodegenModelTest.java create mode 100644 modules/openapi-generator/src/test/java/org/openapitools/codegen/swift-alt/SwiftAltClientCodegenOptionsTest.java create mode 100644 modules/openapi-generator/src/test/java/org/openapitools/codegen/swift-alt/SwiftAltClientCodegenTest.java create mode 100644 samples/client/petstore/swift/alt/.openapi-generator-ignore create mode 100644 samples/client/petstore/swift/alt/.openapi-generator/FILES create mode 100644 samples/client/petstore/swift/alt/.openapi-generator/VERSION create mode 100644 samples/client/petstore/swift/alt/Apis/PetApi.swift create mode 100644 samples/client/petstore/swift/alt/Apis/StoreApi.swift create mode 100644 samples/client/petstore/swift/alt/Apis/UserApi.swift create mode 100644 samples/client/petstore/swift/alt/Models/ApiResponse.swift create mode 100644 samples/client/petstore/swift/alt/Models/Category.swift create mode 100644 samples/client/petstore/swift/alt/Models/Order.swift create mode 100644 samples/client/petstore/swift/alt/Models/Pet.swift create mode 100644 samples/client/petstore/swift/alt/Models/Tag.swift create mode 100644 samples/client/petstore/swift/alt/Models/User.swift create mode 100644 samples/client/petstore/swift/alt/README.md diff --git a/bin/configs/swift-alt-petstore-new.yaml b/bin/configs/swift-alt-petstore-new.yaml new file mode 100644 index 000000000000..3f60f1a221ae --- /dev/null +++ b/bin/configs/swift-alt-petstore-new.yaml @@ -0,0 +1,6 @@ +generatorName: swift-alt +outputDir: samples/client/petstore/swift/alt +inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml +templateDir: modules/openapi-generator/src/main/resources/swift-alt +additionalProperties: + hideGenerationTimestamp: "true" diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java new file mode 100644 index 000000000000..2bb6f7334d02 --- /dev/null +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java @@ -0,0 +1,46 @@ +package org.openapitools.codegen.languages; + +import org.openapitools.codegen.*; +import io.swagger.models.properties.ArrayProperty; +import io.swagger.models.properties.MapProperty; +import io.swagger.models.properties.Property; +import io.swagger.models.parameters.Parameter; + +import java.io.File; +import java.util.*; + +import org.apache.commons.lang3.StringUtils; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SwiftAltClientCodegen extends DefaultCodegen implements CodegenConfig { + public static final String PROJECT_NAME = "projectName"; + + static final Logger LOGGER = LoggerFactory.getLogger(SwiftAltClientCodegen.class); + + public CodegenType getTag() { + return CodegenType.CLIENT; + } + + public String getName() { + return "swift-alt"; + } + + public String getHelp() { + return "Generates a swift-alt client."; + } + + public SwiftAltClientCodegen() { + super(); + + outputFolder = "generated-code" + File.separator + "swift-alt"; + modelTemplateFiles.put("model.mustache", ".swift"); + apiTemplateFiles.put("api.mustache", ".swift"); + embeddedTemplateDir = templateDir = "swift-alt"; + apiPackage = "Apis"; + modelPackage = "Models"; + supportingFiles.add(new SupportingFile("README.mustache", "", "README.md")); + // TODO: Fill this out. + } +} diff --git a/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig b/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig index 70a9b14b2446..13f3937dd412 100644 --- a/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig +++ b/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig @@ -138,3 +138,4 @@ org.openapitools.codegen.languages.TypeScriptReduxQueryClientCodegen org.openapitools.codegen.languages.TypeScriptRxjsClientCodegen org.openapitools.codegen.languages.WsdlSchemaCodegen org.openapitools.codegen.languages.XojoClientCodegen +org.openapitools.codegen.languages.SwiftAltClientCodegen diff --git a/modules/openapi-generator/src/main/resources/swift-alt/README.mustache b/modules/openapi-generator/src/main/resources/swift-alt/README.mustache new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/modules/openapi-generator/src/main/resources/swift-alt/api.mustache b/modules/openapi-generator/src/main/resources/swift-alt/api.mustache new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/modules/openapi-generator/src/main/resources/swift-alt/model.mustache b/modules/openapi-generator/src/main/resources/swift-alt/model.mustache new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/SwiftAltClientCodegenOptionsProvider.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/SwiftAltClientCodegenOptionsProvider.java new file mode 100644 index 000000000000..058c59c379cb --- /dev/null +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/SwiftAltClientCodegenOptionsProvider.java @@ -0,0 +1,31 @@ +package org.openapitools.codegen.options; + +import org.openapitools.codegen.CodegenConstants; +import org.openapitools.codegen.languages.SwiftAltClientCodegen; + +import com.google.common.collect.ImmutableMap; + +import java.util.Map; + +public class SwiftAltClientCodegenOptionsProvider implements OptionsProvider { + public static final String PROJECT_NAME_VALUE = "OpenAPI"; + + @Override + public String getLanguage() { + return "swift-alt"; + } + + @Override + public Map createOptions() { + ImmutableMap.Builder builder = new ImmutableMap.Builder(); + return builder + .put(SwiftAltClientCodegen.PROJECT_NAME, PROJECT_NAME_VALUE) + .build(); + } + + @Override + public boolean isServer() { + return false; + } +} + diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/swift-alt/SwiftAltClientCodegenModelTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/swift-alt/SwiftAltClientCodegenModelTest.java new file mode 100644 index 000000000000..070300882844 --- /dev/null +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/swift-alt/SwiftAltClientCodegenModelTest.java @@ -0,0 +1,29 @@ +package org.openapitools.codegen.swift.alt; + +import org.openapitools.codegen.*; +import org.openapitools.codegen.languages.SwiftAltClientCodegen; +import io.swagger.models.*; +import io.swagger.models.properties.*; + +import org.testng.Assert; +import org.testng.annotations.Test; + +@SuppressWarnings("static-method") +public class SwiftAltClientCodegenModelTest { + + @Test(description = "convert a simple java model") + public void simpleModelTest() { + final Model model = new ModelImpl() + .description("a sample model") + .property("id", new LongProperty()) + .property("name", new StringProperty()) + .required("id") + .required("name"); + final DefaultCodegen codegen = new SwiftAltClientCodegen(); + + // TODO: Complete this test. + Assert.fail("Not implemented."); + } + +} + diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/swift-alt/SwiftAltClientCodegenOptionsTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/swift-alt/SwiftAltClientCodegenOptionsTest.java new file mode 100644 index 000000000000..56dd84c038be --- /dev/null +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/swift-alt/SwiftAltClientCodegenOptionsTest.java @@ -0,0 +1,30 @@ +package org.openapitools.codegen.swift.alt; + +import org.openapitools.codegen.AbstractOptionsTest; +import org.openapitools.codegen.CodegenConfig; +import org.openapitools.codegen.languages.SwiftAltClientCodegen; +import org.openapitools.codegen.options.SwiftAltClientCodegenOptionsProvider; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +public class SwiftAltClientCodegenOptionsTest extends AbstractOptionsTest { + private SwiftAltClientCodegen codegen = mock(SwiftAltClientCodegen.class, mockSettings); + + public SwiftAltClientCodegenOptionsTest() { + super(new SwiftAltClientCodegenOptionsProvider()); + } + + @Override + protected CodegenConfig getCodegenConfig() { + return codegen; + } + + @SuppressWarnings("unused") + @Override + protected void verifyOptions() { + // TODO: Complete options using Mockito + // verify(codegen).someMethod(arguments) + } +} + diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/swift-alt/SwiftAltClientCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/swift-alt/SwiftAltClientCodegenTest.java new file mode 100644 index 000000000000..b37e4a7505ea --- /dev/null +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/swift-alt/SwiftAltClientCodegenTest.java @@ -0,0 +1,19 @@ +package org.openapitools.codegen.swift.alt; + +import org.openapitools.codegen.*; +import org.openapitools.codegen.languages.SwiftAltClientCodegen; +import io.swagger.models.*; +import io.swagger.parser.SwaggerParser; +import org.testng.Assert; +import org.testng.annotations.Test; + +public class SwiftAltClientCodegenTest { + + SwiftAltClientCodegen codegen = new SwiftAltClientCodegen(); + + @Test + public void shouldSucceed() throws Exception { + // TODO: Complete this test. + Assert.fail("Not implemented."); + } +} diff --git a/samples/client/petstore/swift/alt/.openapi-generator-ignore b/samples/client/petstore/swift/alt/.openapi-generator-ignore new file mode 100644 index 000000000000..7484ee590a38 --- /dev/null +++ b/samples/client/petstore/swift/alt/.openapi-generator-ignore @@ -0,0 +1,23 @@ +# OpenAPI Generator Ignore +# Generated by openapi-generator https://github.com/openapitools/openapi-generator + +# Use this file to prevent files from being overwritten by the generator. +# The patterns follow closely to .gitignore or .dockerignore. + +# As an example, the C# client generator defines ApiClient.cs. +# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line: +#ApiClient.cs + +# You can match any string of characters against a directory, file or extension with a single asterisk (*): +#foo/*/qux +# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux + +# You can recursively match patterns against a directory, file or extension with a double asterisk (**): +#foo/**/qux +# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux + +# You can also negate patterns with an exclamation (!). +# For example, you can ignore all files in a docs folder with the file extension .md: +#docs/*.md +# Then explicitly reverse the ignore rule for a single file: +#!docs/README.md diff --git a/samples/client/petstore/swift/alt/.openapi-generator/FILES b/samples/client/petstore/swift/alt/.openapi-generator/FILES new file mode 100644 index 000000000000..0d7c0a4af138 --- /dev/null +++ b/samples/client/petstore/swift/alt/.openapi-generator/FILES @@ -0,0 +1,10 @@ +Apis/PetApi.swift +Apis/StoreApi.swift +Apis/UserApi.swift +Models/ApiResponse.swift +Models/Category.swift +Models/Order.swift +Models/Pet.swift +Models/Tag.swift +Models/User.swift +README.md diff --git a/samples/client/petstore/swift/alt/.openapi-generator/VERSION b/samples/client/petstore/swift/alt/.openapi-generator/VERSION new file mode 100644 index 000000000000..4b448de535c7 --- /dev/null +++ b/samples/client/petstore/swift/alt/.openapi-generator/VERSION @@ -0,0 +1 @@ +5.3.0-SNAPSHOT \ No newline at end of file diff --git a/samples/client/petstore/swift/alt/Apis/PetApi.swift b/samples/client/petstore/swift/alt/Apis/PetApi.swift new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/samples/client/petstore/swift/alt/Apis/StoreApi.swift b/samples/client/petstore/swift/alt/Apis/StoreApi.swift new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/samples/client/petstore/swift/alt/Apis/UserApi.swift b/samples/client/petstore/swift/alt/Apis/UserApi.swift new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/samples/client/petstore/swift/alt/Models/ApiResponse.swift b/samples/client/petstore/swift/alt/Models/ApiResponse.swift new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/samples/client/petstore/swift/alt/Models/Category.swift b/samples/client/petstore/swift/alt/Models/Category.swift new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/samples/client/petstore/swift/alt/Models/Order.swift b/samples/client/petstore/swift/alt/Models/Order.swift new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/samples/client/petstore/swift/alt/Models/Pet.swift b/samples/client/petstore/swift/alt/Models/Pet.swift new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/samples/client/petstore/swift/alt/Models/Tag.swift b/samples/client/petstore/swift/alt/Models/Tag.swift new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/samples/client/petstore/swift/alt/Models/User.swift b/samples/client/petstore/swift/alt/Models/User.swift new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/samples/client/petstore/swift/alt/README.md b/samples/client/petstore/swift/alt/README.md new file mode 100644 index 000000000000..e69de29bb2d1 From 71dc3826f200912e886f602509ca5db39a6381f5 Mon Sep 17 00:00:00 2001 From: Anton Davydov Date: Mon, 25 Oct 2021 19:23:13 +0300 Subject: [PATCH 02/33] swift-alt-gen in progress --- .../languages/SwiftAltClientCodegen.java | 877 +++++++++++++++++- .../resources/swift-alt/APIHelper.mustache | 72 ++ .../main/resources/swift-alt/APIs.mustache | 68 ++ .../swift-alt/CodableHelper.mustache | 49 + .../swift-alt/Configuration.mustache | 28 + .../resources/swift-alt/Extensions.mustache | 238 +++++ .../swift-alt/JSONDataEncoding.mustache | 53 ++ .../swift-alt/JSONEncodingHelper.mustache | 45 + .../main/resources/swift-alt/Models.mustache | 54 ++ .../OpenISO8601DateFormatter.mustache | 44 + .../swift-alt/Package.swift.mustache | 57 ++ .../main/resources/swift-alt/README.mustache | 76 ++ .../swift-alt/SynchronizedDictionary.mustache | 36 + .../resources/swift-alt/XcodeGen.mustache | 18 + .../main/resources/swift-alt/_param.mustache | 1 + .../src/main/resources/swift-alt/api.mustache | 559 +++++++++++ .../main/resources/swift-alt/model.mustache | 18 + .../resources/swift-alt/modelArray.mustache | 1 + .../resources/swift-alt/modelEnum.mustache | 7 + .../modelInlineEnumDeclaration.mustache | 7 + .../resources/swift-alt/modelObject.mustache | 46 + .../resources/swift-alt/modelOneOf.mustache | 31 + .../swift/alt/.openapi-generator/FILES | 21 +- .../petstore/swift/alt/Apis/PetApi.swift | 0 .../petstore/swift/alt/Apis/StoreApi.swift | 0 .../petstore/swift/alt/Apis/UserApi.swift | 0 samples/client/petstore/swift/alt/Info.plist | 22 + .../swift/alt/Models/ApiResponse.swift | 0 .../petstore/swift/alt/Models/Category.swift | 0 .../petstore/swift/alt/Models/Order.swift | 0 .../petstore/swift/alt/Models/Pet.swift | 0 .../petstore/swift/alt/Models/Tag.swift | 0 .../petstore/swift/alt/Models/User.swift | 0 .../OpenAPIClient.xcodeproj/project.pbxproj | 395 ++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../UserInterfaceState.xcuserstate | Bin 0 -> 32313 bytes .../xcschemes/OpenAPIClient.xcscheme | 94 ++ .../Classes/OpenAPIs/APIs/PetAPI.swift | 566 +++++++++++ .../Classes/OpenAPIs/APIs/StoreAPI.swift | 271 ++++++ .../Classes/OpenAPIs/APIs/UserAPI.swift | 516 +++++++++++ .../Classes/OpenAPIs/Models/ApiResponse.swift | 40 + .../Classes/OpenAPIs/Models/Category.swift | 36 + .../Classes/OpenAPIs/Models/Order.swift | 58 ++ .../Classes/OpenAPIs/Models/Pet.swift | 58 ++ .../Classes/OpenAPIs/Models/Tag.swift | 36 + .../Classes/OpenAPIs/Models/User.swift | 61 ++ .../client/petstore/swift/alt/Package.swift | 33 + samples/client/petstore/swift/alt/project.yml | 15 + 49 files changed, 4592 insertions(+), 30 deletions(-) create mode 100644 modules/openapi-generator/src/main/resources/swift-alt/APIHelper.mustache create mode 100644 modules/openapi-generator/src/main/resources/swift-alt/APIs.mustache create mode 100644 modules/openapi-generator/src/main/resources/swift-alt/CodableHelper.mustache create mode 100644 modules/openapi-generator/src/main/resources/swift-alt/Configuration.mustache create mode 100644 modules/openapi-generator/src/main/resources/swift-alt/Extensions.mustache create mode 100644 modules/openapi-generator/src/main/resources/swift-alt/JSONDataEncoding.mustache create mode 100644 modules/openapi-generator/src/main/resources/swift-alt/JSONEncodingHelper.mustache create mode 100644 modules/openapi-generator/src/main/resources/swift-alt/Models.mustache create mode 100644 modules/openapi-generator/src/main/resources/swift-alt/OpenISO8601DateFormatter.mustache create mode 100644 modules/openapi-generator/src/main/resources/swift-alt/Package.swift.mustache create mode 100644 modules/openapi-generator/src/main/resources/swift-alt/SynchronizedDictionary.mustache create mode 100644 modules/openapi-generator/src/main/resources/swift-alt/XcodeGen.mustache create mode 100644 modules/openapi-generator/src/main/resources/swift-alt/_param.mustache create mode 100644 modules/openapi-generator/src/main/resources/swift-alt/modelArray.mustache create mode 100644 modules/openapi-generator/src/main/resources/swift-alt/modelEnum.mustache create mode 100644 modules/openapi-generator/src/main/resources/swift-alt/modelInlineEnumDeclaration.mustache create mode 100644 modules/openapi-generator/src/main/resources/swift-alt/modelObject.mustache create mode 100644 modules/openapi-generator/src/main/resources/swift-alt/modelOneOf.mustache delete mode 100644 samples/client/petstore/swift/alt/Apis/PetApi.swift delete mode 100644 samples/client/petstore/swift/alt/Apis/StoreApi.swift delete mode 100644 samples/client/petstore/swift/alt/Apis/UserApi.swift create mode 100644 samples/client/petstore/swift/alt/Info.plist delete mode 100644 samples/client/petstore/swift/alt/Models/ApiResponse.swift delete mode 100644 samples/client/petstore/swift/alt/Models/Category.swift delete mode 100644 samples/client/petstore/swift/alt/Models/Order.swift delete mode 100644 samples/client/petstore/swift/alt/Models/Pet.swift delete mode 100644 samples/client/petstore/swift/alt/Models/Tag.swift delete mode 100644 samples/client/petstore/swift/alt/Models/User.swift create mode 100644 samples/client/petstore/swift/alt/OpenAPIClient.xcodeproj/project.pbxproj create mode 100644 samples/client/petstore/swift/alt/OpenAPIClient.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 samples/client/petstore/swift/alt/OpenAPIClient.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 samples/client/petstore/swift/alt/OpenAPIClient.xcodeproj/project.xcworkspace/xcuserdata/a.davydov.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 samples/client/petstore/swift/alt/OpenAPIClient.xcodeproj/xcshareddata/xcschemes/OpenAPIClient.xcscheme create mode 100644 samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/APIs/PetAPI.swift create mode 100644 samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/APIs/StoreAPI.swift create mode 100644 samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/APIs/UserAPI.swift create mode 100644 samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/Models/ApiResponse.swift create mode 100644 samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/Models/Category.swift create mode 100644 samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/Models/Order.swift create mode 100644 samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/Models/Pet.swift create mode 100644 samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/Models/Tag.swift create mode 100644 samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/Models/User.swift create mode 100644 samples/client/petstore/swift/alt/Package.swift create mode 100644 samples/client/petstore/swift/alt/project.yml diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java index 2bb6f7334d02..ca36c092dec0 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java @@ -1,46 +1,883 @@ +/* + * Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech) + * Copyright 2018 SmartBear Software + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.openapitools.codegen.languages; +import io.swagger.v3.oas.models.media.ArraySchema; +import io.swagger.v3.oas.models.media.Schema; +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.text.WordUtils; import org.openapitools.codegen.*; -import io.swagger.models.properties.ArrayProperty; -import io.swagger.models.properties.MapProperty; -import io.swagger.models.properties.Property; -import io.swagger.models.parameters.Parameter; +import org.openapitools.codegen.meta.GeneratorMetadata; +import org.openapitools.codegen.meta.Stability; +import org.openapitools.codegen.utils.ModelUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.File; +import java.io.IOException; import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.time.OffsetDateTime; +import java.time.Instant; +import java.time.temporal.ChronoField; +import java.util.concurrent.TimeUnit; -import org.apache.commons.lang3.StringUtils; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import static org.openapitools.codegen.utils.StringUtils.camelize; public class SwiftAltClientCodegen extends DefaultCodegen implements CodegenConfig { + private final Logger LOGGER = LoggerFactory.getLogger(SwiftAltClientCodegen.class); + public static final String PROJECT_NAME = "projectName"; + protected String projectName = "OpenAPIClient"; + protected String swiftPackagePath = "Classes" + File.separator + "OpenAPIs"; + protected String sourceFolder = swiftPackagePath; + + /** + * Constructor for the swift alt language codegen module. + */ + public SwiftAltClientCodegen() { + super(); + this.useOneOfInterfaces = true; + + generatorMetadata = GeneratorMetadata.newBuilder(generatorMetadata) + .stability(Stability.STABLE) + .build(); + + outputFolder = "generated-code" + File.separator + "swift"; + modelTemplateFiles.put("model.mustache", ".swift"); + apiTemplateFiles.put("api.mustache", ".swift"); + supportingFiles.add(new SupportingFile("Package.swift.mustache", + "", + "Package.swift")); + supportingFiles.add(new SupportingFile("XcodeGen.mustache", + "", + "project.yml")); + embeddedTemplateDir = templateDir = "swift-alt"; + apiPackage = File.separator + "APIs"; + modelPackage = File.separator + "Models"; + + languageSpecificPrimitives = new HashSet<>( + Arrays.asList( + "Int", + "Int32", + "Int64", + "Float", + "Double", + "Bool", + "Void", + "String", + "Data", + "Date", + "Character", + "UUID", + "URL", + "AnyObject", + "Any", + "Decimal") + ); + defaultIncludes = new HashSet<>( + Arrays.asList( + "Data", + "Date", + "URL", // for file + "UUID", + "Array", + "Dictionary", + "Set", + "Any", + "Empty", + "AnyObject", + "Any", + "Decimal") + ); + + reservedWords = new HashSet<>( + Arrays.asList( + // name used by swift client + "ErrorResponse", "Response", - static final Logger LOGGER = LoggerFactory.getLogger(SwiftAltClientCodegen.class); + // Swift keywords. This list is taken from here: + // https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/doc/uid/TP40014097-CH30-ID410 + // + // Keywords used in declarations + "associatedtype", "class", "deinit", "enum", "extension", "fileprivate", "func", "import", "init", + "inout", "internal", "let", "open", "operator", "private", "protocol", "public", "static", "struct", + "subscript", "typealias", "var", + // Keywords uses in statements + "break", "case", "continue", "default", "defer", "do", "else", "fallthrough", "for", "guard", "if", + "in", "repeat", "return", "switch", "where", "while", + // Keywords used in expressions and types + "as", "Any", "catch", "false", "is", "nil", "rethrows", "super", "self", "Self", "throw", "throws", "true", "try", + // Keywords used in patterns + "_", + // Keywords that begin with a number sign + "#available", "#colorLiteral", "#column", "#else", "#elseif", "#endif", "#file", "#fileLiteral", "#function", "#if", + "#imageLiteral", "#line", "#selector", "#sourceLocation", + // Keywords reserved in particular contexts + "associativity", "convenience", "dynamic", "didSet", "final", "get", "infix", "indirect", "lazy", "left", + "mutating", "none", "nonmutating", "optional", "override", "postfix", "precedence", "prefix", "Protocol", + "required", "right", "set", "Type", "unowned", "weak", "willSet", + // + // Swift Standard Library types + // https://developer.apple.com/documentation/swift + // + // Numbers and Basic Values + "Bool", "Int", "Double", "Float", "Range", "ClosedRange", "Error", "Optional", + // Special-Use Numeric Types + "UInt", "UInt8", "UInt16", "UInt32", "UInt64", "Int8", "Int16", "Int32", "Int64", "Float80", "Float32", "Float64", + // Strings and Text + "String", "Character", "Unicode", "StaticString", + // Collections + "Array", "Dictionary", "Set", "OptionSet", "CountableRange", "CountableClosedRange", + + // The following are commonly-used Foundation types + "URL", "Data", "Codable", "Encodable", "Decodable", + + // The following are other words we want to reserve + "Void", "AnyObject", "Class", "dynamicType", "COLUMN", "FILE", "FUNCTION", "LINE" + ) + ); + + typeMapping = new HashMap<>(); + typeMapping.put("array", "Array"); + typeMapping.put("map", "Dictionary"); + typeMapping.put("set", "Set"); + typeMapping.put("date", "Date"); + typeMapping.put("Date", "Date"); + typeMapping.put("DateTime", "Date"); + typeMapping.put("boolean", "Bool"); + typeMapping.put("string", "String"); + typeMapping.put("char", "Character"); + typeMapping.put("short", "Int"); + typeMapping.put("int", "Int"); + typeMapping.put("long", "Int64"); + typeMapping.put("integer", "Int"); + typeMapping.put("Integer", "Int"); + typeMapping.put("float", "Float"); + typeMapping.put("number", "Double"); + typeMapping.put("double", "Double"); + typeMapping.put("file", "URL"); + typeMapping.put("binary", "URL"); + typeMapping.put("ByteArray", "Data"); + typeMapping.put("UUID", "UUID"); + typeMapping.put("URI", "String"); + typeMapping.put("decimal", "Decimal"); + typeMapping.put("object", "AnyCodable"); + typeMapping.put("AnyType", "AnyCodable"); + typeMapping.put("file", "Data"); + typeMapping.put("binary", "Data"); + + importMapping = new HashMap<>(); + + cliOptions.add(new CliOption(PROJECT_NAME, "Project name in Xcode")); + cliOptions.add(new CliOption(CodegenConstants.API_NAME_PREFIX, CodegenConstants.API_NAME_PREFIX_DESC)); + CliOption libraryOption = new CliOption(CodegenConstants.LIBRARY, "Library template (sub-template) to use"); + } + + private static CodegenModel reconcileProperties(CodegenModel codegenModel, + CodegenModel parentCodegenModel) { + // To support inheritance in this generator, we will analyze + // the parent and child models, look for properties that match, and remove + // them from the child models and leave them in the parent. + // Because the child models extend the parents, the properties + // will be available via the parent. + + // Get the properties for the parent and child models + final List parentModelCodegenProperties = parentCodegenModel.vars; + List codegenProperties = codegenModel.vars; + codegenModel.allVars = new ArrayList(codegenProperties); + codegenModel.parentVars = parentCodegenModel.allVars; + + // Iterate over all of the parent model properties + boolean removedChildProperty = false; + + for (CodegenProperty parentModelCodegenProperty : parentModelCodegenProperties) { + // Now that we have found a prop in the parent class, + // and search the child class for the same prop. + Iterator iterator = codegenProperties.iterator(); + while (iterator.hasNext()) { + CodegenProperty codegenProperty = iterator.next(); + if (codegenProperty.baseName.equals(parentModelCodegenProperty.baseName)) { + // We found a property in the child class that is + // a duplicate of the one in the parent, so remove it. + iterator.remove(); + removedChildProperty = true; + } + } + } + + if (removedChildProperty) { + codegenModel.vars = codegenProperties; + } + + return codegenModel; + } + + @Override public CodegenType getTag() { return CodegenType.CLIENT; } + @Override public String getName() { return "swift-alt"; } + @Override public String getHelp() { - return "Generates a swift-alt client."; + return "Generates a Swift 5 alternative client library."; } - public SwiftAltClientCodegen() { - super(); + @Override + protected void addAdditionPropertiesToCodeGenModel(CodegenModel codegenModel, + Schema schema) { - outputFolder = "generated-code" + File.separator + "swift-alt"; - modelTemplateFiles.put("model.mustache", ".swift"); - apiTemplateFiles.put("api.mustache", ".swift"); - embeddedTemplateDir = templateDir = "swift-alt"; - apiPackage = "Apis"; - modelPackage = "Models"; - supportingFiles.add(new SupportingFile("README.mustache", "", "README.md")); - // TODO: Fill this out. + final Schema additionalProperties = getAdditionalProperties(schema); + + if (additionalProperties != null) { + Schema inner = null; + if (ModelUtils.isArraySchema(schema)) { + ArraySchema ap = (ArraySchema) schema; + inner = ap.getItems(); + } else if (ModelUtils.isMapSchema(schema)) { + inner = getAdditionalProperties(schema); + } + + codegenModel.additionalPropertiesType = inner != null ? getTypeDeclaration(inner) : getSchemaType(additionalProperties); + } + } + + @Override + public void processOpts() { + super.processOpts(); + + if (StringUtils.isEmpty(System.getenv("SWIFT_POST_PROCESS_FILE"))) { + LOGGER.info("Environment variable SWIFT_POST_PROCESS_FILE not defined so the Swift code may not be properly formatted. To define it, try 'export SWIFT_POST_PROCESS_FILE=/usr/local/bin/swiftformat' (Linux/Mac)"); + LOGGER.info("NOTE: To enable file post-processing, 'enablePostProcessFile' must be set to `true` (--enable-post-process-file for CLI)."); + } + + // Setup project name + if (additionalProperties.containsKey(PROJECT_NAME)) { + setProjectName((String) additionalProperties.get(PROJECT_NAME)); + } else { + additionalProperties.put(PROJECT_NAME, projectName); + } + sourceFolder = projectName + File.separator + sourceFolder; + } + + @Override + protected boolean isReservedWord(String word) { + return word != null && reservedWords.contains(word); //don't lowercase as super does + } + + @Override + public String modelFileFolder() { + return outputFolder + File.separator + sourceFolder + + modelPackage().replace('.', File.separatorChar); + } + + @Override + public String apiFileFolder() { + return outputFolder + File.separator + sourceFolder + + apiPackage().replace('.', File.separatorChar); + } + + @Override + public String getTypeDeclaration(Schema p) { + if (ModelUtils.isArraySchema(p)) { + ArraySchema ap = (ArraySchema) p; + Schema inner = ap.getItems(); + return ModelUtils.isSet(p) ? "Set<" + getTypeDeclaration(inner) + ">" : "[" + getTypeDeclaration(inner) + "]"; + } else if (ModelUtils.isMapSchema(p)) { + Schema inner = getAdditionalProperties(p); + return "[String: " + getTypeDeclaration(inner) + "]"; + } + return super.getTypeDeclaration(p); + } + + @Override + public String getSchemaType(Schema p) { + String openAPIType = super.getSchemaType(p); + String type; + if (typeMapping.containsKey(openAPIType)) { + type = typeMapping.get(openAPIType); + if (languageSpecificPrimitives.contains(type) || defaultIncludes.contains(type)) { + return type; + } + } else { + type = openAPIType; + } + return toModelName(type); + } + + @Override + public boolean isDataTypeFile(String dataType) { + return "URL".equals(dataType); + } + + @Override + public boolean isDataTypeBinary(final String dataType) { + return "Data".equals(dataType); + } + + /** + * Output the proper model name (capitalized). + * + * @param name the name of the model + * @return capitalized model name + */ + @Override + public String toModelName(String name) { + // FIXME parameter should not be assigned. Also declare it as "final" + name = sanitizeName(name); + + if (!StringUtils.isEmpty(modelNameSuffix)) { // set model suffix + name = name + "_" + modelNameSuffix; + } + + if (!StringUtils.isEmpty(modelNamePrefix)) { // set model prefix + name = modelNamePrefix + "_" + name; + } + + // camelize the model name + // phone_number => PhoneNumber + name = camelize(name); + + // model name cannot use reserved keyword, e.g. return + if (isReservedWord(name)) { + String modelName = "Model" + name; + LOGGER.warn("{} (reserved word) cannot be used as model name. Renamed to {}", name, modelName); + return modelName; + } + + // model name starts with number + if (name.matches("^\\d.*")) { + // e.g. 200Response => Model200Response (after camelize) + String modelName = "Model" + name; + LOGGER.warn("{} (model name starts with number) cannot be used as model name. Renamed to {}", name, + modelName); + return modelName; + } + + return name; + } + + /** + * Return the capitalized file name of the model. + * + * @param name the model name + * @return the file name of the model + */ + @Override + public String toModelFilename(String name) { + // should be the same as the model name + return toModelName(name); + } + + @Override + public String toDefaultValue(Schema p) { + if (p.getEnum() != null && !p.getEnum().isEmpty()) { + if (p.getDefault() != null) { + if (ModelUtils.isStringSchema(p)) { + return "." + toEnumVarName(escapeText((String) p.getDefault()), p.getType()); + } else { + return "." + toEnumVarName(escapeText(p.getDefault().toString()), p.getType()); + } + } + } + if (p.getDefault() != null) { + if (ModelUtils.isIntegerSchema(p) || ModelUtils.isNumberSchema(p) || ModelUtils.isBooleanSchema(p)) { + return p.getDefault().toString(); + } else if (ModelUtils.isDateTimeSchema(p)) { + // Datetime time stamps in Swift are expressed as Seconds with Microsecond precision. + // In Java, we need to be creative to get the Timestamp in Microseconds as a long. + Instant instant = ((OffsetDateTime) p.getDefault()).toInstant(); + long epochMicro = TimeUnit.SECONDS.toMicros(instant.getEpochSecond()) + (instant.get(ChronoField.MICRO_OF_SECOND)); + return "Date(timeIntervalSince1970: " + String.valueOf(epochMicro) + ".0 / 1_000_000)"; + } else if (ModelUtils.isStringSchema(p)) { + return "\"" + escapeText((String) p.getDefault()) + "\""; + } + // TODO: Handle more cases from `ModelUtils`, such as Date + } + return null; + } + + @Override + public String toInstantiationType(Schema p) { + if (ModelUtils.isMapSchema(p)) { + return getSchemaType(getAdditionalProperties(p)); + } else if (ModelUtils.isArraySchema(p)) { + ArraySchema ap = (ArraySchema) p; + String inner = getSchemaType(ap.getItems()); + return ModelUtils.isSet(p) ? "Set<" + inner + ">" : "[" + inner + "]"; + } + return null; + } + + @Override + public String toApiName(String name) { + if (name.length() == 0) { + return "DefaultAPI"; + } + return camelize(apiNamePrefix + "_" + name) + "API"; + } + + @Override + public String toModelDocFilename(String name) { + return toModelName(name); + } + + @Override + public String toApiDocFilename(String name) { + return toApiName(name); + } + + @Override + public String toOperationId(String operationId) { + operationId = camelize(sanitizeName(operationId), true); + + // Throw exception if method name is empty. + // This should not happen but keep the check just in case + if (StringUtils.isEmpty(operationId)) { + throw new RuntimeException("Empty method name (operationId) not allowed"); + } + + // method name cannot use reserved keyword, e.g. return + if (isReservedWord(operationId)) { + String newOperationId = camelize(("call_" + operationId), true); + LOGGER.warn("{} (reserved word) cannot be used as method name. Renamed to {}", operationId, newOperationId); + return newOperationId; + } + + // operationId starts with a number + if (operationId.matches("^\\d.*")) { + LOGGER.warn("{} (starting with a number) cannot be used as method name. Renamed to {}", operationId, camelize(sanitizeName("call_" + operationId), true)); + operationId = camelize(sanitizeName("call_" + operationId), true); + } + + + return operationId; + } + + @Override + public String toVarName(String name) { + // sanitize name + name = sanitizeName(name); + + // if it's all upper case, do nothing + if (name.matches("^[A-Z_]*$")) { + return name; + } + + // camelize the variable name + // pet_id => petId + name = camelize(name, true); + + // for reserved words surround with `` or append _ + if (isReservedWord(name)) { + name = escapeReservedWord(name); + } + + // for words starting with number, append _ + if (name.matches("^\\d.*")) { + name = "_" + name; + } + + return name; + } + + @Override + public String toParamName(String name) { + // sanitize name + name = sanitizeName(name); + + // replace - with _ e.g. created-at => created_at + name = name.replaceAll("-", "_"); + + // if it's all upper case, do nothing + if (name.matches("^[A-Z_]*$")) { + return name; + } + + // camelize(lower) the variable name + // pet_id => petId + name = camelize(name, true); + + // for reserved words surround with `` + if (isReservedWord(name)) { + name = escapeReservedWord(name); + } + + // for words starting with number, append _ + if (name.matches("^\\d.*")) { + name = "_" + name; + } + + return name; + } + + @Override + public CodegenModel fromModel(String name, Schema model) { + Map allDefinitions = ModelUtils.getSchemas(this.openAPI); + CodegenModel codegenModel = super.fromModel(name, model); + if (codegenModel.description != null) { + codegenModel.imports.add("ApiModel"); + } + if (allDefinitions != null) { + String parentSchema = codegenModel.parentSchema; + + // multilevel inheritance: reconcile properties of all the parents + while (parentSchema != null) { + final Schema parentModel = allDefinitions.get(parentSchema); + final CodegenModel parentCodegenModel = super.fromModel(codegenModel.parent, + parentModel); + codegenModel = SwiftAltClientCodegen.reconcileProperties(codegenModel, parentCodegenModel); + + // get the next parent + parentSchema = parentCodegenModel.parentSchema; + } + } + return codegenModel; + } + + public void setProjectName(String projectName) { + this.projectName = projectName; + } + public void setSwiftPackagePath(String swiftPackagePath) { + this.swiftPackagePath = swiftPackagePath; + } + + @Override + public String toEnumValue(String value, String datatype) { + // for string, array of string + if ("String".equals(datatype) || "[String]".equals(datatype) || "[String: String]".equals(datatype)) { + return "\"" + String.valueOf(value) + "\""; + } else { + return String.valueOf(value); + } + } + + @Override + public String toEnumDefaultValue(String value, String datatype) { + return datatype + "_" + value; + } + + @Override + public String toEnumVarName(String name, String datatype) { + if (name.length() == 0) { + return "empty"; + } + + Pattern startWithNumberPattern = Pattern.compile("^\\d+"); + Matcher startWithNumberMatcher = startWithNumberPattern.matcher(name); + if (startWithNumberMatcher.find()) { + String startingNumbers = startWithNumberMatcher.group(0); + String nameWithoutStartingNumbers = name.substring(startingNumbers.length()); + + return "_" + startingNumbers + camelize(nameWithoutStartingNumbers, true); + } + + // for symbol, e.g. $, # + if (getSymbolName(name) != null) { + return camelize(WordUtils.capitalizeFully(getSymbolName(name).toUpperCase(Locale.ROOT)), true); + } + + // Camelize only when we have a structure defined below + Boolean camelized = false; + if (name.matches("[A-Z][a-z0-9]+[a-zA-Z0-9]*")) { + name = camelize(name, true); + camelized = true; + } + + // Reserved Name + String nameLowercase = StringUtils.lowerCase(name); + if (isReservedWord(nameLowercase)) { + return escapeReservedWord(nameLowercase); + } + + // Check for numerical conversions + if ("Int".equals(datatype) || "Int32".equals(datatype) || "Int64".equals(datatype) + || "Float".equals(datatype) || "Double".equals(datatype)) { + String varName = "number" + camelize(name); + varName = varName.replaceAll("-", "minus"); + varName = varName.replaceAll("\\+", "plus"); + varName = varName.replaceAll("\\.", "dot"); + return varName; + } + + // If we have already camelized the word, don't progress + // any further + if (camelized) { + return name; + } + + char[] separators = {'-', '_', ' ', ':', '(', ')'}; + return camelize(WordUtils.capitalizeFully(StringUtils.lowerCase(name), separators) + .replaceAll("[-_ :\\(\\)]", ""), + true); + } + + @Override + public String toEnumName(CodegenProperty property) { + String enumName = toModelName(property.name); + + // Ensure that the enum type doesn't match a reserved word or + // the variable name doesn't match the generated enum type or the + // Swift compiler will generate an error + if (isReservedWord(property.datatypeWithEnum) + || toVarName(property.name).equals(property.datatypeWithEnum)) { + enumName = property.datatypeWithEnum + "Enum"; + } + + // TODO: toModelName already does something for names starting with number, + // so this code is probably never called + if (enumName.matches("\\d.*")) { // starts with number + return "_" + enumName; + } else { + return enumName; + } + } + + @Override + public Map postProcessModels(Map objs) { + Map postProcessedModelsEnum = postProcessModelsEnum(objs); + + // We iterate through the list of models, and also iterate through each of the + // properties for each model. For each property, if: + // + // CodegenProperty.name != CodegenProperty.baseName + // + // then we set + // + // CodegenProperty.vendorExtensions["x-codegen-escaped-property-name"] = true + // + // Also, if any property in the model has x-codegen-escaped-property-name=true, then we mark: + // + // CodegenModel.vendorExtensions["x-codegen-has-escaped-property-names"] = true + // + List models = (List) postProcessedModelsEnum.get("models"); + for (Object _mo : models) { + Map mo = (Map) _mo; + CodegenModel cm = (CodegenModel) mo.get("model"); + boolean modelHasPropertyWithEscapedName = false; + for (CodegenProperty prop : cm.allVars) { + if (!prop.name.equals(prop.baseName)) { + prop.vendorExtensions.put("x-codegen-escaped-property-name", true); + modelHasPropertyWithEscapedName = true; + } + } + if (modelHasPropertyWithEscapedName) { + cm.vendorExtensions.put("x-codegen-has-escaped-property-names", true); + } + } + + return postProcessedModelsEnum; + } + + @Override + public void postProcessModelProperty(CodegenModel model, CodegenProperty property) { + super.postProcessModelProperty(model, property); + + boolean isSwiftScalarType = property.isInteger || property.isLong || property.isFloat + || property.isDouble || property.isBoolean; + if ((!property.required || property.isNullable) && isSwiftScalarType) { + // Optional scalar types like Int?, Int64?, Float?, Double?, and Bool? + // do not translate to Objective-C. So we want to flag those + // properties in case we want to put special code in the templates + // which provide Objective-C compatibility. + property.vendorExtensions.put("x-swift-optional-scalar", true); + } + } + + @Override + public String escapeQuotationMark(String input) { + // remove " to avoid code injection + return input.replace("\"", ""); + } + + @Override + public String escapeUnsafeCharacters(String input) { + return input.replace("*/", "*_/").replace("/*", "/_*"); + } + + @Override + public void postProcessFile(File file, String fileType) { + if (file == null) { + return; + } + String swiftPostProcessFile = System.getenv("SWIFT_POST_PROCESS_FILE"); + if (StringUtils.isEmpty(swiftPostProcessFile)) { + return; // skip if SWIFT_POST_PROCESS_FILE env variable is not defined + } + // only process files with swift extension + if ("swift".equals(FilenameUtils.getExtension(file.toString()))) { + String command = swiftPostProcessFile + " " + file.toString(); + try { + Process p = Runtime.getRuntime().exec(command); + int exitValue = p.waitFor(); + if (exitValue != 0) { + LOGGER.error("Error running the command ({}). Exit value: {}", command, exitValue); + } else { + LOGGER.info("Successfully executed: {}", command); + } + } catch (InterruptedException | IOException e) { + LOGGER.error("Error running the command ({}). Exception: {}", command, e.getMessage()); + // Restore interrupted state + Thread.currentThread().interrupt(); + } + } + } + + @Override + public Map postProcessOperationsWithModels(Map objs, List allModels) { + Map objectMap = (Map) objs.get("operations"); + + HashMap modelMaps = new HashMap(); + for (Object o : allModels) { + HashMap h = (HashMap) o; + CodegenModel m = (CodegenModel) h.get("model"); + modelMaps.put(m.classname, m); + } + + List operations = (List) objectMap.get("operation"); + for (CodegenOperation operation : operations) { + for (CodegenParameter cp : operation.allParams) { + cp.vendorExtensions.put("x-swift-example", constructExampleCode(cp, modelMaps, new HashSet())); + } + } + return objs; + } + + public String constructExampleCode(CodegenParameter codegenParameter, HashMap modelMaps, Set visitedModels) { + if (codegenParameter.isArray) { // array + return "[" + constructExampleCode(codegenParameter.items, modelMaps, visitedModels) + "]"; + } else if (codegenParameter.isMap) { // TODO: map, file type + return "\"TODO\""; + } else if (languageSpecificPrimitives.contains(codegenParameter.dataType)) { // primitive type + if ("String".equals(codegenParameter.dataType) || "Character".equals(codegenParameter.dataType)) { + if (StringUtils.isEmpty(codegenParameter.example)) { + return "\"" + codegenParameter.example + "\""; + } else { + return "\"" + codegenParameter.paramName + "_example\""; + } + } else if ("Bool".equals(codegenParameter.dataType)) { // boolean + if (Boolean.parseBoolean(codegenParameter.example)) { + return "true"; + } else { + return "false"; + } + } else if ("URL".equals(codegenParameter.dataType)) { // URL + return "URL(string: \"https://example.com\")!"; + } else if ("Data".equals(codegenParameter.dataType)) { // URL + return "Data([9, 8, 7])"; + } else if ("Date".equals(codegenParameter.dataType)) { // date + return "Date()"; + } else { // numeric + if (StringUtils.isEmpty(codegenParameter.example)) { + return codegenParameter.example; + } else { + return "987"; + } + } + } else { // model + // look up the model + if (modelMaps.containsKey(codegenParameter.dataType)) { + if (visitedModels.contains(codegenParameter.dataType)) { + // recursive/self-referencing model, simply return nil to avoid stackoverflow + return "nil"; + } else { + visitedModels.add(codegenParameter.dataType); + return constructExampleCode(modelMaps.get(codegenParameter.dataType), modelMaps, visitedModels); + } + } else { + //LOGGER.error("Error in constructing examples. Failed to look up the model " + codegenParameter.dataType); + return "TODO"; + } + } + } + + public String constructExampleCode(CodegenProperty codegenProperty, HashMap modelMaps, Set visitedModels) { + if (codegenProperty.isArray) { // array + return "[" + constructExampleCode(codegenProperty.items, modelMaps, visitedModels) + "]"; + } else if (codegenProperty.isMap) { // TODO: map, file type + return "\"TODO\""; + } else if (languageSpecificPrimitives.contains(codegenProperty.dataType)) { // primitive type + if ("String".equals(codegenProperty.dataType) || "Character".equals(codegenProperty.dataType)) { + if (StringUtils.isEmpty(codegenProperty.example)) { + return "\"" + codegenProperty.example + "\""; + } else { + return "\"" + codegenProperty.name + "_example\""; + } + } else if ("Bool".equals(codegenProperty.dataType)) { // boolean + if (Boolean.parseBoolean(codegenProperty.example)) { + return "true"; + } else { + return "false"; + } + } else if ("URL".equals(codegenProperty.dataType)) { // URL + return "URL(string: \"https://example.com\")!"; + } else if ("Date".equals(codegenProperty.dataType)) { // date + return "Date()"; + } else { // numeric + if (StringUtils.isEmpty(codegenProperty.example)) { + return codegenProperty.example; + } else { + return "123"; + } + } + } else { + // look up the model + if (modelMaps.containsKey(codegenProperty.dataType)) { + if (visitedModels.contains(codegenProperty.dataType)) { + // recursive/self-referencing model, simply return nil to avoid stackoverflow + return "nil"; + } else { + visitedModels.add(codegenProperty.dataType); + return constructExampleCode(modelMaps.get(codegenProperty.dataType), modelMaps, visitedModels); + } + } else { + //LOGGER.error("Error in constructing examples. Failed to look up the model " + codegenProperty.dataType); + return "\"TODO\""; + } + } + } + + public String constructExampleCode(CodegenModel codegenModel, HashMap modelMaps, Set visitedModels) { + String example; + example = codegenModel.name + "("; + List propertyExamples = new ArrayList<>(); + for (CodegenProperty codegenProperty : codegenModel.vars) { + propertyExamples.add(codegenProperty.name + ": " + constructExampleCode(codegenProperty, modelMaps, visitedModels)); + } + example += StringUtils.join(propertyExamples, ", "); + example += ")"; + return example; + } + + @Override + public void postProcess() { + System.out.println("################################################################################"); + System.out.println("# Thanks for using OpenAPI Generator. #"); + System.out.println("# swift alternative generator #"); + System.out.println("################################################################################"); } } diff --git a/modules/openapi-generator/src/main/resources/swift-alt/APIHelper.mustache b/modules/openapi-generator/src/main/resources/swift-alt/APIHelper.mustache new file mode 100644 index 000000000000..e535c7df4c44 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/swift-alt/APIHelper.mustache @@ -0,0 +1,72 @@ +// APIHelper.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation{{#useVapor}} +import Vapor{{/useVapor}} + +{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} struct APIHelper { + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} static func rejectNil(_ source: [String: Any?]) -> [String: Any]? { + let destination = source.reduce(into: [String: Any]()) { result, item in + if let value = item.value { + result[item.key] = value + } + } + + if destination.isEmpty { + return nil + } + return destination + } + + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} static func rejectNilHeaders(_ source: [String: Any?]) -> [String: String] { + return source.reduce(into: [String: String]()) { result, item in + if let collection = item.value as? [Any?] { + result[item.key] = collection.filter { $0 != nil }.map { "\($0!)" }.joined(separator: ",") + } else if let value: Any = item.value { + result[item.key] = "\(value)" + } + } + } + + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} static func convertBoolToString(_ source: [String: Any]?) -> [String: Any]? { + guard let source = source else { + return nil + } + + return source.reduce(into: [String: Any]()) { result, item in + switch item.value { + case let x as Bool: + result[item.key] = x.description + default: + result[item.key] = item.value + } + } + } + + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} static func mapValueToPathItem(_ source: Any) -> Any { + if let collection = source as? [Any?] { + return collection.filter { $0 != nil }.map { "\($0!)" }.joined(separator: ",") + } + return source + } + + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} static func mapValuesToQueryItems(_ source: [String: Any?]) -> [URLQueryItem]? { + let destination = source.filter { $0.value != nil }.reduce(into: [URLQueryItem]()) { result, item in + if let collection = item.value as? [Any?] { + collection.filter { $0 != nil }.map { "\($0!)" }.forEach { value in + result.append(URLQueryItem(name: item.key, value: value)) + } + } else if let value = item.value { + result.append(URLQueryItem(name: item.key, value: "\(value)")) + } + } + + if destination.isEmpty { + return nil + } + return destination + } +} diff --git a/modules/openapi-generator/src/main/resources/swift-alt/APIs.mustache b/modules/openapi-generator/src/main/resources/swift-alt/APIs.mustache new file mode 100644 index 000000000000..88a2b21b6dc7 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/swift-alt/APIs.mustache @@ -0,0 +1,68 @@ +// APIs.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + +{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class {{projectName}}API { + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} static var basePath = "{{{basePath}}}" + {{#useVapor}} + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} static var customHeaders: HTTPHeaders = [:] + {{/useVapor}} + {{^useVapor}} + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} static var customHeaders: [String: String] = [:] + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} static var credential: URLCredential?{{#useAlamofire}} + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} static var requestBuilderFactory: RequestBuilderFactory = AlamofireRequestBuilderFactory(){{/useAlamofire}}{{#useURLSession}} + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} static var requestBuilderFactory: RequestBuilderFactory = URLSessionRequestBuilderFactory(){{/useURLSession}} + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} static var apiResponseQueue: DispatchQueue = .main + {{/useVapor}} +}{{^useVapor}} + +{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class RequestBuilder { + var credential: URLCredential? + var headers: [String: String] + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} let parameters: [String: Any]? + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} let method: String + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} let URLString: String + + /// Optional block to obtain a reference to the request's progress instance when available.{{#useURLSession}} + /// With the URLSession http client the request's progress only works on iOS 11.0, macOS 10.13, macCatalyst 13.0, tvOS 11.0, watchOS 4.0. + /// If you need to get the request's progress in older OS versions, please use Alamofire http client.{{/useURLSession}} + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var onProgressReady: ((Progress) -> Void)? + + required {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} init(method: String, URLString: String, parameters: [String: Any]?, headers: [String: String] = [:]) { + self.method = method + self.URLString = URLString + self.parameters = parameters + self.headers = headers + + addHeaders({{projectName}}API.customHeaders) + } + + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} func addHeaders(_ aHeaders: [String: String]) { + for (header, value) in aHeaders { + headers[header] = value + } + } + + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} func execute(_ apiResponseQueue: DispatchQueue = {{projectName}}API.apiResponseQueue, _ completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { } + + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} func addHeader(name: String, value: String) -> Self { + if !value.isEmpty { + headers[name] = value + } + return self + } + + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} func addCredential() -> Self { + credential = {{projectName}}API.credential + return self + } +} + +{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} protocol RequestBuilderFactory { + func getNonDecodableBuilder() -> RequestBuilder.Type + func getBuilder() -> RequestBuilder.Type +}{{/useVapor}} diff --git a/modules/openapi-generator/src/main/resources/swift-alt/CodableHelper.mustache b/modules/openapi-generator/src/main/resources/swift-alt/CodableHelper.mustache new file mode 100644 index 000000000000..554418a5ee6d --- /dev/null +++ b/modules/openapi-generator/src/main/resources/swift-alt/CodableHelper.mustache @@ -0,0 +1,49 @@ +// +// CodableHelper.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + +{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class CodableHelper { + private static var customDateFormatter: DateFormatter? + private static var defaultDateFormatter: DateFormatter = OpenISO8601DateFormatter() + + private static var customJSONDecoder: JSONDecoder? + private static var defaultJSONDecoder: JSONDecoder = { + let decoder = JSONDecoder() + decoder.dateDecodingStrategy = .formatted(CodableHelper.dateFormatter) + return decoder + }() + + private static var customJSONEncoder: JSONEncoder? + private static var defaultJSONEncoder: JSONEncoder = { + let encoder = JSONEncoder() + encoder.dateEncodingStrategy = .formatted(CodableHelper.dateFormatter) + encoder.outputFormatting = .prettyPrinted + return encoder + }() + + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} static var dateFormatter: DateFormatter { + get { return customDateFormatter ?? defaultDateFormatter } + set { customDateFormatter = newValue } + } + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} static var jsonDecoder: JSONDecoder { + get { return customJSONDecoder ?? defaultJSONDecoder } + set { customJSONDecoder = newValue } + } + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} static var jsonEncoder: JSONEncoder { + get { return customJSONEncoder ?? defaultJSONEncoder } + set { customJSONEncoder = newValue } + } + + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class func decode(_ type: T.Type, from data: Data) -> Swift.Result where T: Decodable { + return Swift.Result { try jsonDecoder.decode(type, from: data) } + } + + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class func encode(_ value: T) -> Swift.Result where T: Encodable { + return Swift.Result { try jsonEncoder.encode(value) } + } +} diff --git a/modules/openapi-generator/src/main/resources/swift-alt/Configuration.mustache b/modules/openapi-generator/src/main/resources/swift-alt/Configuration.mustache new file mode 100644 index 000000000000..d563d11b4acd --- /dev/null +++ b/modules/openapi-generator/src/main/resources/swift-alt/Configuration.mustache @@ -0,0 +1,28 @@ +// Configuration.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation{{#useVapor}} +import Vapor{{/useVapor}} + +{{#swiftUseApiNamespace}} +@available(*, deprecated, renamed: "{{projectName}}API.Configuration") +{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} typealias Configuration = {{projectName}}API.Configuration + +extension {{projectName}}API { +{{/swiftUseApiNamespace}} +{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class Configuration { + {{#useVapor}}{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} static var apiClient: Vapor.Client? = nil + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} static var apiWrapper: (inout Vapor.ClientRequest) throws -> () = { _ in } + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} static var contentConfiguration = ContentConfiguration.default(){{/useVapor}}{{^useVapor}} + // This value is used to configure the date formatter that is used to serialize dates into JSON format. + // You must set it prior to encoding any dates, and it will only be read once. + @available(*, unavailable, message: "To set a different date format, use CodableHelper.dateFormatter instead.") + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} static var dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"{{/useVapor}} +} +{{#swiftUseApiNamespace}} +} + +{{/swiftUseApiNamespace}} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/swift-alt/Extensions.mustache b/modules/openapi-generator/src/main/resources/swift-alt/Extensions.mustache new file mode 100644 index 000000000000..7f5d8b582f7e --- /dev/null +++ b/modules/openapi-generator/src/main/resources/swift-alt/Extensions.mustache @@ -0,0 +1,238 @@ +// Extensions.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation +#if canImport(AnyCodable) +import AnyCodable +#endif{{#usePromiseKit}} +import PromiseKit{{/usePromiseKit}}{{#useVapor}} +import Vapor{{/useVapor}}{{^useVapor}} + +extension Bool: JSONEncodable { + func encodeToJSON() -> Any { return self as Any } +} + +extension Float: JSONEncodable { + func encodeToJSON() -> Any { return self as Any } +} + +extension Int: JSONEncodable { + func encodeToJSON() -> Any { return self as Any } +} + +extension Int32: JSONEncodable { + func encodeToJSON() -> Any { return NSNumber(value: self as Int32) } +} + +extension Int64: JSONEncodable { + func encodeToJSON() -> Any { return NSNumber(value: self as Int64) } +} + +extension Double: JSONEncodable { + func encodeToJSON() -> Any { return self as Any } +} + +extension String: JSONEncodable { + func encodeToJSON() -> Any { return self as Any } +} + +extension RawRepresentable where RawValue: JSONEncodable { + func encodeToJSON() -> Any { return self.rawValue as Any } +} + +private func encodeIfPossible(_ object: T) -> Any { + if let encodableObject = object as? JSONEncodable { + return encodableObject.encodeToJSON() + } else { + return object as Any + } +} + +extension Array: JSONEncodable { + func encodeToJSON() -> Any { + return self.map(encodeIfPossible) + } +} + +extension Set: JSONEncodable { + func encodeToJSON() -> Any { + return Array(self).encodeToJSON() + } +} + +extension Dictionary: JSONEncodable { + func encodeToJSON() -> Any { + var dictionary = [AnyHashable: Any]() + for (key, value) in self { + dictionary[key] = encodeIfPossible(value) + } + return dictionary as Any + } +} + +extension Data: JSONEncodable { + func encodeToJSON() -> Any { + return self.base64EncodedString(options: Data.Base64EncodingOptions()) + } +} + +extension Date: JSONEncodable { + func encodeToJSON() -> Any { + return CodableHelper.dateFormatter.string(from: self) as Any + } +} + +extension URL: JSONEncodable { + func encodeToJSON() -> Any { + return self + } +} + +extension UUID: JSONEncodable { + func encodeToJSON() -> Any { + return self.uuidString + } +}{{/useVapor}}{{#generateModelAdditionalProperties}} + +extension String: CodingKey { + + public var stringValue: String { + return self + } + + public init?(stringValue: String) { + self.init(stringLiteral: stringValue) + } + + public var intValue: Int? { + return nil + } + + public init?(intValue: Int) { + return nil + } + +} + +extension KeyedEncodingContainerProtocol { + + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} mutating func encodeArray(_ values: [T], forKey key: Self.Key) throws where T: Encodable { + var arrayContainer = nestedUnkeyedContainer(forKey: key) + try arrayContainer.encode(contentsOf: values) + } + + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} mutating func encodeArrayIfPresent(_ values: [T]?, forKey key: Self.Key) throws where T: Encodable { + if let values = values { + try encodeArray(values, forKey: key) + } + } + + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} mutating func encodeMap(_ pairs: [Self.Key: T]) throws where T: Encodable { + for (key, value) in pairs { + try encode(value, forKey: key) + } + } + + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} mutating func encodeMapIfPresent(_ pairs: [Self.Key: T]?) throws where T: Encodable { + if let pairs = pairs { + try encodeMap(pairs) + } + } + +} + +extension KeyedDecodingContainerProtocol { + + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} func decodeArray(_ type: T.Type, forKey key: Self.Key) throws -> [T] where T: Decodable { + var tmpArray = [T]() + + var nestedContainer = try nestedUnkeyedContainer(forKey: key) + while !nestedContainer.isAtEnd { + let arrayValue = try nestedContainer.decode(T.self) + tmpArray.append(arrayValue) + } + + return tmpArray + } + + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} func decodeArrayIfPresent(_ type: T.Type, forKey key: Self.Key) throws -> [T]? where T: Decodable { + var tmpArray: [T]? + + if contains(key) { + tmpArray = try decodeArray(T.self, forKey: key) + } + + return tmpArray + } + + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} func decodeMap(_ type: T.Type, excludedKeys: Set) throws -> [Self.Key: T] where T: Decodable { + var map: [Self.Key: T] = [:] + + for key in allKeys { + if !excludedKeys.contains(key) { + let value = try decode(T.self, forKey: key) + map[key] = value + } + } + + return map + } + +}{{/generateModelAdditionalProperties}}{{^useVapor}} + +extension HTTPURLResponse { + var isStatusCodeSuccessful: Bool { + return Array(200 ..< 300).contains(statusCode) + } +}{{/useVapor}}{{#usePromiseKit}} + +extension RequestBuilder { + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} func execute() -> Promise> { + let deferred = Promise>.pending() + self.execute { result in + switch result { + case let .success(response): + deferred.resolver.fulfill(response) + case let .failure(error): + deferred.resolver.reject(error) + } + } + return deferred.promise + } +}{{/usePromiseKit}}{{#useVapor}} + +extension UUID: Content { } + +extension URL: Content { } + +extension Bool: Content { } + +extension Set: ResponseEncodable where Element: Content { + public func encodeResponse(for request: Vapor.Request) -> EventLoopFuture { + let response = Vapor.Response() + do { + try response.content.encode(Array(self)) + } catch { + return request.eventLoop.makeFailedFuture(error) + } + return request.eventLoop.makeSucceededFuture(response) + } +} + +extension Set: RequestDecodable where Element: Content { + public static func decodeRequest(_ request: Vapor.Request) -> EventLoopFuture { + do { + let content = try request.content.decode([Element].self) + return request.eventLoop.makeSucceededFuture(Set(content)) + } catch { + return request.eventLoop.makeFailedFuture(error) + } + } +} + +extension Set: Content where Element: Content { } + +extension AnyCodable: Content {}{{/useVapor}} diff --git a/modules/openapi-generator/src/main/resources/swift-alt/JSONDataEncoding.mustache b/modules/openapi-generator/src/main/resources/swift-alt/JSONDataEncoding.mustache new file mode 100644 index 000000000000..e227058129b5 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/swift-alt/JSONDataEncoding.mustache @@ -0,0 +1,53 @@ +// +// JSONDataEncoding.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + +{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} struct JSONDataEncoding { + + // MARK: Properties + + private static let jsonDataKey = "jsonData" + + // MARK: Encoding + + /// Creates a URL request by encoding parameters and applying them onto an existing request. + /// + /// - parameter urlRequest: The request to have parameters applied. + /// - parameter parameters: The parameters to apply. This should have a single key/value + /// pair with "jsonData" as the key and a Data object as the value. + /// + /// - throws: An `Error` if the encoding process encounters an error. + /// + /// - returns: The encoded request. + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} func encode(_ urlRequest: URLRequest, with parameters: [String: Any]?) -> URLRequest { + var urlRequest = urlRequest + + guard let jsonData = parameters?[JSONDataEncoding.jsonDataKey] as? Data, !jsonData.isEmpty else { + return urlRequest + } + + if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil { + urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type") + } + + urlRequest.httpBody = jsonData + + return urlRequest + } + + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} static func encodingParameters(jsonData: Data?) -> [String: Any]? { + var returnedParams: [String: Any]? + if let jsonData = jsonData, !jsonData.isEmpty { + var params: [String: Any] = [:] + params[jsonDataKey] = jsonData + returnedParams = params + } + return returnedParams + } + +} diff --git a/modules/openapi-generator/src/main/resources/swift-alt/JSONEncodingHelper.mustache b/modules/openapi-generator/src/main/resources/swift-alt/JSONEncodingHelper.mustache new file mode 100644 index 000000000000..0eae73e1b39d --- /dev/null +++ b/modules/openapi-generator/src/main/resources/swift-alt/JSONEncodingHelper.mustache @@ -0,0 +1,45 @@ +// +// JSONEncodingHelper.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + +{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class JSONEncodingHelper { + + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class func encodingParameters(forEncodableObject encodableObj: T?) -> [String: Any]? { + var params: [String: Any]? + + // Encode the Encodable object + if let encodableObj = encodableObj { + let encodeResult = CodableHelper.encode(encodableObj) + do { + let data = try encodeResult.get() + params = JSONDataEncoding.encodingParameters(jsonData: data) + } catch { + print(error.localizedDescription) + } + } + + return params + } + + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class func encodingParameters(forEncodableObject encodableObj: Any?) -> [String: Any]? { + var params: [String: Any]? + + if let encodableObj = encodableObj { + do { + let data = try JSONSerialization.data(withJSONObject: encodableObj, options: .prettyPrinted) + params = JSONDataEncoding.encodingParameters(jsonData: data) + } catch { + print(error.localizedDescription) + return nil + } + } + + return params + } + +} diff --git a/modules/openapi-generator/src/main/resources/swift-alt/Models.mustache b/modules/openapi-generator/src/main/resources/swift-alt/Models.mustache new file mode 100644 index 000000000000..74ce973b2872 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/swift-alt/Models.mustache @@ -0,0 +1,54 @@ +// Models.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + +protocol JSONEncodable { + func encodeToJSON() -> Any +} + +{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} enum ErrorResponse: Error { + case error(Int, Data?, URLResponse?, Error) +} + +{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} enum DownloadException: Error { + case responseDataMissing + case responseFailed + case requestMissing + case requestMissingPath + case requestMissingURL +} + +{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} enum DecodableRequestBuilderError: Error { + case emptyDataResponse + case nilHTTPResponse + case unsuccessfulHTTPStatusCode + case jsonDecoding(DecodingError) + case generalError(Error) +} + +{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class Response { + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} let statusCode: Int + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} let header: [String: String] + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} let body: T? + + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} init(statusCode: Int, header: [String: String], body: T?) { + self.statusCode = statusCode + self.header = header + self.body = body + } + + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} convenience init(response: HTTPURLResponse, body: T?) { + let rawHeader = response.allHeaderFields + var header = [String: String]() + for (key, value) in rawHeader { + if let key = key.base as? String, let value = value as? String { + header[key] = value + } + } + self.init(statusCode: response.statusCode, header: header, body: body) + } +} diff --git a/modules/openapi-generator/src/main/resources/swift-alt/OpenISO8601DateFormatter.mustache b/modules/openapi-generator/src/main/resources/swift-alt/OpenISO8601DateFormatter.mustache new file mode 100644 index 000000000000..29c28dac3ffb --- /dev/null +++ b/modules/openapi-generator/src/main/resources/swift-alt/OpenISO8601DateFormatter.mustache @@ -0,0 +1,44 @@ +// +// OpenISO8601DateFormatter.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + +// https://stackoverflow.com/a/50281094/976628 +{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} class OpenISO8601DateFormatter: DateFormatter { + static let withoutSeconds: DateFormatter = { + let formatter = DateFormatter() + formatter.calendar = Calendar(identifier: .iso8601) + formatter.locale = Locale(identifier: "en_US_POSIX") + formatter.timeZone = TimeZone(secondsFromGMT: 0) + formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ" + return formatter + }() + + private func setup() { + calendar = Calendar(identifier: .iso8601) + locale = Locale(identifier: "en_US_POSIX") + timeZone = TimeZone(secondsFromGMT: 0) + dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ" + } + + override init() { + super.init() + setup() + } + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + setup() + } + + override {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} func date(from string: String) -> Date? { + if let result = super.date(from: string) { + return result + } + return OpenISO8601DateFormatter.withoutSeconds.date(from: string) + } +} diff --git a/modules/openapi-generator/src/main/resources/swift-alt/Package.swift.mustache b/modules/openapi-generator/src/main/resources/swift-alt/Package.swift.mustache new file mode 100644 index 000000000000..c84db4b5c772 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/swift-alt/Package.swift.mustache @@ -0,0 +1,57 @@ +// swift-tools-version:5.1 + +import PackageDescription + +let package = Package( + name: "{{projectName}}", + platforms: [ + {{#useVapor}} + .macOS(.v10_15), + {{/useVapor}} + {{^useVapor}} + {{#useAlamofire}} + .iOS(.v10), + .macOS(.v10_12), + .tvOS(.v10), + {{/useAlamofire}} + {{^useAlamofire}} + .iOS(.v9), + .macOS(.v10_11), + .tvOS(.v9), + {{/useAlamofire}} + .watchOS(.v3), + {{/useVapor}} + ], + products: [ + // Products define the executables and libraries produced by a package, and make them visible to other packages. + .library( + name: "{{projectName}}", + targets: ["{{projectName}}"] + ), + ], + dependencies: [ + // Dependencies declare other packages that this package depends on. + .package(url: "https://github.com/Flight-School/AnyCodable", from: "0.6.1"), + {{#useAlamofire}} + .package(url: "https://github.com/Alamofire/Alamofire", from: "5.4.3"), + {{/useAlamofire}} + {{#usePromiseKit}} + .package(url: "https://github.com/mxcl/PromiseKit", from: "6.15.3"), + {{/usePromiseKit}} + {{#useRxSwift}} + .package(url: "https://github.com/ReactiveX/RxSwift", from: "6.2.0"), + {{/useRxSwift}} + {{#useVapor}} + .package(url: "https://github.com/vapor/vapor", from: "4.0.0") + {{/useVapor}} + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages which this package depends on. + .target( + name: "{{projectName}}", + dependencies: ["AnyCodable", {{#useVapor}}"Vapor", {{/useVapor}}{{#useAlamofire}}"Alamofire", {{/useAlamofire}}{{#usePromiseKit}}"PromiseKit", {{/usePromiseKit}}{{#useRxSwift}}"RxSwift"{{/useRxSwift}}], + path: "{{swiftPackagePath}}{{^swiftPackagePath}}{{#useSPMFileStructure}}Sources/{{projectName}}{{/useSPMFileStructure}}{{^useSPMFileStructure}}{{projectName}}/Classes{{/useSPMFileStructure}}{{/swiftPackagePath}}" + ), + ] +) diff --git a/modules/openapi-generator/src/main/resources/swift-alt/README.mustache b/modules/openapi-generator/src/main/resources/swift-alt/README.mustache index e69de29bb2d1..ad83e06abc80 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/README.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/README.mustache @@ -0,0 +1,76 @@ +# Swift5 API client for {{{projectName}}} + +{{#appDescriptionWithNewLines}} +{{{.}}} +{{/appDescriptionWithNewLines}} + +## Overview +This API client was generated by the [OpenAPI Generator](https://openapi-generator.tech) project. By using the [openapi-spec](https://github.com/OAI/OpenAPI-Specification) from a remote server, you can easily generate an API client. + +- API version: {{appVersion}} +- Package version: {{packageVersion}} +{{^hideGenerationTimestamp}} +- Build date: {{generatedDate}} +{{/hideGenerationTimestamp}} +- Build package: {{generatorClass}} +{{#infoUrl}} +For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}}) +{{/infoUrl}} + +## Installation + +{{#useVapor}} +Add the following entry in your Package.swift: + +> .package(path: "./{{{projectName}}}") + +{{/useVapor}} +{{^useVapor}} +### Carthage + +Run `carthage update` + +### CocoaPods + +Run `pod install` + +{{/useVapor}}## Documentation for API Endpoints + +All URIs are relative to *{{basePath}}* + +Class | Method | HTTP request | Description +------------ | ------------- | ------------- | ------------- +{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}*{{classname}}* | [**{{operationId}}**]({{apiDocPath}}{{classname}}.md#{{operationIdLowerCase}}) | **{{httpMethod}}** {{path}} | {{summary}} +{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} + +## Documentation For Models + +{{#models}}{{#model}} - [{{{classname}}}]({{modelDocPath}}{{{classname}}}.md) +{{/model}}{{/models}} + +## Documentation For Authorization + +{{^authMethods}} All endpoints do not require authorization. +{{/authMethods}}{{#authMethods}}{{#last}} Authentication schemes defined for the API:{{/last}}{{/authMethods}} +{{#authMethods}}## {{{name}}} + +{{#isApiKey}}- **Type**: API key +- **API key parameter name**: {{{keyParamName}}} +- **Location**: {{#isKeyInQuery}}URL query string{{/isKeyInQuery}}{{#isKeyInHeader}}HTTP header{{/isKeyInHeader}} +{{/isApiKey}} +{{#isBasic}}- **Type**: HTTP basic authentication +{{/isBasic}} +{{#isOAuth}}- **Type**: OAuth +- **Flow**: {{{flow}}} +- **Authorization URL**: {{{authorizationUrl}}} +- **Scopes**: {{^scopes}}N/A{{/scopes}} +{{#scopes}} - **{{{scope}}}**: {{{description}}} +{{/scopes}} +{{/isOAuth}} + +{{/authMethods}} + +## Author + +{{#apiInfo}}{{#apis}}{{#-last}}{{infoEmail}} +{{/-last}}{{/apis}}{{/apiInfo}} diff --git a/modules/openapi-generator/src/main/resources/swift-alt/SynchronizedDictionary.mustache b/modules/openapi-generator/src/main/resources/swift-alt/SynchronizedDictionary.mustache new file mode 100644 index 000000000000..acf7ff4031bd --- /dev/null +++ b/modules/openapi-generator/src/main/resources/swift-alt/SynchronizedDictionary.mustache @@ -0,0 +1,36 @@ +// SynchronizedDictionary.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + +internal struct SynchronizedDictionary { + + private var dictionary = [K: V]() + private let queue = DispatchQueue( + label: "SynchronizedDictionary", + qos: DispatchQoS.userInitiated, + attributes: [DispatchQueue.Attributes.concurrent], + autoreleaseFrequency: DispatchQueue.AutoreleaseFrequency.inherit, + target: nil + ) + + internal subscript(key: K) -> V? { + get { + var value: V? + + queue.sync { + value = self.dictionary[key] + } + + return value + } + set { + queue.sync(flags: DispatchWorkItemFlags.barrier) { + self.dictionary[key] = newValue + } + } + } +} diff --git a/modules/openapi-generator/src/main/resources/swift-alt/XcodeGen.mustache b/modules/openapi-generator/src/main/resources/swift-alt/XcodeGen.mustache new file mode 100644 index 000000000000..31f01b8bedd6 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/swift-alt/XcodeGen.mustache @@ -0,0 +1,18 @@ +name: {{projectName}} +targets: + {{projectName}}: + type: framework + platform: iOS + deploymentTarget: "9.0" + sources: [{{swiftPackagePath}}{{^swiftPackagePath}}{{#useSPMFileStructure}}Sources{{/useSPMFileStructure}}{{^useSPMFileStructure}}{{projectName}}{{/useSPMFileStructure}}{{/swiftPackagePath}}] + info: + path: ./Info.plist + version: {{podVersion}}{{^podVersion}}{{#apiInfo}}{{version}}{{/apiInfo}}{{^apiInfo}}}0.0.1{{/apiInfo}}{{/podVersion}} + settings: + APPLICATION_EXTENSION_API_ONLY: true + scheme: {} + dependencies: + - carthage: AnyCodable{{#useAlamofire}} + - carthage: Alamofire{{/useAlamofire}}{{#usePromiseKit}} + - carthage: PromiseKit{{/usePromiseKit}}{{#useRxSwift}} + - carthage: RxSwift{{/useRxSwift}} diff --git a/modules/openapi-generator/src/main/resources/swift-alt/_param.mustache b/modules/openapi-generator/src/main/resources/swift-alt/_param.mustache new file mode 100644 index 000000000000..770458343aa9 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/swift-alt/_param.mustache @@ -0,0 +1 @@ +"{{baseName}}": {{paramName}}{{^required}}?{{/required}}.encodeToJSON() \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/swift-alt/api.mustache b/modules/openapi-generator/src/main/resources/swift-alt/api.mustache index e69de29bb2d1..9708cffcca11 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/api.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/api.mustache @@ -0,0 +1,559 @@ +{{#operations}}// +// {{classname}}.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation +import Combine +// import Runtime + +{{#description}} +/** {{{.}}} */{{/description}} +open class {{classname}} { + private let transport: Transport + + public init(_ transport: Transport) { + self.transport = transport + } +{{#operation}} + + /** + {{#summary}} + {{{.}}} + {{/summary}} + - {{httpMethod}} {{{path}}}{{#notes}} + - {{{.}}}{{/notes}}{{#subresourceOperation}} + - subresourceOperation: {{.}}{{/subresourceOperation}}{{#defaultResponse}} + - defaultResponse: {{.}}{{/defaultResponse}} + {{#authMethods}} + - {{#isBasic}}BASIC{{/isBasic}}{{#isOAuth}}OAuth{{/isOAuth}}{{#isApiKey}}API Key{{/isApiKey}}: + - type: {{type}}{{#keyParamName}} {{keyParamName}} {{#isKeyInQuery}}(QUERY){{/isKeyInQuery}}{{#isKeyInHeaer}}(HEADER){{/isKeyInHeaer}}{{/keyParamName}} + - name: {{name}} + {{/authMethods}} + {{#hasResponseHeaders}} + - responseHeaders: [{{#responseHeaders}}{{{baseName}}}({{{dataType}}}){{^-last}}, {{/-last}}{{/responseHeaders}}] + {{/hasResponseHeaders}} + {{#externalDocs}} + - externalDocs: {{.}} + {{/externalDocs}} + {{#allParams}} + - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + {{/allParams}} + - returns: Future<{{{returnType}}}{{^returnType}}Void{{/returnType}}, Never> {{description}} + */ + open func {{operationId}}({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}) -> Future<{{{returnType}}}{{^returnType}}Void{{/returnType}}, Never> { + } +{{/operation}} +} +//// + +/** +{{#summary}} + {{{.}}} +{{/summary}} +- {{httpMethod}} {{{path}}}{{#notes}} + - {{{.}}}{{/notes}}{{#subresourceOperation}} + - subresourceOperation: {{.}}{{/subresourceOperation}}{{#defaultResponse}} + - defaultResponse: {{.}}{{/defaultResponse}} +{{#authMethods}} + - {{#isBasic}}BASIC{{/isBasic}}{{#isOAuth}}OAuth{{/isOAuth}}{{#isApiKey}}API Key{{/isApiKey}}: + - type: {{type}}{{#keyParamName}} {{keyParamName}} {{#isKeyInQuery}}(QUERY){{/isKeyInQuery}}{{#isKeyInHeaer}}(HEADER){{/isKeyInHeaer}}{{/keyParamName}} + - name: {{name}} +{{/authMethods}} +{{#hasResponseHeaders}} + - responseHeaders: [{{#responseHeaders}}{{{baseName}}}({{{dataType}}}){{^-last}}, {{/-last}}{{/responseHeaders}}] +{{/hasResponseHeaders}} +{{#externalDocs}} + - externalDocs: {{.}} +{{/externalDocs}} +{{#allParams}} + - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} +{{/allParams}} +- returns: RequestBuilder<{{{returnType}}}{{^returnType}}Void{{/returnType}}> {{description}} + */ +{{#isDeprecated}} + @available(*, deprecated, message: "This operation is deprecated.") +{{/isDeprecated}} +{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class func {{operationId}}WithRequestBuilder({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}) -> RequestBuilder<{{{returnType}}}{{^returnType}}Void{{/returnType}}> { +{{^pathParams}}let{{/pathParams}}{{#pathParams}}{{#-first}}var{{/-first}}{{/pathParams}} localVariablePath = "{{{path}}}"{{#pathParams}} + let {{paramName}}PreEscape = "\({{#isEnum}}{{paramName}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}.rawValue{{/isContainer}}{{/isEnum}}{{^isEnum}}APIHelper.mapValueToPathItem({{paramName}}){{/isEnum}})" + let {{paramName}}PostEscape = {{paramName}}PreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" + localVariablePath = localVariablePath.replacingOccurrences(of: "{{=<% %>=}}{<%baseName%>}<%={{ }}=%>", with: {{paramName}}PostEscape, options: .literal, range: nil){{/pathParams}} + let localVariableURLString = {{projectName}}API.basePath + localVariablePath +{{#bodyParam}} + let localVariableParameters = JSONEncodingHelper.encodingParameters(forEncodableObject: {{paramName}}) +{{/bodyParam}} +{{^bodyParam}} + {{#hasFormParams}} + let localVariableFormParams: [String: Any?] = [ + {{#formParams}} + {{> _param}}, + {{/formParams}} + ] + + let localVariableNonNullParameters = APIHelper.rejectNil(localVariableFormParams) + let localVariableParameters = APIHelper.convertBoolToString(localVariableNonNullParameters) + {{/hasFormParams}} + {{^hasFormParams}} + let localVariableParameters: [String: Any]? = nil + {{/hasFormParams}} +{{/bodyParam}}{{#hasQueryParams}} + var localVariableUrlComponents = URLComponents(string: localVariableURLString) + localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems([{{^queryParams}}:{{/queryParams}} + {{#queryParams}} + {{> _param}}, + {{/queryParams}} + ]){{/hasQueryParams}}{{^hasQueryParams}} + let localVariableUrlComponents = URLComponents(string: localVariableURLString){{/hasQueryParams}} + + let localVariableNillableHeaders: [String: Any?] = [{{^headerParams}}{{^hasFormParams}} + :{{/hasFormParams}}{{/headerParams}}{{#hasFormParams}} + "Content-Type": {{^consumes}}"multipart/form-data"{{/consumes}}{{#consumes.0}}"{{{mediaType}}}"{{/consumes.0}},{{/hasFormParams}}{{#headerParams}} + {{> _param}},{{/headerParams}} + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder<{{{returnType}}}{{^returnType}}Void{{/returnType}}>.Type = {{projectName}}API.requestBuilderFactory.{{#returnType}}getBuilder(){{/returnType}}{{^returnType}}getNonDecodableBuilder(){{/returnType}} + + return localVariableRequestBuilder.init(method: "{{httpMethod}}", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } + +import Foundation{{#usePromiseKit}} +import PromiseKit{{/usePromiseKit}}{{#useRxSwift}} +import RxSwift{{/useRxSwift}}{{#useCombine}} +#if canImport(Combine) +import Combine +#endif{{/useCombine}}{{#useVapor}} +import Vapor{{/useVapor}} +#if canImport(AnyCodable) +import AnyCodable +#endif{{#swiftUseApiNamespace}} + +extension {{projectName}}API { +{{/swiftUseApiNamespace}} + +{{#description}} +/** {{{.}}} */{{/description}} +{{#objcCompatible}}@objc {{/objcCompatible}}{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class {{classname}}{{#objcCompatible}} : NSObject{{/objcCompatible}} { +{{#operation}} + + {{#allParams}} + {{#isEnum}} + /** + * enum for parameter {{paramName}} + */ + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} enum {{enumName}}_{{operationId}}: {{^isContainer}}{{{dataType}}}{{/isContainer}}{{#isContainer}}String{{/isContainer}}, CaseIterable{{#useVapor}}, Content{{/useVapor}} { + {{#allowableValues}} + {{#enumVars}} + case {{name}} = {{{value}}} + {{/enumVars}} + {{/allowableValues}} + } + + {{/isEnum}} + {{/allParams}} +{{^useVapor}} +{{^usePromiseKit}} +{{^useRxSwift}} +{{^useResult}} +{{^useCombine}} +{{^useAsyncAwait}} + /** + {{#summary}} + {{{.}}} + {{/summary}}{{#allParams}} + - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}} + - parameter apiResponseQueue: The queue on which api response is dispatched. + - parameter completion: completion handler to receive the data and the error objects + */ + {{#isDeprecated}} + @available(*, deprecated, message: "This operation is deprecated.") + {{/isDeprecated}} + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class func {{operationId}}({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}apiResponseQueue: DispatchQueue = {{projectName}}API.apiResponseQueue, completion: @escaping ((_ data: {{{returnType}}}{{^returnType}}Void{{/returnType}}?, _ error: Error?) -> Void)) { + {{operationId}}WithRequestBuilder({{#allParams}}{{paramName}}: {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}).execute(apiResponseQueue) { result in + switch result { + {{#returnType}} + case let .success(response): + completion(response.body, nil) + {{/returnType}} + {{^returnType}} + case .success: + completion((), nil) + {{/returnType}} + case let .failure(error): + completion(nil, error) + } + } + } +{{/useAsyncAwait}} +{{/useCombine}} +{{/useResult}} +{{/useRxSwift}} +{{/usePromiseKit}} +{{/useVapor}} +{{#usePromiseKit}} + /** + {{#summary}} + {{{.}}} + {{/summary}}{{#allParams}} + - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}} + - parameter apiResponseQueue: The queue on which api response is dispatched. + - returns: Promise<{{{returnType}}}{{^returnType}}Void{{/returnType}}> + */ + {{#isDeprecated}} + @available(*, deprecated, message: "This operation is deprecated.") + {{/isDeprecated}} + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class func {{operationId}}({{#allParams}} {{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}apiResponseQueue: DispatchQueue = {{projectName}}API.apiResponseQueue) -> Promise<{{{returnType}}}{{^returnType}}Void{{/returnType}}> { + let deferred = Promise<{{{returnType}}}{{^returnType}}Void{{/returnType}}>.pending() + {{operationId}}WithRequestBuilder({{#allParams}}{{paramName}}: {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}).execute(apiResponseQueue) { result in + switch result { + {{#returnType}} + case let .success(response): + deferred.resolver.fulfill(response.body!) + {{/returnType}} + {{^returnType}} + case .success: + deferred.resolver.fulfill(()) + {{/returnType}} + case let .failure(error): + deferred.resolver.reject(error) + } + } + return deferred.promise + } +{{/usePromiseKit}} +{{#useRxSwift}} + /** + {{#summary}} + {{{.}}} + {{/summary}}{{#allParams}} + - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}} + - parameter apiResponseQueue: The queue on which api response is dispatched. + - returns: Observable<{{{returnType}}}{{^returnType}}Void{{/returnType}}> + */ + {{#isDeprecated}} + @available(*, deprecated, message: "This operation is deprecated.") + {{/isDeprecated}} + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class func {{operationId}}({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}apiResponseQueue: DispatchQueue = {{projectName}}API.apiResponseQueue) -> Observable<{{{returnType}}}{{^returnType}}Void{{/returnType}}> { + return Observable.create { observer -> Disposable in + {{operationId}}WithRequestBuilder({{#allParams}}{{paramName}}: {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}).execute(apiResponseQueue) { result in + switch result { + {{#returnType}} + case let .success(response): + observer.onNext(response.body!) + {{/returnType}} + {{^returnType}} + case .success: + observer.onNext(()) + {{/returnType}} + case let .failure(error): + observer.onError(error) + } + observer.onCompleted() + } + return Disposables.create() + } + } +{{/useRxSwift}} +{{#useCombine}} + /** + {{#summary}} + {{{.}}} + {{/summary}}{{#allParams}} + - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}} + - parameter apiResponseQueue: The queue on which api response is dispatched. + - returns: AnyPublisher<{{{returnType}}}{{^returnType}}Void{{/returnType}}, Error> + */ + #if canImport(Combine) + {{#isDeprecated}} + @available(*, deprecated, message: "This operation is deprecated.") + {{/isDeprecated}} + @available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *) + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class func {{operationId}}({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}apiResponseQueue: DispatchQueue = {{projectName}}API.apiResponseQueue) -> AnyPublisher<{{{returnType}}}{{^returnType}}Void{{/returnType}}, Error> { + return Future<{{{returnType}}}{{^returnType}}Void{{/returnType}}, Error> { promise in + {{operationId}}WithRequestBuilder({{#allParams}}{{paramName}}: {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}).execute(apiResponseQueue) { result in + switch result { + {{#returnType}} + case let .success(response): + promise(.success(response.body!)) + {{/returnType}} + {{^returnType}} + case .success: + promise(.success(())) + {{/returnType}} + case let .failure(error): + promise(.failure(error)) + } + } + }.eraseToAnyPublisher() + } + #endif +{{/useCombine}} +{{#useAsyncAwait}} + /** + {{#summary}} + {{{.}}} + {{/summary}}{{#allParams}} + - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}} + - parameter apiResponseQueue: The queue on which api response is dispatched. + - returns: {{{returnType}}}{{^returnType}}Void{{/returnType}} + */ + {{#isDeprecated}} + @available(*, deprecated, message: "This operation is deprecated.") + {{/isDeprecated}} + @available(macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0, *) + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class func {{operationId}}({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}apiResponseQueue: DispatchQueue = {{projectName}}API.apiResponseQueue) async throws{{#returnType}} -> {{{returnType}}}{{/returnType}} { + return try await withCheckedThrowingContinuation { continuation in + {{operationId}}WithRequestBuilder({{#allParams}}{{paramName}}: {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}).execute(apiResponseQueue) { result in + switch result { + {{#returnType}} + case let .success(response): + continuation.resume(returning: response.body!) + {{/returnType}} + {{^returnType}} + case .success: + continuation.resume(returning: ()) + {{/returnType}} + case let .failure(error): + continuation.resume(throwing: error) + } + } + } + } +{{/useAsyncAwait}} +{{#useResult}} + /** + {{#summary}} + {{{.}}} + {{/summary}}{{#allParams}} + - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}} + - parameter apiResponseQueue: The queue on which api response is dispatched. + - parameter completion: completion handler to receive the result + */ + {{#isDeprecated}} + @available(*, deprecated, message: "This operation is deprecated.") + {{/isDeprecated}} + open class func {{operationId}}({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}apiResponseQueue: DispatchQueue = {{projectName}}API.apiResponseQueue, completion: @escaping ((_ result: Swift.Result<{{{returnType}}}{{^returnType}}Void{{/returnType}}, ErrorResponse>) -> Void)) { + {{operationId}}WithRequestBuilder({{#allParams}}{{paramName}}: {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}).execute(apiResponseQueue) { result in + switch result { + {{#returnType}} + case let .success(response): + completion(.success(response.body!)) + {{/returnType}} + {{^returnType}} + case .success: + completion(.success(())) + {{/returnType}} + case let .failure(error): + completion(.failure(error)) + } + } + } +{{/useResult}} +{{#useVapor}} + /** + {{#summary}} + {{{.}}} + {{/summary}} + {{httpMethod}} {{{path}}}{{#notes}} + {{{.}}}{{/notes}}{{#subresourceOperation}} + subresourceOperation: {{.}}{{/subresourceOperation}}{{#defaultResponse}} + defaultResponse: {{.}}{{/defaultResponse}} + {{#authMethods}} + - {{#isBasic}}BASIC{{/isBasic}}{{#isOAuth}}OAuth{{/isOAuth}}{{#isApiKey}}API Key{{/isApiKey}}: + - type: {{type}}{{#keyParamName}} {{keyParamName}} {{#isKeyInQuery}}(QUERY){{/isKeyInQuery}}{{#isKeyInHeaer}}(HEADER){{/isKeyInHeaer}}{{/keyParamName}} + - name: {{name}} + {{/authMethods}} + {{#hasResponseHeaders}} + - responseHeaders: [{{#responseHeaders}}{{{baseName}}}({{{dataType}}}){{^-last}}, {{/-last}}{{/responseHeaders}}] + {{/hasResponseHeaders}} + {{#externalDocs}} + - externalDocs: {{.}} + {{/externalDocs}} + {{#allParams}} + - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{{description}}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + {{/allParams}} + - returns: `EventLoopFuture` of `ClientResponse` {{{description}}} + */ + {{#isDeprecated}} + @available(*, deprecated, message: "This operation is deprecated.") + {{/isDeprecated}} + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class func {{operationId}}Raw({{#allParams}}{{paramName}}: {{#isEnum}}{{#isArray}}[{{enumName}}_{{operationId}}]{{/isArray}}{{^isArray}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isArray}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}headers: HTTPHeaders = {{projectName}}API.customHeaders, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + {{^pathParams}}let{{/pathParams}}{{#pathParams}}{{#-first}}var{{/-first}}{{/pathParams}} localVariablePath = "{{{path}}}"{{#pathParams}} + let {{paramName}}PreEscape = String(describing: {{#isEnum}}{{paramName}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}.rawValue{{/isContainer}}{{/isEnum}}{{^isEnum}}{{paramName}}{{/isEnum}}) + let {{paramName}}PostEscape = {{paramName}}PreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" + localVariablePath = localVariablePath.replacingOccurrences(of: "{{=<% %>=}}{<%baseName%>}<%={{ }}=%>", with: {{paramName}}PostEscape, options: .literal, range: nil){{/pathParams}} + let localVariableURLString = {{projectName}}API.basePath + localVariablePath + + guard let localVariableApiClient = {{#swiftUseApiNamespace}}{{projectName}}API.{{/swiftUseApiNamespace}}Configuration.apiClient else { + fatalError("Configuration.apiClient is not set.") + } + + return localVariableApiClient.send(.{{httpMethod}}, headers: headers, to: URI(string: localVariableURLString)) { localVariableRequest in + try {{#swiftUseApiNamespace}}{{projectName}}API.{{/swiftUseApiNamespace}}Configuration.apiWrapper(&localVariableRequest) + {{#hasHeaderParams}}{{#headerParams}} + localVariableRequest.headers.add(name: "{{baseName}}", value: {{#isArray}}{{paramName}}{{^required}}?{{/required}}.map { $0{{#isEnum}}.rawValue{{/isEnum}}.description }.description{{/isArray}}{{^isArray}}{{#isEnum}}{{paramName}}{{^required}}?{{/required}}.rawValue.description{{/isEnum}}{{^isEnum}}{{paramName}}{{^required}}?{{/required}}.description{{/isEnum}}{{/isArray}}{{^required}} ?? ""{{/required}}) + {{/headerParams}}{{/hasHeaderParams}} + {{#hasQueryParams}}struct QueryParams: Content { + {{#queryParams}} + var {{paramName}}: {{#isEnum}}{{#isArray}}[{{enumName}}_{{operationId}}]{{/isArray}}{{^isArray}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isArray}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}?{{/required}} + {{/queryParams}} + + enum CodingKeys: String, CodingKey { + {{#queryParams}} + case {{paramName}}{{#baseName}} = "{{.}}"{{/baseName}} + {{/queryParams}} + } + } + try localVariableRequest.query.encode(QueryParams({{#queryParams}}{{paramName}}: {{paramName}}{{^-last}}, {{/-last}}{{/queryParams}})){{/hasQueryParams}} + {{#hasBodyParam}} + {{#bodyParam}}{{#required}}{{#isBinary}}localVariableRequest.body = ByteBuffer(data: {{paramName}}){{/isBinary}}{{^isBinary}}{{#isFile}}localVariableRequest.body = ByteBuffer(data: {{paramName}}){{/isFile}}try localVariableRequest.content.encode({{paramName}}, using: Configuration.contentConfiguration.requireEncoder(for: {{{dataType}}}.defaultContentType)){{/isBinary}}{{/required}}{{^required}}if let localVariableBody = {{paramName}} { + {{#isBinary}}localVariableRequest.body = ByteBuffer(data: localVariableBody){{/isBinary}}{{^isBinary}}{{#isFile}}localVariableRequest.body = ByteBuffer(data: localVariableBody){{/isFile}}try localVariableRequest.content.encode(localVariableBody, using: Configuration.contentConfiguration.requireEncoder(for: {{{dataType}}}.defaultContentType)){{/isBinary}} + }{{/required}}{{/bodyParam}} + {{/hasBodyParam}} + {{#hasFormParams}}struct FormParams: Content { + static let defaultContentType = Vapor.HTTPMediaType.formData + {{#formParams}} + var {{paramName}}: {{#isEnum}}{{#isArray}}[{{enumName}}_{{operationId}}]{{/isArray}}{{^isArray}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isArray}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}?{{/required}} + {{/formParams}} + } + try localVariableRequest.content.encode(FormParams({{#formParams}}{{paramName}}: {{paramName}}{{^-last}}, {{/-last}}{{/formParams}}), using: Configuration.contentConfiguration.requireEncoder(for: FormParams.defaultContentType)){{/hasFormParams}} + try beforeSend(&localVariableRequest) + } + } + + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} enum {{#lambda.titlecase}}{{operationId}}{{/lambda.titlecase}} { + {{#responses}} + case http{{code}}({{#dataType}}value: {{{.}}}, {{/dataType}}raw: ClientResponse) + {{/responses}} + {{^hasDefaultResponse}} + case http0(raw: ClientResponse) + {{/hasDefaultResponse}} + } + + /** + {{#summary}} + {{{.}}} + {{/summary}} + {{httpMethod}} {{{path}}}{{#notes}} + {{{.}}}{{/notes}}{{#subresourceOperation}} + subresourceOperation: {{.}}{{/subresourceOperation}}{{#defaultResponse}} + defaultResponse: {{.}}{{/defaultResponse}} + {{#authMethods}} + - {{#isBasic}}BASIC{{/isBasic}}{{#isOAuth}}OAuth{{/isOAuth}}{{#isApiKey}}API Key{{/isApiKey}}: + - type: {{type}}{{#keyParamName}} {{keyParamName}} {{#isKeyInQuery}}(QUERY){{/isKeyInQuery}}{{#isKeyInHeaer}}(HEADER){{/isKeyInHeaer}}{{/keyParamName}} + - name: {{name}} + {{/authMethods}} + {{#hasResponseHeaders}} + - responseHeaders: [{{#responseHeaders}}{{{baseName}}}({{{dataType}}}){{^-last}}, {{/-last}}{{/responseHeaders}}] + {{/hasResponseHeaders}} + {{#externalDocs}} + - externalDocs: {{.}} + {{/externalDocs}} + {{#allParams}} + - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{{description}}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + {{/allParams}} + - returns: `EventLoopFuture` of `{{#lambda.titlecase}}{{operationId}}{{/lambda.titlecase}}` {{{description}}} + */ + {{#isDeprecated}} + @available(*, deprecated, message: "This operation is deprecated.") + {{/isDeprecated}} + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class func {{operationId}}({{#allParams}}{{paramName}}: {{#isEnum}}{{#isArray}}[{{enumName}}_{{operationId}}]{{/isArray}}{{^isArray}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isArray}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}headers: HTTPHeaders = {{projectName}}API.customHeaders, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture<{{#lambda.titlecase}}{{operationId}}{{/lambda.titlecase}}> { + return {{operationId}}Raw({{#allParams}}{{paramName}}: {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}headers: headers, beforeSend: beforeSend).flatMapThrowing { response -> {{#lambda.titlecase}}{{operationId}}{{/lambda.titlecase}} in + switch response.status.code { + {{#responses}} + {{#isDefault}}default{{/isDefault}}{{^isDefault}}case {{code}}{{/isDefault}}: + return .http{{code}}({{#dataType}}value: {{#isBinary}}Data(buffer: response.body ?? ByteBuffer()){{/isBinary}}{{^isBinary}}{{#isFile}}Data(buffer: response.body ?? ByteBuffer()){{/isFile}}{{^isFile}}try response.content.decode({{{dataType}}}.self, using: Configuration.contentConfiguration.requireDecoder(for: {{{dataType}}}.defaultContentType)){{/isFile}}{{/isBinary}}, {{/dataType}}raw: response) + {{/responses}} + {{^hasDefaultResponse}} + default: + return .http0(raw: response) + {{/hasDefaultResponse}} + } + } + } + +{{/useVapor}} +{{^useVapor}} + + /** + {{#summary}} + {{{.}}} + {{/summary}} + - {{httpMethod}} {{{path}}}{{#notes}} + - {{{.}}}{{/notes}}{{#subresourceOperation}} + - subresourceOperation: {{.}}{{/subresourceOperation}}{{#defaultResponse}} + - defaultResponse: {{.}}{{/defaultResponse}} + {{#authMethods}} + - {{#isBasic}}BASIC{{/isBasic}}{{#isOAuth}}OAuth{{/isOAuth}}{{#isApiKey}}API Key{{/isApiKey}}: + - type: {{type}}{{#keyParamName}} {{keyParamName}} {{#isKeyInQuery}}(QUERY){{/isKeyInQuery}}{{#isKeyInHeaer}}(HEADER){{/isKeyInHeaer}}{{/keyParamName}} + - name: {{name}} + {{/authMethods}} + {{#hasResponseHeaders}} + - responseHeaders: [{{#responseHeaders}}{{{baseName}}}({{{dataType}}}){{^-last}}, {{/-last}}{{/responseHeaders}}] + {{/hasResponseHeaders}} + {{#externalDocs}} + - externalDocs: {{.}} + {{/externalDocs}} + {{#allParams}} + - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + {{/allParams}} + - returns: RequestBuilder<{{{returnType}}}{{^returnType}}Void{{/returnType}}> {{description}} + */ + {{#isDeprecated}} + @available(*, deprecated, message: "This operation is deprecated.") + {{/isDeprecated}} + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class func {{operationId}}WithRequestBuilder({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}) -> RequestBuilder<{{{returnType}}}{{^returnType}}Void{{/returnType}}> { + {{^pathParams}}let{{/pathParams}}{{#pathParams}}{{#-first}}var{{/-first}}{{/pathParams}} localVariablePath = "{{{path}}}"{{#pathParams}} + let {{paramName}}PreEscape = "\({{#isEnum}}{{paramName}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}.rawValue{{/isContainer}}{{/isEnum}}{{^isEnum}}APIHelper.mapValueToPathItem({{paramName}}){{/isEnum}})" + let {{paramName}}PostEscape = {{paramName}}PreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" + localVariablePath = localVariablePath.replacingOccurrences(of: "{{=<% %>=}}{<%baseName%>}<%={{ }}=%>", with: {{paramName}}PostEscape, options: .literal, range: nil){{/pathParams}} + let localVariableURLString = {{projectName}}API.basePath + localVariablePath + {{#bodyParam}} + let localVariableParameters = JSONEncodingHelper.encodingParameters(forEncodableObject: {{paramName}}) + {{/bodyParam}} + {{^bodyParam}} + {{#hasFormParams}} + let localVariableFormParams: [String: Any?] = [ + {{#formParams}} + {{> _param}}, + {{/formParams}} + ] + + let localVariableNonNullParameters = APIHelper.rejectNil(localVariableFormParams) + let localVariableParameters = APIHelper.convertBoolToString(localVariableNonNullParameters) + {{/hasFormParams}} + {{^hasFormParams}} + let localVariableParameters: [String: Any]? = nil + {{/hasFormParams}} +{{/bodyParam}}{{#hasQueryParams}} + var localVariableUrlComponents = URLComponents(string: localVariableURLString) + localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems([{{^queryParams}}:{{/queryParams}} + {{#queryParams}} + {{> _param}}, + {{/queryParams}} + ]){{/hasQueryParams}}{{^hasQueryParams}} + let localVariableUrlComponents = URLComponents(string: localVariableURLString){{/hasQueryParams}} + + let localVariableNillableHeaders: [String: Any?] = [{{^headerParams}}{{^hasFormParams}} + :{{/hasFormParams}}{{/headerParams}}{{#hasFormParams}} + "Content-Type": {{^consumes}}"multipart/form-data"{{/consumes}}{{#consumes.0}}"{{{mediaType}}}"{{/consumes.0}},{{/hasFormParams}}{{#headerParams}} + {{> _param}},{{/headerParams}} + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder<{{{returnType}}}{{^returnType}}Void{{/returnType}}>.Type = {{projectName}}API.requestBuilderFactory.{{#returnType}}getBuilder(){{/returnType}}{{^returnType}}getNonDecodableBuilder(){{/returnType}} + + return localVariableRequestBuilder.init(method: "{{httpMethod}}", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } +{{/useVapor}} +{{/operation}} +} +{{#swiftUseApiNamespace}} +} +{{/swiftUseApiNamespace}} +{{/operations}} diff --git a/modules/openapi-generator/src/main/resources/swift-alt/model.mustache b/modules/openapi-generator/src/main/resources/swift-alt/model.mustache index e69de29bb2d1..b006540ffc21 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/model.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/model.mustache @@ -0,0 +1,18 @@ +{{#models}}{{#model}}// +// {{classname}}.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation +#if canImport(AnyCodable) +import AnyCodable +#endif + +{{#description}}/** {{.}} */{{/description}} +{{#vendorExtensions.x-is-one-of-interface}} +{{> modelOneOf}}{{/vendorExtensions.x-is-one-of-interface}}{{^vendorExtensions.x-is-one-of-interface}}{{#isArray}} +{{> modelArray}}{{/isArray}}{{^isArray}}{{#isEnum}} +{{> modelEnum}}{{/isEnum}}{{^isEnum}} +{{> modelObject}}{{/isEnum}}{{/isArray}}{{/vendorExtensions.x-is-one-of-interface}}{{/model}}{{/models}} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/swift-alt/modelArray.mustache b/modules/openapi-generator/src/main/resources/swift-alt/modelArray.mustache new file mode 100644 index 000000000000..843626158cd6 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/swift-alt/modelArray.mustache @@ -0,0 +1 @@ +public typealias {{classname}} = {{parent}} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/swift-alt/modelEnum.mustache b/modules/openapi-generator/src/main/resources/swift-alt/modelEnum.mustache new file mode 100644 index 000000000000..fd9a11330558 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/swift-alt/modelEnum.mustache @@ -0,0 +1,7 @@ +public enum {{classname}}: {{dataType}}, Hashable, Codable, CaseIterable { +{{#allowableValues}} +{{#enumVars}} + case {{{name}}} = {{{value}}} +{{/enumVars}} +{{/allowableValues}} +} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/swift-alt/modelInlineEnumDeclaration.mustache b/modules/openapi-generator/src/main/resources/swift-alt/modelInlineEnumDeclaration.mustache new file mode 100644 index 000000000000..aed8f3629829 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/swift-alt/modelInlineEnumDeclaration.mustache @@ -0,0 +1,7 @@ + public enum {{enumName}}: {{^isContainer}}{{dataType}}{{/isContainer}}{{#isContainer}}String{{/isContainer}}, Hashable, Codable, CaseIterable { + {{#allowableValues}} + {{#enumVars}} + case {{{name}}} = {{{value}}} + {{/enumVars}} + {{/allowableValues}} + } \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/swift-alt/modelObject.mustache b/modules/openapi-generator/src/main/resources/swift-alt/modelObject.mustache new file mode 100644 index 000000000000..f1909aae9208 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/swift-alt/modelObject.mustache @@ -0,0 +1,46 @@ +public struct {{{classname}}}: Codable, Hashable { +{{#allVars}} +{{#isEnum}} +{{> modelInlineEnumDeclaration}} +{{/isEnum}} +{{/allVars}} +{{#allVars}} +{{#isEnum}} + {{#description}}/** {{{.}}} */ + {{/description}}public var {{{name}}}: {{{datatypeWithEnum}}}{{#required}}{{#isNullable}}?{{/isNullable}}{{/required}}{{^required}}?{{/required}}{{#defaultValue}} = {{{.}}}{{/defaultValue}} +{{/isEnum}} +{{^isEnum}} + {{#description}}/** {{{.}}} */ + {{/description}}public var {{{name}}}: {{{datatype}}}{{#required}}{{#isNullable}}?{{/isNullable}}{{/required}}{{^required}}?{{/required}}{{#defaultValue}} = {{{.}}}{{/defaultValue}} +{{/isEnum}} +{{/allVars}} +{{#hasVars}} + + public init({{#allVars}}{{{name}}}: {{{datatypeWithEnum}}}{{#required}}{{#isNullable}}?{{/isNullable}}{{/required}}{{^required}}?{{/required}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}{{^defaultValue}}{{^required}} = nil{{/required}}{{/defaultValue}}{{^-last}}, {{/-last}}{{/allVars}}) { + {{#allVars}} + self.{{{name}}} = {{{name}}} + {{/allVars}} + } +{{/hasVars}} + + public enum CodingKeys: {{#hasVars}}String, {{/hasVars}}CodingKey, CaseIterable { + {{#allVars}} + case {{{name}}}{{#vendorExtensions.x-codegen-escaped-property-name}} = "{{{baseName}}}"{{/vendorExtensions.x-codegen-escaped-property-name}} + {{/allVars}} + } + + // Encodable protocol methods + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + {{#allVars}} + try container.encode{{^required}}IfPresent{{/required}}({{{name}}}, forKey: .{{{name}}}) + {{/allVars}} + {{#generateModelAdditionalProperties}} + {{#additionalPropertiesType}} + var additionalPropertiesContainer = encoder.container(keyedBy: String.self) + try additionalPropertiesContainer.encodeMap(additionalProperties) + {{/additionalPropertiesType}} + {{/generateModelAdditionalProperties}} + } +} diff --git a/modules/openapi-generator/src/main/resources/swift-alt/modelOneOf.mustache b/modules/openapi-generator/src/main/resources/swift-alt/modelOneOf.mustache new file mode 100644 index 000000000000..315373aace5f --- /dev/null +++ b/modules/openapi-generator/src/main/resources/swift-alt/modelOneOf.mustache @@ -0,0 +1,31 @@ +public enum {{classname}}: Codable, Hashable { + {{#oneOf}} + case type{{.}}({{.}}) + {{/oneOf}} + + public func encode(to encoder: Encoder) throws { + var container = encoder.singleValueContainer() + switch self { + {{#oneOf}} + case .type{{.}}(let value): + try container.encode(value) + {{/oneOf}} + } + } + + public init(from decoder: Decoder) throws { + let container = try decoder.singleValueContainer() + {{#oneOf}} + {{#-first}} + if let value = try? container.decode({{.}}.self) { + {{/-first}} + {{^-first}} + } else if let value = try? container.decode({{.}}.self) { + {{/-first}} + self = .type{{.}}(value) + {{/oneOf}} + } else { + throw DecodingError.typeMismatch(Self.Type.self, .init(codingPath: decoder.codingPath, debugDescription: "Unable to decode instance of {{classname}}")) + } + } +} diff --git a/samples/client/petstore/swift/alt/.openapi-generator/FILES b/samples/client/petstore/swift/alt/.openapi-generator/FILES index 0d7c0a4af138..b1f9bb2cd593 100644 --- a/samples/client/petstore/swift/alt/.openapi-generator/FILES +++ b/samples/client/petstore/swift/alt/.openapi-generator/FILES @@ -1,10 +1,11 @@ -Apis/PetApi.swift -Apis/StoreApi.swift -Apis/UserApi.swift -Models/ApiResponse.swift -Models/Category.swift -Models/Order.swift -Models/Pet.swift -Models/Tag.swift -Models/User.swift -README.md +OpenAPIClient/Classes/OpenAPIs/APIs/PetAPI.swift +OpenAPIClient/Classes/OpenAPIs/APIs/StoreAPI.swift +OpenAPIClient/Classes/OpenAPIs/APIs/UserAPI.swift +OpenAPIClient/Classes/OpenAPIs/Models/ApiResponse.swift +OpenAPIClient/Classes/OpenAPIs/Models/Category.swift +OpenAPIClient/Classes/OpenAPIs/Models/Order.swift +OpenAPIClient/Classes/OpenAPIs/Models/Pet.swift +OpenAPIClient/Classes/OpenAPIs/Models/Tag.swift +OpenAPIClient/Classes/OpenAPIs/Models/User.swift +Package.swift +project.yml diff --git a/samples/client/petstore/swift/alt/Apis/PetApi.swift b/samples/client/petstore/swift/alt/Apis/PetApi.swift deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/samples/client/petstore/swift/alt/Apis/StoreApi.swift b/samples/client/petstore/swift/alt/Apis/StoreApi.swift deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/samples/client/petstore/swift/alt/Apis/UserApi.swift b/samples/client/petstore/swift/alt/Apis/UserApi.swift deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/samples/client/petstore/swift/alt/Info.plist b/samples/client/petstore/swift/alt/Info.plist new file mode 100644 index 000000000000..323e5ecfc420 --- /dev/null +++ b/samples/client/petstore/swift/alt/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/samples/client/petstore/swift/alt/Models/ApiResponse.swift b/samples/client/petstore/swift/alt/Models/ApiResponse.swift deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/samples/client/petstore/swift/alt/Models/Category.swift b/samples/client/petstore/swift/alt/Models/Category.swift deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/samples/client/petstore/swift/alt/Models/Order.swift b/samples/client/petstore/swift/alt/Models/Order.swift deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/samples/client/petstore/swift/alt/Models/Pet.swift b/samples/client/petstore/swift/alt/Models/Pet.swift deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/samples/client/petstore/swift/alt/Models/Tag.swift b/samples/client/petstore/swift/alt/Models/Tag.swift deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/samples/client/petstore/swift/alt/Models/User.swift b/samples/client/petstore/swift/alt/Models/User.swift deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/samples/client/petstore/swift/alt/OpenAPIClient.xcodeproj/project.pbxproj b/samples/client/petstore/swift/alt/OpenAPIClient.xcodeproj/project.pbxproj new file mode 100644 index 000000000000..aa50ef688273 --- /dev/null +++ b/samples/client/petstore/swift/alt/OpenAPIClient.xcodeproj/project.pbxproj @@ -0,0 +1,395 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 51; + objects = { + +/* Begin PBXBuildFile section */ + 07AD66F44F142A25134285D2 /* Tag.swift in Sources */ = {isa = PBXBuildFile; fileRef = 004F49F830DBCE73EE547625 /* Tag.swift */; }; + 2BD3B8D12727080900E16037 /* Runtime.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2BD3B8D02727080900E16037 /* Runtime.swift */; }; + 5FDB83D7EF01DBFD3E8B6AD6 /* ApiResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F0D02E61CF4C58B24BC1581 /* ApiResponse.swift */; }; + 615F8910ABA037FBFA0BC09F /* User.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA84FDE7CC165FCEDC532CE0 /* User.swift */; }; + 8BB28EBA3F247E1FC0AEB946 /* Pet.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6443F80E261022596B8ABA4 /* Pet.swift */; }; + B3B33292169982AB380577B9 /* Category.swift in Sources */ = {isa = PBXBuildFile; fileRef = E99367F9F7013FFD55123670 /* Category.swift */; }; + D2051AFBDBA23137A85FCA3B /* Order.swift in Sources */ = {isa = PBXBuildFile; fileRef = 557E9F1F7D8EE8697FFC77CA /* Order.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 004F49F830DBCE73EE547625 /* Tag.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tag.swift; sourceTree = ""; }; + 2BD3B8D02727080900E16037 /* Runtime.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Runtime.swift; path = "../../../../../../../../../wallet-client-ios/Runtime.swift"; sourceTree = ""; }; + 2BD3B8D327270A5E00E16037 /* PetAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PetAPI.swift; sourceTree = ""; }; + 2BD3B8D427270A5E00E16037 /* UserAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAPI.swift; sourceTree = ""; }; + 2BD3B8D527270A5E00E16037 /* StoreAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoreAPI.swift; sourceTree = ""; }; + 557E9F1F7D8EE8697FFC77CA /* Order.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Order.swift; sourceTree = ""; }; + 5A68201A010940B069E402C4 /* OpenAPIClient.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = OpenAPIClient.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 7F0D02E61CF4C58B24BC1581 /* ApiResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApiResponse.swift; sourceTree = ""; }; + 804F7195C2469F7D77EEA124 /* AnyCodable.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = AnyCodable.framework; sourceTree = ""; }; + D6443F80E261022596B8ABA4 /* Pet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Pet.swift; sourceTree = ""; }; + DA84FDE7CC165FCEDC532CE0 /* User.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = User.swift; sourceTree = ""; }; + E99367F9F7013FFD55123670 /* Category.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Category.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 15E6C78D0C713DC56DE5E647 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 2BD3B8D227270A5E00E16037 /* APIs */ = { + isa = PBXGroup; + children = ( + 2BD3B8D327270A5E00E16037 /* PetAPI.swift */, + 2BD3B8D427270A5E00E16037 /* UserAPI.swift */, + 2BD3B8D527270A5E00E16037 /* StoreAPI.swift */, + ); + path = APIs; + sourceTree = ""; + }; + 531C2FA0FDC4145945B665DB /* Frameworks */ = { + isa = PBXGroup; + children = ( + 6DC4C6468A5F92971BE0F705 /* Carthage */, + ); + name = Frameworks; + sourceTree = ""; + }; + 58C164DF5107AE40B4ED3435 /* OpenAPIs */ = { + isa = PBXGroup; + children = ( + 2BD3B8D02727080900E16037 /* Runtime.swift */, + 2BD3B8D227270A5E00E16037 /* APIs */, + D3393B2ECC9C8AA58D9CC6B5 /* Models */, + ); + path = OpenAPIs; + sourceTree = ""; + }; + 6DC4C6468A5F92971BE0F705 /* Carthage */ = { + isa = PBXGroup; + children = ( + DC6DFE2BA49A9138D046C5C0 /* iOS */, + ); + name = Carthage; + path = Carthage/Build; + sourceTree = ""; + }; + 924C9AB67DF7BB7E7B243C8E = { + isa = PBXGroup; + children = ( + E1C55E9B3278648005177880 /* OpenAPIClient */, + 531C2FA0FDC4145945B665DB /* Frameworks */, + C93545A0873D7B9F1535DF32 /* Products */, + ); + sourceTree = ""; + }; + C93545A0873D7B9F1535DF32 /* Products */ = { + isa = PBXGroup; + children = ( + 5A68201A010940B069E402C4 /* OpenAPIClient.framework */, + ); + name = Products; + sourceTree = ""; + }; + D3393B2ECC9C8AA58D9CC6B5 /* Models */ = { + isa = PBXGroup; + children = ( + 7F0D02E61CF4C58B24BC1581 /* ApiResponse.swift */, + E99367F9F7013FFD55123670 /* Category.swift */, + 557E9F1F7D8EE8697FFC77CA /* Order.swift */, + D6443F80E261022596B8ABA4 /* Pet.swift */, + 004F49F830DBCE73EE547625 /* Tag.swift */, + DA84FDE7CC165FCEDC532CE0 /* User.swift */, + ); + path = Models; + sourceTree = ""; + }; + D88204A3BFDDC0BFD4278A5C /* Classes */ = { + isa = PBXGroup; + children = ( + 58C164DF5107AE40B4ED3435 /* OpenAPIs */, + ); + path = Classes; + sourceTree = ""; + }; + DC6DFE2BA49A9138D046C5C0 /* iOS */ = { + isa = PBXGroup; + children = ( + 804F7195C2469F7D77EEA124 /* AnyCodable.framework */, + ); + path = iOS; + sourceTree = ""; + }; + E1C55E9B3278648005177880 /* OpenAPIClient */ = { + isa = PBXGroup; + children = ( + D88204A3BFDDC0BFD4278A5C /* Classes */, + ); + path = OpenAPIClient; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 5D9D2D004FCC44CC7017F1A4 /* OpenAPIClient */ = { + isa = PBXNativeTarget; + buildConfigurationList = CF386033EEF5925F9C2E4094 /* Build configuration list for PBXNativeTarget "OpenAPIClient" */; + buildPhases = ( + 640E75056E1784D861D4EED4 /* Sources */, + 15E6C78D0C713DC56DE5E647 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = OpenAPIClient; + productName = OpenAPIClient; + productReference = 5A68201A010940B069E402C4 /* OpenAPIClient.framework */; + productType = "com.apple.product-type.framework"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + E9DEC8DB659CA753BD8ABDEC /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1200; + }; + buildConfigurationList = 2579284DF1820817301E6542 /* Build configuration list for PBXProject "OpenAPIClient" */; + compatibilityVersion = "Xcode 10.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + Base, + en, + ); + mainGroup = 924C9AB67DF7BB7E7B243C8E; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 5D9D2D004FCC44CC7017F1A4 /* OpenAPIClient */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 640E75056E1784D861D4EED4 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 5FDB83D7EF01DBFD3E8B6AD6 /* ApiResponse.swift in Sources */, + B3B33292169982AB380577B9 /* Category.swift in Sources */, + 2BD3B8D12727080900E16037 /* Runtime.swift in Sources */, + D2051AFBDBA23137A85FCA3B /* Order.swift in Sources */, + 8BB28EBA3F247E1FC0AEB946 /* Pet.swift in Sources */, + 07AD66F44F142A25134285D2 /* Tag.swift in Sources */, + 615F8910ABA037FBFA0BC09F /* User.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 36800091FD978FBD6D1175B7 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CODE_SIGN_IDENTITY = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/iOS", + ); + INFOPLIST_FILE = Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 14.1; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; + 59749DDA0BC81FD9808AC0E2 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "DEBUG=1", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + C56D67BF2B255376EE156215 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + E341761E3A15E306F1C55FE0 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CODE_SIGN_IDENTITY = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/iOS", + ); + INFOPLIST_FILE = Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 14.1; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 2579284DF1820817301E6542 /* Build configuration list for PBXProject "OpenAPIClient" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 59749DDA0BC81FD9808AC0E2 /* Debug */, + C56D67BF2B255376EE156215 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + CF386033EEF5925F9C2E4094 /* Build configuration list for PBXNativeTarget "OpenAPIClient" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E341761E3A15E306F1C55FE0 /* Debug */, + 36800091FD978FBD6D1175B7 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; +/* End XCConfigurationList section */ + }; + rootObject = E9DEC8DB659CA753BD8ABDEC /* Project object */; +} diff --git a/samples/client/petstore/swift/alt/OpenAPIClient.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/samples/client/petstore/swift/alt/OpenAPIClient.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000000..919434a6254f --- /dev/null +++ b/samples/client/petstore/swift/alt/OpenAPIClient.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/samples/client/petstore/swift/alt/OpenAPIClient.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/samples/client/petstore/swift/alt/OpenAPIClient.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000000..18d981003d68 --- /dev/null +++ b/samples/client/petstore/swift/alt/OpenAPIClient.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/samples/client/petstore/swift/alt/OpenAPIClient.xcodeproj/project.xcworkspace/xcuserdata/a.davydov.xcuserdatad/UserInterfaceState.xcuserstate b/samples/client/petstore/swift/alt/OpenAPIClient.xcodeproj/project.xcworkspace/xcuserdata/a.davydov.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..738e80166dbd60e61c6d4741879e61bf94fdb997 GIT binary patch literal 32313 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 z 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/APIs/PetAPI.swift b/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/APIs/PetAPI.swift new file mode 100644 index 000000000000..0ba3c64a2042 --- /dev/null +++ b/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/APIs/PetAPI.swift @@ -0,0 +1,566 @@ +// +// PetAPI.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation +import Combine +// import Runtime + + +open class PetAPI { + private let transport: Transport + + public init(_ transport: Transport) { + self.transport = transport + } + /** + Add a new pet to the store + - POST /pet + - OAuth: + - type: oauth2 + - name: petstore_auth + - parameter pet: (body) Pet object that needs to be added to the store + - returns: Future + */ + open func addPet(pet: Pet) -> Future { + } + /** + Deletes a pet + - DELETE /pet/{petId} + - OAuth: + - type: oauth2 + - name: petstore_auth + - parameter petId: (path) Pet id to delete + - parameter apiKey: (header) (optional) + - returns: Future + */ + open func deletePet(petId: Int64, apiKey: String? = nil) -> Future { + } + /** + Finds Pets by status + - GET /pet/findByStatus + - Multiple status values can be provided with comma separated strings + - OAuth: + - type: oauth2 + - name: petstore_auth + - parameter status: () Status values that need to be considered for filter + - returns: Future<[Pet], Never> + */ + open func findPetsByStatus(status: [String]) -> Future<[Pet], Never> { + } + /** + Finds Pets by tags + - GET /pet/findByTags + - Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. + - OAuth: + - type: oauth2 + - name: petstore_auth + - parameter tags: () Tags to filter by + - returns: Future<[Pet], Never> + */ + open func findPetsByTags(tags: [String]) -> Future<[Pet], Never> { + } + /** + Find pet by ID + - GET /pet/{petId} + - Returns a single pet + - API Key: + - type: apiKey api_key + - name: api_key + - parameter petId: (path) ID of pet to return + - returns: Future + */ + open func getPetById(petId: Int64) -> Future { + } + /** + Update an existing pet + - PUT /pet + - OAuth: + - type: oauth2 + - name: petstore_auth + - parameter pet: (body) Pet object that needs to be added to the store + - returns: Future + */ + open func updatePet(pet: Pet) -> Future { + } + /** + Updates a pet in the store with form data + - POST /pet/{petId} + - OAuth: + - type: oauth2 + - name: petstore_auth + - parameter petId: (path) ID of pet that needs to be updated + - parameter name: (form) Updated name of the pet (optional) + - parameter status: (form) Updated status of the pet (optional) + - returns: Future + */ + open func updatePetWithForm(petId: Int64, name: String? = nil, status: String? = nil) -> Future { + } + /** + uploads an image + - POST /pet/{petId}/uploadImage + - OAuth: + - type: oauth2 + - name: petstore_auth + - parameter petId: (path) ID of pet to update + - parameter additionalMetadata: (form) Additional data to pass to server (optional) + - parameter file: (form) file to upload (optional) + - returns: Future + */ + open func uploadFile(petId: Int64, additionalMetadata: String? = nil, file: Data? = nil) -> Future { + } +} +//// + +/** +- + - API Key: + - type: apiKey api_key + - name: api_key + - OAuth: + - type: oauth2 + - name: petstore_auth +- returns: RequestBuilder + */ +open class func WithRequestBuilder() -> RequestBuilder { +let localVariablePath = "" + let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath + let localVariableParameters: [String: Any]? = nil + + let localVariableUrlComponents = URLComponents(string: localVariableURLString) + + let localVariableNillableHeaders: [String: Any?] = [ + : + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() + + return localVariableRequestBuilder.init(method: "", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } + +import Foundation +#if canImport(AnyCodable) +import AnyCodable +#endif + +open class PetAPI { + + /** + Add a new pet to the store + + - parameter pet: (body) Pet object that needs to be added to the store + - parameter apiResponseQueue: The queue on which api response is dispatched. + - parameter completion: completion handler to receive the data and the error objects + */ + open class func addPet(pet: Pet, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Pet?, _ error: Error?) -> Void)) { + addPetWithRequestBuilder(pet: pet).execute(apiResponseQueue) { result in + switch result { + case let .success(response): + completion(response.body, nil) + case let .failure(error): + completion(nil, error) + } + } + } + + /** + Add a new pet to the store + - POST /pet + - OAuth: + - type: oauth2 + - name: petstore_auth + - parameter pet: (body) Pet object that needs to be added to the store + - returns: RequestBuilder + */ + open class func addPetWithRequestBuilder(pet: Pet) -> RequestBuilder { + let localVariablePath = "/pet" + let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath + let localVariableParameters = JSONEncodingHelper.encodingParameters(forEncodableObject: pet) + + let localVariableUrlComponents = URLComponents(string: localVariableURLString) + + let localVariableNillableHeaders: [String: Any?] = [ + : + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getBuilder() + + return localVariableRequestBuilder.init(method: "POST", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } + + /** + Deletes a pet + + - parameter petId: (path) Pet id to delete + - parameter apiKey: (header) (optional) + - parameter apiResponseQueue: The queue on which api response is dispatched. + - parameter completion: completion handler to receive the data and the error objects + */ + open class func deletePet(petId: Int64, apiKey: String? = nil, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Void?, _ error: Error?) -> Void)) { + deletePetWithRequestBuilder(petId: petId, apiKey: apiKey).execute(apiResponseQueue) { result in + switch result { + case .success: + completion((), nil) + case let .failure(error): + completion(nil, error) + } + } + } + + /** + Deletes a pet + - DELETE /pet/{petId} + - OAuth: + - type: oauth2 + - name: petstore_auth + - parameter petId: (path) Pet id to delete + - parameter apiKey: (header) (optional) + - returns: RequestBuilder + */ + open class func deletePetWithRequestBuilder(petId: Int64, apiKey: String? = nil) -> RequestBuilder { + var localVariablePath = "/pet/{petId}" + let petIdPreEscape = "\(APIHelper.mapValueToPathItem(petId))" + let petIdPostEscape = petIdPreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" + localVariablePath = localVariablePath.replacingOccurrences(of: "{petId}", with: petIdPostEscape, options: .literal, range: nil) + let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath + let localVariableParameters: [String: Any]? = nil + + let localVariableUrlComponents = URLComponents(string: localVariableURLString) + + let localVariableNillableHeaders: [String: Any?] = [ + "api_key": apiKey?.encodeToJSON(), + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() + + return localVariableRequestBuilder.init(method: "DELETE", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } + + /** + * enum for parameter status + */ + public enum Status_findPetsByStatus: String, CaseIterable { + case available = "available" + case pending = "pending" + case sold = "sold" + } + + /** + Finds Pets by status + + - parameter status: (query) Status values that need to be considered for filter + - parameter apiResponseQueue: The queue on which api response is dispatched. + - parameter completion: completion handler to receive the data and the error objects + */ + open class func findPetsByStatus(status: [String], apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: [Pet]?, _ error: Error?) -> Void)) { + findPetsByStatusWithRequestBuilder(status: status).execute(apiResponseQueue) { result in + switch result { + case let .success(response): + completion(response.body, nil) + case let .failure(error): + completion(nil, error) + } + } + } + + /** + Finds Pets by status + - GET /pet/findByStatus + - Multiple status values can be provided with comma separated strings + - OAuth: + - type: oauth2 + - name: petstore_auth + - parameter status: (query) Status values that need to be considered for filter + - returns: RequestBuilder<[Pet]> + */ + open class func findPetsByStatusWithRequestBuilder(status: [String]) -> RequestBuilder<[Pet]> { + let localVariablePath = "/pet/findByStatus" + let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath + let localVariableParameters: [String: Any]? = nil + + var localVariableUrlComponents = URLComponents(string: localVariableURLString) + localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems([ + "status": status.encodeToJSON(), + ]) + + let localVariableNillableHeaders: [String: Any?] = [ + : + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder<[Pet]>.Type = OpenAPIClientAPI.requestBuilderFactory.getBuilder() + + return localVariableRequestBuilder.init(method: "GET", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } + + /** + Finds Pets by tags + + - parameter tags: (query) Tags to filter by + - parameter apiResponseQueue: The queue on which api response is dispatched. + - parameter completion: completion handler to receive the data and the error objects + */ + @available(*, deprecated, message: "This operation is deprecated.") + open class func findPetsByTags(tags: [String], apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: [Pet]?, _ error: Error?) -> Void)) { + findPetsByTagsWithRequestBuilder(tags: tags).execute(apiResponseQueue) { result in + switch result { + case let .success(response): + completion(response.body, nil) + case let .failure(error): + completion(nil, error) + } + } + } + + /** + Finds Pets by tags + - GET /pet/findByTags + - Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. + - OAuth: + - type: oauth2 + - name: petstore_auth + - parameter tags: (query) Tags to filter by + - returns: RequestBuilder<[Pet]> + */ + @available(*, deprecated, message: "This operation is deprecated.") + open class func findPetsByTagsWithRequestBuilder(tags: [String]) -> RequestBuilder<[Pet]> { + let localVariablePath = "/pet/findByTags" + let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath + let localVariableParameters: [String: Any]? = nil + + var localVariableUrlComponents = URLComponents(string: localVariableURLString) + localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems([ + "tags": tags.encodeToJSON(), + ]) + + let localVariableNillableHeaders: [String: Any?] = [ + : + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder<[Pet]>.Type = OpenAPIClientAPI.requestBuilderFactory.getBuilder() + + return localVariableRequestBuilder.init(method: "GET", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } + + /** + Find pet by ID + + - parameter petId: (path) ID of pet to return + - parameter apiResponseQueue: The queue on which api response is dispatched. + - parameter completion: completion handler to receive the data and the error objects + */ + open class func getPetById(petId: Int64, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Pet?, _ error: Error?) -> Void)) { + getPetByIdWithRequestBuilder(petId: petId).execute(apiResponseQueue) { result in + switch result { + case let .success(response): + completion(response.body, nil) + case let .failure(error): + completion(nil, error) + } + } + } + + /** + Find pet by ID + - GET /pet/{petId} + - Returns a single pet + - API Key: + - type: apiKey api_key + - name: api_key + - parameter petId: (path) ID of pet to return + - returns: RequestBuilder + */ + open class func getPetByIdWithRequestBuilder(petId: Int64) -> RequestBuilder { + var localVariablePath = "/pet/{petId}" + let petIdPreEscape = "\(APIHelper.mapValueToPathItem(petId))" + let petIdPostEscape = petIdPreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" + localVariablePath = localVariablePath.replacingOccurrences(of: "{petId}", with: petIdPostEscape, options: .literal, range: nil) + let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath + let localVariableParameters: [String: Any]? = nil + + let localVariableUrlComponents = URLComponents(string: localVariableURLString) + + let localVariableNillableHeaders: [String: Any?] = [ + : + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getBuilder() + + return localVariableRequestBuilder.init(method: "GET", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } + + /** + Update an existing pet + + - parameter pet: (body) Pet object that needs to be added to the store + - parameter apiResponseQueue: The queue on which api response is dispatched. + - parameter completion: completion handler to receive the data and the error objects + */ + open class func updatePet(pet: Pet, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Pet?, _ error: Error?) -> Void)) { + updatePetWithRequestBuilder(pet: pet).execute(apiResponseQueue) { result in + switch result { + case let .success(response): + completion(response.body, nil) + case let .failure(error): + completion(nil, error) + } + } + } + + /** + Update an existing pet + - PUT /pet + - OAuth: + - type: oauth2 + - name: petstore_auth + - parameter pet: (body) Pet object that needs to be added to the store + - returns: RequestBuilder + */ + open class func updatePetWithRequestBuilder(pet: Pet) -> RequestBuilder { + let localVariablePath = "/pet" + let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath + let localVariableParameters = JSONEncodingHelper.encodingParameters(forEncodableObject: pet) + + let localVariableUrlComponents = URLComponents(string: localVariableURLString) + + let localVariableNillableHeaders: [String: Any?] = [ + : + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getBuilder() + + return localVariableRequestBuilder.init(method: "PUT", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } + + /** + Updates a pet in the store with form data + + - parameter petId: (path) ID of pet that needs to be updated + - parameter name: (form) Updated name of the pet (optional) + - parameter status: (form) Updated status of the pet (optional) + - parameter apiResponseQueue: The queue on which api response is dispatched. + - parameter completion: completion handler to receive the data and the error objects + */ + open class func updatePetWithForm(petId: Int64, name: String? = nil, status: String? = nil, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Void?, _ error: Error?) -> Void)) { + updatePetWithFormWithRequestBuilder(petId: petId, name: name, status: status).execute(apiResponseQueue) { result in + switch result { + case .success: + completion((), nil) + case let .failure(error): + completion(nil, error) + } + } + } + + /** + Updates a pet in the store with form data + - POST /pet/{petId} + - OAuth: + - type: oauth2 + - name: petstore_auth + - parameter petId: (path) ID of pet that needs to be updated + - parameter name: (form) Updated name of the pet (optional) + - parameter status: (form) Updated status of the pet (optional) + - returns: RequestBuilder + */ + open class func updatePetWithFormWithRequestBuilder(petId: Int64, name: String? = nil, status: String? = nil) -> RequestBuilder { + var localVariablePath = "/pet/{petId}" + let petIdPreEscape = "\(APIHelper.mapValueToPathItem(petId))" + let petIdPostEscape = petIdPreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" + localVariablePath = localVariablePath.replacingOccurrences(of: "{petId}", with: petIdPostEscape, options: .literal, range: nil) + let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath + let localVariableFormParams: [String: Any?] = [ + "name": name?.encodeToJSON(), + "status": status?.encodeToJSON(), + ] + + let localVariableNonNullParameters = APIHelper.rejectNil(localVariableFormParams) + let localVariableParameters = APIHelper.convertBoolToString(localVariableNonNullParameters) + + let localVariableUrlComponents = URLComponents(string: localVariableURLString) + + let localVariableNillableHeaders: [String: Any?] = [ + "Content-Type": "application/x-www-form-urlencoded", + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() + + return localVariableRequestBuilder.init(method: "POST", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } + + /** + uploads an image + + - parameter petId: (path) ID of pet to update + - parameter additionalMetadata: (form) Additional data to pass to server (optional) + - parameter file: (form) file to upload (optional) + - parameter apiResponseQueue: The queue on which api response is dispatched. + - parameter completion: completion handler to receive the data and the error objects + */ + open class func uploadFile(petId: Int64, additionalMetadata: String? = nil, file: Data? = nil, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: ApiResponse?, _ error: Error?) -> Void)) { + uploadFileWithRequestBuilder(petId: petId, additionalMetadata: additionalMetadata, file: file).execute(apiResponseQueue) { result in + switch result { + case let .success(response): + completion(response.body, nil) + case let .failure(error): + completion(nil, error) + } + } + } + + /** + uploads an image + - POST /pet/{petId}/uploadImage + - OAuth: + - type: oauth2 + - name: petstore_auth + - parameter petId: (path) ID of pet to update + - parameter additionalMetadata: (form) Additional data to pass to server (optional) + - parameter file: (form) file to upload (optional) + - returns: RequestBuilder + */ + open class func uploadFileWithRequestBuilder(petId: Int64, additionalMetadata: String? = nil, file: Data? = nil) -> RequestBuilder { + var localVariablePath = "/pet/{petId}/uploadImage" + let petIdPreEscape = "\(APIHelper.mapValueToPathItem(petId))" + let petIdPostEscape = petIdPreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" + localVariablePath = localVariablePath.replacingOccurrences(of: "{petId}", with: petIdPostEscape, options: .literal, range: nil) + let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath + let localVariableFormParams: [String: Any?] = [ + "additionalMetadata": additionalMetadata?.encodeToJSON(), + "file": file?.encodeToJSON(), + ] + + let localVariableNonNullParameters = APIHelper.rejectNil(localVariableFormParams) + let localVariableParameters = APIHelper.convertBoolToString(localVariableNonNullParameters) + + let localVariableUrlComponents = URLComponents(string: localVariableURLString) + + let localVariableNillableHeaders: [String: Any?] = [ + "Content-Type": "multipart/form-data", + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getBuilder() + + return localVariableRequestBuilder.init(method: "POST", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } +} diff --git a/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/APIs/StoreAPI.swift b/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/APIs/StoreAPI.swift new file mode 100644 index 000000000000..0482548154fb --- /dev/null +++ b/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/APIs/StoreAPI.swift @@ -0,0 +1,271 @@ +// +// StoreAPI.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation +import Combine +// import Runtime + + +open class StoreAPI { + private let transport: Transport + + public init(_ transport: Transport) { + self.transport = transport + } + /** + Delete purchase order by ID + - DELETE /store/order/{orderId} + - For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors + - parameter orderId: (path) ID of the order that needs to be deleted + - returns: Future + */ + open func deleteOrder(orderId: String) -> Future { + } + /** + Returns pet inventories by status + - GET /store/inventory + - Returns a map of status codes to quantities + - API Key: + - type: apiKey api_key + - name: api_key + - returns: Future<[String: Int], Never> + */ + open func getInventory() -> Future<[String: Int], Never> { + } + /** + Find purchase order by ID + - GET /store/order/{orderId} + - For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions + - parameter orderId: (path) ID of pet that needs to be fetched + - returns: Future + */ + open func getOrderById(orderId: Int64) -> Future { + } + /** + Place an order for a pet + - POST /store/order + - parameter order: (body) order placed for purchasing the pet + - returns: Future + */ + open func placeOrder(order: Order) -> Future { + } +} +//// + +/** +- + - API Key: + - type: apiKey api_key + - name: api_key + - OAuth: + - type: oauth2 + - name: petstore_auth +- returns: RequestBuilder + */ +open class func WithRequestBuilder() -> RequestBuilder { +let localVariablePath = "" + let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath + let localVariableParameters: [String: Any]? = nil + + let localVariableUrlComponents = URLComponents(string: localVariableURLString) + + let localVariableNillableHeaders: [String: Any?] = [ + : + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() + + return localVariableRequestBuilder.init(method: "", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } + +import Foundation +#if canImport(AnyCodable) +import AnyCodable +#endif + +open class StoreAPI { + + /** + Delete purchase order by ID + + - parameter orderId: (path) ID of the order that needs to be deleted + - parameter apiResponseQueue: The queue on which api response is dispatched. + - parameter completion: completion handler to receive the data and the error objects + */ + open class func deleteOrder(orderId: String, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Void?, _ error: Error?) -> Void)) { + deleteOrderWithRequestBuilder(orderId: orderId).execute(apiResponseQueue) { result in + switch result { + case .success: + completion((), nil) + case let .failure(error): + completion(nil, error) + } + } + } + + /** + Delete purchase order by ID + - DELETE /store/order/{orderId} + - For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors + - parameter orderId: (path) ID of the order that needs to be deleted + - returns: RequestBuilder + */ + open class func deleteOrderWithRequestBuilder(orderId: String) -> RequestBuilder { + var localVariablePath = "/store/order/{orderId}" + let orderIdPreEscape = "\(APIHelper.mapValueToPathItem(orderId))" + let orderIdPostEscape = orderIdPreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" + localVariablePath = localVariablePath.replacingOccurrences(of: "{orderId}", with: orderIdPostEscape, options: .literal, range: nil) + let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath + let localVariableParameters: [String: Any]? = nil + + let localVariableUrlComponents = URLComponents(string: localVariableURLString) + + let localVariableNillableHeaders: [String: Any?] = [ + : + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() + + return localVariableRequestBuilder.init(method: "DELETE", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } + + /** + Returns pet inventories by status + + - parameter apiResponseQueue: The queue on which api response is dispatched. + - parameter completion: completion handler to receive the data and the error objects + */ + open class func getInventory(apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: [String: Int]?, _ error: Error?) -> Void)) { + getInventoryWithRequestBuilder().execute(apiResponseQueue) { result in + switch result { + case let .success(response): + completion(response.body, nil) + case let .failure(error): + completion(nil, error) + } + } + } + + /** + Returns pet inventories by status + - GET /store/inventory + - Returns a map of status codes to quantities + - API Key: + - type: apiKey api_key + - name: api_key + - returns: RequestBuilder<[String: Int]> + */ + open class func getInventoryWithRequestBuilder() -> RequestBuilder<[String: Int]> { + let localVariablePath = "/store/inventory" + let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath + let localVariableParameters: [String: Any]? = nil + + let localVariableUrlComponents = URLComponents(string: localVariableURLString) + + let localVariableNillableHeaders: [String: Any?] = [ + : + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder<[String: Int]>.Type = OpenAPIClientAPI.requestBuilderFactory.getBuilder() + + return localVariableRequestBuilder.init(method: "GET", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } + + /** + Find purchase order by ID + + - parameter orderId: (path) ID of pet that needs to be fetched + - parameter apiResponseQueue: The queue on which api response is dispatched. + - parameter completion: completion handler to receive the data and the error objects + */ + open class func getOrderById(orderId: Int64, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Order?, _ error: Error?) -> Void)) { + getOrderByIdWithRequestBuilder(orderId: orderId).execute(apiResponseQueue) { result in + switch result { + case let .success(response): + completion(response.body, nil) + case let .failure(error): + completion(nil, error) + } + } + } + + /** + Find purchase order by ID + - GET /store/order/{orderId} + - For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions + - parameter orderId: (path) ID of pet that needs to be fetched + - returns: RequestBuilder + */ + open class func getOrderByIdWithRequestBuilder(orderId: Int64) -> RequestBuilder { + var localVariablePath = "/store/order/{orderId}" + let orderIdPreEscape = "\(APIHelper.mapValueToPathItem(orderId))" + let orderIdPostEscape = orderIdPreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" + localVariablePath = localVariablePath.replacingOccurrences(of: "{orderId}", with: orderIdPostEscape, options: .literal, range: nil) + let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath + let localVariableParameters: [String: Any]? = nil + + let localVariableUrlComponents = URLComponents(string: localVariableURLString) + + let localVariableNillableHeaders: [String: Any?] = [ + : + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getBuilder() + + return localVariableRequestBuilder.init(method: "GET", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } + + /** + Place an order for a pet + + - parameter order: (body) order placed for purchasing the pet + - parameter apiResponseQueue: The queue on which api response is dispatched. + - parameter completion: completion handler to receive the data and the error objects + */ + open class func placeOrder(order: Order, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Order?, _ error: Error?) -> Void)) { + placeOrderWithRequestBuilder(order: order).execute(apiResponseQueue) { result in + switch result { + case let .success(response): + completion(response.body, nil) + case let .failure(error): + completion(nil, error) + } + } + } + + /** + Place an order for a pet + - POST /store/order + - parameter order: (body) order placed for purchasing the pet + - returns: RequestBuilder + */ + open class func placeOrderWithRequestBuilder(order: Order) -> RequestBuilder { + let localVariablePath = "/store/order" + let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath + let localVariableParameters = JSONEncodingHelper.encodingParameters(forEncodableObject: order) + + let localVariableUrlComponents = URLComponents(string: localVariableURLString) + + let localVariableNillableHeaders: [String: Any?] = [ + : + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getBuilder() + + return localVariableRequestBuilder.init(method: "POST", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } +} diff --git a/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/APIs/UserAPI.swift b/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/APIs/UserAPI.swift new file mode 100644 index 000000000000..a9dcc7267b0f --- /dev/null +++ b/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/APIs/UserAPI.swift @@ -0,0 +1,516 @@ +// +// UserAPI.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation +import Combine +// import Runtime + + +open class UserAPI { + private let transport: Transport + + public init(_ transport: Transport) { + self.transport = transport + } + /** + Create user + - POST /user + - This can only be done by the logged in user. + - API Key: + - type: apiKey api_key + - name: api_key + - parameter user: (body) Created user object + - returns: Future + */ + open func createUser(user: User) -> Future { + } + /** + Creates list of users with given input array + - POST /user/createWithArray + - API Key: + - type: apiKey api_key + - name: api_key + - parameter user: (body) List of user object + - returns: Future + */ + open func createUsersWithArrayInput(user: [User]) -> Future { + } + /** + Creates list of users with given input array + - POST /user/createWithList + - API Key: + - type: apiKey api_key + - name: api_key + - parameter user: (body) List of user object + - returns: Future + */ + open func createUsersWithListInput(user: [User]) -> Future { + } + /** + Delete user + - DELETE /user/{username} + - This can only be done by the logged in user. + - API Key: + - type: apiKey api_key + - name: api_key + - parameter username: (path) The name that needs to be deleted + - returns: Future + */ + open func deleteUser(username: String) -> Future { + } + /** + Get user by user name + - GET /user/{username} + - parameter username: (path) The name that needs to be fetched. Use user1 for testing. + - returns: Future + */ + open func getUserByName(username: String) -> Future { + } + /** + Logs user into the system + - GET /user/login + - responseHeaders: [Set-Cookie(String), X-Rate-Limit(Int), X-Expires-After(Date)] + - parameter username: () The user name for login + - parameter password: () The password for login in clear text + - returns: Future + */ + open func loginUser(username: String, password: String) -> Future { + } + /** + Logs out current logged in user session + - GET /user/logout + - API Key: + - type: apiKey api_key + - name: api_key + - returns: Future + */ + open func logoutUser() -> Future { + } + /** + Updated user + - PUT /user/{username} + - This can only be done by the logged in user. + - API Key: + - type: apiKey api_key + - name: api_key + - parameter username: (path) name that need to be deleted + - parameter user: (body) Updated user object + - returns: Future + */ + open func updateUser(username: String, user: User) -> Future { + } +} +//// + +/** +- + - API Key: + - type: apiKey api_key + - name: api_key + - OAuth: + - type: oauth2 + - name: petstore_auth +- returns: RequestBuilder + */ +open class func WithRequestBuilder() -> RequestBuilder { +let localVariablePath = "" + let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath + let localVariableParameters: [String: Any]? = nil + + let localVariableUrlComponents = URLComponents(string: localVariableURLString) + + let localVariableNillableHeaders: [String: Any?] = [ + : + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() + + return localVariableRequestBuilder.init(method: "", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } + +import Foundation +#if canImport(AnyCodable) +import AnyCodable +#endif + +open class UserAPI { + + /** + Create user + + - parameter user: (body) Created user object + - parameter apiResponseQueue: The queue on which api response is dispatched. + - parameter completion: completion handler to receive the data and the error objects + */ + open class func createUser(user: User, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Void?, _ error: Error?) -> Void)) { + createUserWithRequestBuilder(user: user).execute(apiResponseQueue) { result in + switch result { + case .success: + completion((), nil) + case let .failure(error): + completion(nil, error) + } + } + } + + /** + Create user + - POST /user + - This can only be done by the logged in user. + - API Key: + - type: apiKey api_key + - name: api_key + - parameter user: (body) Created user object + - returns: RequestBuilder + */ + open class func createUserWithRequestBuilder(user: User) -> RequestBuilder { + let localVariablePath = "/user" + let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath + let localVariableParameters = JSONEncodingHelper.encodingParameters(forEncodableObject: user) + + let localVariableUrlComponents = URLComponents(string: localVariableURLString) + + let localVariableNillableHeaders: [String: Any?] = [ + : + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() + + return localVariableRequestBuilder.init(method: "POST", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } + + /** + Creates list of users with given input array + + - parameter user: (body) List of user object + - parameter apiResponseQueue: The queue on which api response is dispatched. + - parameter completion: completion handler to receive the data and the error objects + */ + open class func createUsersWithArrayInput(user: [User], apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Void?, _ error: Error?) -> Void)) { + createUsersWithArrayInputWithRequestBuilder(user: user).execute(apiResponseQueue) { result in + switch result { + case .success: + completion((), nil) + case let .failure(error): + completion(nil, error) + } + } + } + + /** + Creates list of users with given input array + - POST /user/createWithArray + - API Key: + - type: apiKey api_key + - name: api_key + - parameter user: (body) List of user object + - returns: RequestBuilder + */ + open class func createUsersWithArrayInputWithRequestBuilder(user: [User]) -> RequestBuilder { + let localVariablePath = "/user/createWithArray" + let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath + let localVariableParameters = JSONEncodingHelper.encodingParameters(forEncodableObject: user) + + let localVariableUrlComponents = URLComponents(string: localVariableURLString) + + let localVariableNillableHeaders: [String: Any?] = [ + : + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() + + return localVariableRequestBuilder.init(method: "POST", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } + + /** + Creates list of users with given input array + + - parameter user: (body) List of user object + - parameter apiResponseQueue: The queue on which api response is dispatched. + - parameter completion: completion handler to receive the data and the error objects + */ + open class func createUsersWithListInput(user: [User], apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Void?, _ error: Error?) -> Void)) { + createUsersWithListInputWithRequestBuilder(user: user).execute(apiResponseQueue) { result in + switch result { + case .success: + completion((), nil) + case let .failure(error): + completion(nil, error) + } + } + } + + /** + Creates list of users with given input array + - POST /user/createWithList + - API Key: + - type: apiKey api_key + - name: api_key + - parameter user: (body) List of user object + - returns: RequestBuilder + */ + open class func createUsersWithListInputWithRequestBuilder(user: [User]) -> RequestBuilder { + let localVariablePath = "/user/createWithList" + let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath + let localVariableParameters = JSONEncodingHelper.encodingParameters(forEncodableObject: user) + + let localVariableUrlComponents = URLComponents(string: localVariableURLString) + + let localVariableNillableHeaders: [String: Any?] = [ + : + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() + + return localVariableRequestBuilder.init(method: "POST", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } + + /** + Delete user + + - parameter username: (path) The name that needs to be deleted + - parameter apiResponseQueue: The queue on which api response is dispatched. + - parameter completion: completion handler to receive the data and the error objects + */ + open class func deleteUser(username: String, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Void?, _ error: Error?) -> Void)) { + deleteUserWithRequestBuilder(username: username).execute(apiResponseQueue) { result in + switch result { + case .success: + completion((), nil) + case let .failure(error): + completion(nil, error) + } + } + } + + /** + Delete user + - DELETE /user/{username} + - This can only be done by the logged in user. + - API Key: + - type: apiKey api_key + - name: api_key + - parameter username: (path) The name that needs to be deleted + - returns: RequestBuilder + */ + open class func deleteUserWithRequestBuilder(username: String) -> RequestBuilder { + var localVariablePath = "/user/{username}" + let usernamePreEscape = "\(APIHelper.mapValueToPathItem(username))" + let usernamePostEscape = usernamePreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" + localVariablePath = localVariablePath.replacingOccurrences(of: "{username}", with: usernamePostEscape, options: .literal, range: nil) + let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath + let localVariableParameters: [String: Any]? = nil + + let localVariableUrlComponents = URLComponents(string: localVariableURLString) + + let localVariableNillableHeaders: [String: Any?] = [ + : + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() + + return localVariableRequestBuilder.init(method: "DELETE", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } + + /** + Get user by user name + + - parameter username: (path) The name that needs to be fetched. Use user1 for testing. + - parameter apiResponseQueue: The queue on which api response is dispatched. + - parameter completion: completion handler to receive the data and the error objects + */ + open class func getUserByName(username: String, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: User?, _ error: Error?) -> Void)) { + getUserByNameWithRequestBuilder(username: username).execute(apiResponseQueue) { result in + switch result { + case let .success(response): + completion(response.body, nil) + case let .failure(error): + completion(nil, error) + } + } + } + + /** + Get user by user name + - GET /user/{username} + - parameter username: (path) The name that needs to be fetched. Use user1 for testing. + - returns: RequestBuilder + */ + open class func getUserByNameWithRequestBuilder(username: String) -> RequestBuilder { + var localVariablePath = "/user/{username}" + let usernamePreEscape = "\(APIHelper.mapValueToPathItem(username))" + let usernamePostEscape = usernamePreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" + localVariablePath = localVariablePath.replacingOccurrences(of: "{username}", with: usernamePostEscape, options: .literal, range: nil) + let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath + let localVariableParameters: [String: Any]? = nil + + let localVariableUrlComponents = URLComponents(string: localVariableURLString) + + let localVariableNillableHeaders: [String: Any?] = [ + : + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getBuilder() + + return localVariableRequestBuilder.init(method: "GET", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } + + /** + Logs user into the system + + - parameter username: (query) The user name for login + - parameter password: (query) The password for login in clear text + - parameter apiResponseQueue: The queue on which api response is dispatched. + - parameter completion: completion handler to receive the data and the error objects + */ + open class func loginUser(username: String, password: String, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: String?, _ error: Error?) -> Void)) { + loginUserWithRequestBuilder(username: username, password: password).execute(apiResponseQueue) { result in + switch result { + case let .success(response): + completion(response.body, nil) + case let .failure(error): + completion(nil, error) + } + } + } + + /** + Logs user into the system + - GET /user/login + - responseHeaders: [Set-Cookie(String), X-Rate-Limit(Int), X-Expires-After(Date)] + - parameter username: (query) The user name for login + - parameter password: (query) The password for login in clear text + - returns: RequestBuilder + */ + open class func loginUserWithRequestBuilder(username: String, password: String) -> RequestBuilder { + let localVariablePath = "/user/login" + let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath + let localVariableParameters: [String: Any]? = nil + + var localVariableUrlComponents = URLComponents(string: localVariableURLString) + localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems([ + "username": username.encodeToJSON(), + "password": password.encodeToJSON(), + ]) + + let localVariableNillableHeaders: [String: Any?] = [ + : + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getBuilder() + + return localVariableRequestBuilder.init(method: "GET", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } + + /** + Logs out current logged in user session + + - parameter apiResponseQueue: The queue on which api response is dispatched. + - parameter completion: completion handler to receive the data and the error objects + */ + open class func logoutUser(apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Void?, _ error: Error?) -> Void)) { + logoutUserWithRequestBuilder().execute(apiResponseQueue) { result in + switch result { + case .success: + completion((), nil) + case let .failure(error): + completion(nil, error) + } + } + } + + /** + Logs out current logged in user session + - GET /user/logout + - API Key: + - type: apiKey api_key + - name: api_key + - returns: RequestBuilder + */ + open class func logoutUserWithRequestBuilder() -> RequestBuilder { + let localVariablePath = "/user/logout" + let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath + let localVariableParameters: [String: Any]? = nil + + let localVariableUrlComponents = URLComponents(string: localVariableURLString) + + let localVariableNillableHeaders: [String: Any?] = [ + : + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() + + return localVariableRequestBuilder.init(method: "GET", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } + + /** + Updated user + + - parameter username: (path) name that need to be deleted + - parameter user: (body) Updated user object + - parameter apiResponseQueue: The queue on which api response is dispatched. + - parameter completion: completion handler to receive the data and the error objects + */ + open class func updateUser(username: String, user: User, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Void?, _ error: Error?) -> Void)) { + updateUserWithRequestBuilder(username: username, user: user).execute(apiResponseQueue) { result in + switch result { + case .success: + completion((), nil) + case let .failure(error): + completion(nil, error) + } + } + } + + /** + Updated user + - PUT /user/{username} + - This can only be done by the logged in user. + - API Key: + - type: apiKey api_key + - name: api_key + - parameter username: (path) name that need to be deleted + - parameter user: (body) Updated user object + - returns: RequestBuilder + */ + open class func updateUserWithRequestBuilder(username: String, user: User) -> RequestBuilder { + var localVariablePath = "/user/{username}" + let usernamePreEscape = "\(APIHelper.mapValueToPathItem(username))" + let usernamePostEscape = usernamePreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" + localVariablePath = localVariablePath.replacingOccurrences(of: "{username}", with: usernamePostEscape, options: .literal, range: nil) + let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath + let localVariableParameters = JSONEncodingHelper.encodingParameters(forEncodableObject: user) + + let localVariableUrlComponents = URLComponents(string: localVariableURLString) + + let localVariableNillableHeaders: [String: Any?] = [ + : + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() + + return localVariableRequestBuilder.init(method: "PUT", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } +} diff --git a/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/Models/ApiResponse.swift b/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/Models/ApiResponse.swift new file mode 100644 index 000000000000..71946091f80a --- /dev/null +++ b/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/Models/ApiResponse.swift @@ -0,0 +1,40 @@ +// +// ApiResponse.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation +#if canImport(AnyCodable) +import AnyCodable +#endif + +/** Describes the result of uploading an image resource */ + +public struct ApiResponse: Codable, Hashable { + public var code: Int? + public var type: String? + public var message: String? + + public init(code: Int? = nil, type: String? = nil, message: String? = nil) { + self.code = code + self.type = type + self.message = message + } + + public enum CodingKeys: String, CodingKey, CaseIterable { + case code + case type + case message + } + + // Encodable protocol methods + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encodeIfPresent(code, forKey: .code) + try container.encodeIfPresent(type, forKey: .type) + try container.encodeIfPresent(message, forKey: .message) + } +} diff --git a/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/Models/Category.swift b/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/Models/Category.swift new file mode 100644 index 000000000000..c826c6caf9b3 --- /dev/null +++ b/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/Models/Category.swift @@ -0,0 +1,36 @@ +// +// Category.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation +#if canImport(AnyCodable) +import AnyCodable +#endif + +/** A category for a pet */ + +public struct Category: Codable, Hashable { + public var id: Int64? + public var name: String? + + public init(id: Int64? = nil, name: String? = nil) { + self.id = id + self.name = name + } + + public enum CodingKeys: String, CodingKey, CaseIterable { + case id + case name + } + + // Encodable protocol methods + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encodeIfPresent(id, forKey: .id) + try container.encodeIfPresent(name, forKey: .name) + } +} diff --git a/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/Models/Order.swift b/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/Models/Order.swift new file mode 100644 index 000000000000..e0744049ca9b --- /dev/null +++ b/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/Models/Order.swift @@ -0,0 +1,58 @@ +// +// Order.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation +#if canImport(AnyCodable) +import AnyCodable +#endif + +/** An order for a pets from the pet store */ + +public struct Order: Codable, Hashable { + public enum Status: String, Hashable, Codable, CaseIterable { + case placed = "placed" + case approved = "approved" + case delivered = "delivered" + } + public var id: Int64? + public var petId: Int64? + public var quantity: Int? + public var shipDate: Date? + /** Order Status */ + public var status: Status? + public var complete: Bool? = false + + public init(id: Int64? = nil, petId: Int64? = nil, quantity: Int? = nil, shipDate: Date? = nil, status: Status? = nil, complete: Bool? = false) { + self.id = id + self.petId = petId + self.quantity = quantity + self.shipDate = shipDate + self.status = status + self.complete = complete + } + + public enum CodingKeys: String, CodingKey, CaseIterable { + case id + case petId + case quantity + case shipDate + case status + case complete + } + + // Encodable protocol methods + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encodeIfPresent(id, forKey: .id) + try container.encodeIfPresent(petId, forKey: .petId) + try container.encodeIfPresent(quantity, forKey: .quantity) + try container.encodeIfPresent(shipDate, forKey: .shipDate) + try container.encodeIfPresent(status, forKey: .status) + try container.encodeIfPresent(complete, forKey: .complete) + } +} diff --git a/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/Models/Pet.swift b/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/Models/Pet.swift new file mode 100644 index 000000000000..c86438b0112c --- /dev/null +++ b/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/Models/Pet.swift @@ -0,0 +1,58 @@ +// +// Pet.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation +#if canImport(AnyCodable) +import AnyCodable +#endif + +/** A pet for sale in the pet store */ + +public struct Pet: Codable, Hashable { + public enum Status: String, Hashable, Codable, CaseIterable { + case available = "available" + case pending = "pending" + case sold = "sold" + } + public var id: Int64? + public var category: Category? + public var name: String + public var photoUrls: [String] + public var tags: [Tag]? + /** pet status in the store */ + public var status: Status? + + public init(id: Int64? = nil, category: Category? = nil, name: String, photoUrls: [String], tags: [Tag]? = nil, status: Status? = nil) { + self.id = id + self.category = category + self.name = name + self.photoUrls = photoUrls + self.tags = tags + self.status = status + } + + public enum CodingKeys: String, CodingKey, CaseIterable { + case id + case category + case name + case photoUrls + case tags + case status + } + + // Encodable protocol methods + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encodeIfPresent(id, forKey: .id) + try container.encodeIfPresent(category, forKey: .category) + try container.encode(name, forKey: .name) + try container.encode(photoUrls, forKey: .photoUrls) + try container.encodeIfPresent(tags, forKey: .tags) + try container.encodeIfPresent(status, forKey: .status) + } +} diff --git a/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/Models/Tag.swift b/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/Models/Tag.swift new file mode 100644 index 000000000000..4724926e4a45 --- /dev/null +++ b/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/Models/Tag.swift @@ -0,0 +1,36 @@ +// +// Tag.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation +#if canImport(AnyCodable) +import AnyCodable +#endif + +/** A tag for a pet */ + +public struct Tag: Codable, Hashable { + public var id: Int64? + public var name: String? + + public init(id: Int64? = nil, name: String? = nil) { + self.id = id + self.name = name + } + + public enum CodingKeys: String, CodingKey, CaseIterable { + case id + case name + } + + // Encodable protocol methods + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encodeIfPresent(id, forKey: .id) + try container.encodeIfPresent(name, forKey: .name) + } +} diff --git a/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/Models/User.swift b/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/Models/User.swift new file mode 100644 index 000000000000..2004d9296628 --- /dev/null +++ b/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/Models/User.swift @@ -0,0 +1,61 @@ +// +// User.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation +#if canImport(AnyCodable) +import AnyCodable +#endif + +/** A User who is purchasing from the pet store */ + +public struct User: Codable, Hashable { + public var id: Int64? + public var username: String? + public var firstName: String? + public var lastName: String? + public var email: String? + public var password: String? + public var phone: String? + /** User Status */ + public var userStatus: Int? + + public init(id: Int64? = nil, username: String? = nil, firstName: String? = nil, lastName: String? = nil, email: String? = nil, password: String? = nil, phone: String? = nil, userStatus: Int? = nil) { + self.id = id + self.username = username + self.firstName = firstName + self.lastName = lastName + self.email = email + self.password = password + self.phone = phone + self.userStatus = userStatus + } + + public enum CodingKeys: String, CodingKey, CaseIterable { + case id + case username + case firstName + case lastName + case email + case password + case phone + case userStatus + } + + // Encodable protocol methods + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encodeIfPresent(id, forKey: .id) + try container.encodeIfPresent(username, forKey: .username) + try container.encodeIfPresent(firstName, forKey: .firstName) + try container.encodeIfPresent(lastName, forKey: .lastName) + try container.encodeIfPresent(email, forKey: .email) + try container.encodeIfPresent(password, forKey: .password) + try container.encodeIfPresent(phone, forKey: .phone) + try container.encodeIfPresent(userStatus, forKey: .userStatus) + } +} diff --git a/samples/client/petstore/swift/alt/Package.swift b/samples/client/petstore/swift/alt/Package.swift new file mode 100644 index 000000000000..d0919390cf6f --- /dev/null +++ b/samples/client/petstore/swift/alt/Package.swift @@ -0,0 +1,33 @@ +// swift-tools-version:5.1 + +import PackageDescription + +let package = Package( + name: "OpenAPIClient", + platforms: [ + .iOS(.v9), + .macOS(.v10_11), + .tvOS(.v9), + .watchOS(.v3), + ], + products: [ + // Products define the executables and libraries produced by a package, and make them visible to other packages. + .library( + name: "OpenAPIClient", + targets: ["OpenAPIClient"] + ), + ], + dependencies: [ + // Dependencies declare other packages that this package depends on. + .package(url: "https://github.com/Flight-School/AnyCodable", from: "0.6.1"), + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages which this package depends on. + .target( + name: "OpenAPIClient", + dependencies: ["AnyCodable", ], + path: "OpenAPIClient/Classes" + ), + ] +) diff --git a/samples/client/petstore/swift/alt/project.yml b/samples/client/petstore/swift/alt/project.yml new file mode 100644 index 000000000000..f9639e1cd247 --- /dev/null +++ b/samples/client/petstore/swift/alt/project.yml @@ -0,0 +1,15 @@ +name: OpenAPIClient +targets: + OpenAPIClient: + type: framework + platform: iOS + deploymentTarget: "9.0" + sources: [OpenAPIClient] + info: + path: ./Info.plist + version: 1.0.0 + settings: + APPLICATION_EXTENSION_API_ONLY: true + scheme: {} + dependencies: + - carthage: AnyCodable From 48d6f7edbcbd18efe78999c202d3696c4d73f8ff Mon Sep 17 00:00:00 2001 From: Anton Davydov Date: Mon, 25 Oct 2021 19:23:52 +0300 Subject: [PATCH 03/33] swift-alt added runtime --- .../src/main/resources/swift-alt/Old.swift | 1361 +++++++++++++++++ .../main/resources/swift-alt/Runtime.swift | 149 ++ .../swift-alt/_converted_param.mustache | 1 + .../src/main/resources/swift-alt/api.mustache | 600 ++------ .../main/resources/swift-alt/api_old.mustache | 515 +++++++ .../OpenAPIClient.xcodeproj/project.pbxproj | 16 +- .../UserInterfaceState.xcuserstate | Bin 32313 -> 36691 bytes .../Classes/OpenAPIs/APIs/PetAPI.swift | 757 ++++----- .../Classes/OpenAPIs/APIs/StoreAPI.swift | 375 ++--- .../Classes/OpenAPIs/APIs/UserAPI.swift | 697 ++++----- 10 files changed, 2854 insertions(+), 1617 deletions(-) create mode 100644 modules/openapi-generator/src/main/resources/swift-alt/Old.swift create mode 100644 modules/openapi-generator/src/main/resources/swift-alt/Runtime.swift create mode 100644 modules/openapi-generator/src/main/resources/swift-alt/_converted_param.mustache create mode 100644 modules/openapi-generator/src/main/resources/swift-alt/api_old.mustache diff --git a/modules/openapi-generator/src/main/resources/swift-alt/Old.swift b/modules/openapi-generator/src/main/resources/swift-alt/Old.swift new file mode 100644 index 000000000000..6bbe1b0aa9f9 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/swift-alt/Old.swift @@ -0,0 +1,1361 @@ +// +// PetAPI.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation +import Combine +// import Runtime + + +open class PetAPI { + private let transport: Transport + + public init(_ transport: Transport) { + self.transport = transport + } + /** + Add a new pet to the store + - POST /pet + - OAuth: + - type: oauth2 + - name: petstore_auth + - parameter pet: (body) Pet object that needs to be added to the store + - returns: Future + */ + open func addPet(pet: Pet) -> AnyPublisher, Never> { + var request = URLRequest(url: transport.baseURL) + return transport.send(request: request, authType: .none) + .eraseToAnyPublisher() + + } + /** + Deletes a pet + - DELETE /pet/{petId} + - OAuth: + - type: oauth2 + - name: petstore_auth + - parameter petId: (path) Pet id to delete + - parameter apiKey: (header) (optional) + - returns: Future + */ + open func deletePet(petId: Int64, apiKey: String? = nil) -> Future { + } + /** + Finds Pets by status + - GET /pet/findByStatus + - Multiple status values can be provided with comma separated strings + - OAuth: + - type: oauth2 + - name: petstore_auth + - parameter status: () Status values that need to be considered for filter + - returns: Future<[Pet], Never> + */ + open func findPetsByStatus(status: [String]) -> Future<[Pet], Never> { + } + /** + Finds Pets by tags + - GET /pet/findByTags + - Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. + - OAuth: + - type: oauth2 + - name: petstore_auth + - parameter tags: () Tags to filter by + - returns: Future<[Pet], Never> + */ + open func findPetsByTags(tags: [String]) -> Future<[Pet], Never> { + } + /** + Find pet by ID + - GET /pet/{petId} + - Returns a single pet + - API Key: + - type: apiKey api_key + - name: api_key + - parameter petId: (path) ID of pet to return + - returns: Future + */ + open func getPetById(petId: Int64) -> Future { + } + /** + Update an existing pet + - PUT /pet + - OAuth: + - type: oauth2 + - name: petstore_auth + - parameter pet: (body) Pet object that needs to be added to the store + - returns: Future + */ + open func updatePet(pet: Pet) -> Future { + } + /** + Updates a pet in the store with form data + - POST /pet/{petId} + - OAuth: + - type: oauth2 + - name: petstore_auth + - parameter petId: (path) ID of pet that needs to be updated + - parameter name: (form) Updated name of the pet (optional) + - parameter status: (form) Updated status of the pet (optional) + - returns: Future + */ + open func updatePetWithForm(petId: Int64, name: String? = nil, status: String? = nil) -> Future { + } + /** + uploads an image + - POST /pet/{petId}/uploadImage + - OAuth: + - type: oauth2 + - name: petstore_auth + - parameter petId: (path) ID of pet to update + - parameter additionalMetadata: (form) Additional data to pass to server (optional) + - parameter file: (form) file to upload (optional) + - returns: Future + */ + open func uploadFile(petId: Int64, additionalMetadata: String? = nil, file: Data? = nil) -> Future { + } +} +//// + +/** +- + - API Key: + - type: apiKey api_key + - name: api_key + - OAuth: + - type: oauth2 + - name: petstore_auth +- returns: RequestBuilder + */ +open class func WithRequestBuilder() -> RequestBuilder { +let localVariablePath = "" + let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath + let localVariableParameters: [String: Any]? = nil + + let localVariableUrlComponents = URLComponents(string: localVariableURLString) + + let localVariableNillableHeaders: [String: Any?] = [ + : + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() + + return localVariableRequestBuilder.init(method: "", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } + +import Foundation +#if canImport(AnyCodable) +import AnyCodable +#endif + +open class PetAPI { + + /** + Add a new pet to the store + + - parameter pet: (body) Pet object that needs to be added to the store + - parameter apiResponseQueue: The queue on which api response is dispatched. + - parameter completion: completion handler to receive the data and the error objects + */ + open class func addPet(pet: Pet, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Pet?, _ error: Error?) -> Void)) { + addPetWithRequestBuilder(pet: pet).execute(apiResponseQueue) { result in + switch result { + case let .success(response): + completion(response.body, nil) + case let .failure(error): + completion(nil, error) + } + } + } + + /** + Add a new pet to the store + - POST /pet + - OAuth: + - type: oauth2 + - name: petstore_auth + - parameter pet: (body) Pet object that needs to be added to the store + - returns: RequestBuilder + */ + open class func addPetWithRequestBuilder(pet: Pet) -> RequestBuilder { + let localVariablePath = "/pet" + let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath + let localVariableParameters = JSONEncodingHelper.encodingParameters(forEncodableObject: pet) + + let localVariableUrlComponents = URLComponents(string: localVariableURLString) + + let localVariableNillableHeaders: [String: Any?] = [ + : + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getBuilder() + + return localVariableRequestBuilder.init(method: "POST", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } + + /** + Deletes a pet + + - parameter petId: (path) Pet id to delete + - parameter apiKey: (header) (optional) + - parameter apiResponseQueue: The queue on which api response is dispatched. + - parameter completion: completion handler to receive the data and the error objects + */ + open class func deletePet(petId: Int64, apiKey: String? = nil, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Void?, _ error: Error?) -> Void)) { + deletePetWithRequestBuilder(petId: petId, apiKey: apiKey).execute(apiResponseQueue) { result in + switch result { + case .success: + completion((), nil) + case let .failure(error): + completion(nil, error) + } + } + } + + /** + Deletes a pet + - DELETE /pet/{petId} + - OAuth: + - type: oauth2 + - name: petstore_auth + - parameter petId: (path) Pet id to delete + - parameter apiKey: (header) (optional) + - returns: RequestBuilder + */ + open class func deletePetWithRequestBuilder(petId: Int64, apiKey: String? = nil) -> RequestBuilder { + var localVariablePath = "/pet/{petId}" + let petIdPreEscape = "\(APIHelper.mapValueToPathItem(petId))" + let petIdPostEscape = petIdPreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" + localVariablePath = localVariablePath.replacingOccurrences(of: "{petId}", with: petIdPostEscape, options: .literal, range: nil) + let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath + let localVariableParameters: [String: Any]? = nil + + let localVariableUrlComponents = URLComponents(string: localVariableURLString) + + let localVariableNillableHeaders: [String: Any?] = [ + "api_key": apiKey?.encodeToJSON(), + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() + + return localVariableRequestBuilder.init(method: "DELETE", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } + + /** + * enum for parameter status + */ + public enum Status_findPetsByStatus: String, CaseIterable { + case available = "available" + case pending = "pending" + case sold = "sold" + } + + /** + Finds Pets by status + + - parameter status: (query) Status values that need to be considered for filter + - parameter apiResponseQueue: The queue on which api response is dispatched. + - parameter completion: completion handler to receive the data and the error objects + */ + open class func findPetsByStatus(status: [String], apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: [Pet]?, _ error: Error?) -> Void)) { + findPetsByStatusWithRequestBuilder(status: status).execute(apiResponseQueue) { result in + switch result { + case let .success(response): + completion(response.body, nil) + case let .failure(error): + completion(nil, error) + } + } + } + + /** + Finds Pets by status + - GET /pet/findByStatus + - Multiple status values can be provided with comma separated strings + - OAuth: + - type: oauth2 + - name: petstore_auth + - parameter status: (query) Status values that need to be considered for filter + - returns: RequestBuilder<[Pet]> + */ + open class func findPetsByStatusWithRequestBuilder(status: [String]) -> RequestBuilder<[Pet]> { + let localVariablePath = "/pet/findByStatus" + let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath + let localVariableParameters: [String: Any]? = nil + + var localVariableUrlComponents = URLComponents(string: localVariableURLString) + localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems([ + "status": status.encodeToJSON(), + ]) + + let localVariableNillableHeaders: [String: Any?] = [ + : + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder<[Pet]>.Type = OpenAPIClientAPI.requestBuilderFactory.getBuilder() + + return localVariableRequestBuilder.init(method: "GET", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } + + /** + Finds Pets by tags + + - parameter tags: (query) Tags to filter by + - parameter apiResponseQueue: The queue on which api response is dispatched. + - parameter completion: completion handler to receive the data and the error objects + */ + @available(*, deprecated, message: "This operation is deprecated.") + open class func findPetsByTags(tags: [String], apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: [Pet]?, _ error: Error?) -> Void)) { + findPetsByTagsWithRequestBuilder(tags: tags).execute(apiResponseQueue) { result in + switch result { + case let .success(response): + completion(response.body, nil) + case let .failure(error): + completion(nil, error) + } + } + } + + /** + Finds Pets by tags + - GET /pet/findByTags + - Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. + - OAuth: + - type: oauth2 + - name: petstore_auth + - parameter tags: (query) Tags to filter by + - returns: RequestBuilder<[Pet]> + */ + @available(*, deprecated, message: "This operation is deprecated.") + open class func findPetsByTagsWithRequestBuilder(tags: [String]) -> RequestBuilder<[Pet]> { + let localVariablePath = "/pet/findByTags" + let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath + let localVariableParameters: [String: Any]? = nil + + var localVariableUrlComponents = URLComponents(string: localVariableURLString) + localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems([ + "tags": tags.encodeToJSON(), + ]) + + let localVariableNillableHeaders: [String: Any?] = [ + : + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder<[Pet]>.Type = OpenAPIClientAPI.requestBuilderFactory.getBuilder() + + return localVariableRequestBuilder.init(method: "GET", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } + + /** + Find pet by ID + + - parameter petId: (path) ID of pet to return + - parameter apiResponseQueue: The queue on which api response is dispatched. + - parameter completion: completion handler to receive the data and the error objects + */ + open class func getPetById(petId: Int64, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Pet?, _ error: Error?) -> Void)) { + getPetByIdWithRequestBuilder(petId: petId).execute(apiResponseQueue) { result in + switch result { + case let .success(response): + completion(response.body, nil) + case let .failure(error): + completion(nil, error) + } + } + } + + /** + Find pet by ID + - GET /pet/{petId} + - Returns a single pet + - API Key: + - type: apiKey api_key + - name: api_key + - parameter petId: (path) ID of pet to return + - returns: RequestBuilder + */ + open class func getPetByIdWithRequestBuilder(petId: Int64) -> RequestBuilder { + var localVariablePath = "/pet/{petId}" + let petIdPreEscape = "\(APIHelper.mapValueToPathItem(petId))" + let petIdPostEscape = petIdPreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" + localVariablePath = localVariablePath.replacingOccurrences(of: "{petId}", with: petIdPostEscape, options: .literal, range: nil) + let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath + let localVariableParameters: [String: Any]? = nil + + let localVariableUrlComponents = URLComponents(string: localVariableURLString) + + let localVariableNillableHeaders: [String: Any?] = [ + : + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getBuilder() + + return localVariableRequestBuilder.init(method: "GET", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } + + /** + Update an existing pet + + - parameter pet: (body) Pet object that needs to be added to the store + - parameter apiResponseQueue: The queue on which api response is dispatched. + - parameter completion: completion handler to receive the data and the error objects + */ + open class func updatePet(pet: Pet, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Pet?, _ error: Error?) -> Void)) { + updatePetWithRequestBuilder(pet: pet).execute(apiResponseQueue) { result in + switch result { + case let .success(response): + completion(response.body, nil) + case let .failure(error): + completion(nil, error) + } + } + } + + /** + Update an existing pet + - PUT /pet + - OAuth: + - type: oauth2 + - name: petstore_auth + - parameter pet: (body) Pet object that needs to be added to the store + - returns: RequestBuilder + */ + open class func updatePetWithRequestBuilder(pet: Pet) -> RequestBuilder { + let localVariablePath = "/pet" + let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath + let localVariableParameters = JSONEncodingHelper.encodingParameters(forEncodableObject: pet) + + let localVariableUrlComponents = URLComponents(string: localVariableURLString) + + let localVariableNillableHeaders: [String: Any?] = [ + : + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getBuilder() + + return localVariableRequestBuilder.init(method: "PUT", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } + + /** + Updates a pet in the store with form data + + - parameter petId: (path) ID of pet that needs to be updated + - parameter name: (form) Updated name of the pet (optional) + - parameter status: (form) Updated status of the pet (optional) + - parameter apiResponseQueue: The queue on which api response is dispatched. + - parameter completion: completion handler to receive the data and the error objects + */ + open class func updatePetWithForm(petId: Int64, name: String? = nil, status: String? = nil, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Void?, _ error: Error?) -> Void)) { + updatePetWithFormWithRequestBuilder(petId: petId, name: name, status: status).execute(apiResponseQueue) { result in + switch result { + case .success: + completion((), nil) + case let .failure(error): + completion(nil, error) + } + } + } + + /** + Updates a pet in the store with form data + - POST /pet/{petId} + - OAuth: + - type: oauth2 + - name: petstore_auth + - parameter petId: (path) ID of pet that needs to be updated + - parameter name: (form) Updated name of the pet (optional) + - parameter status: (form) Updated status of the pet (optional) + - returns: RequestBuilder + */ + open class func updatePetWithFormWithRequestBuilder(petId: Int64, name: String? = nil, status: String? = nil) -> RequestBuilder { + var localVariablePath = "/pet/{petId}" + let petIdPreEscape = "\(APIHelper.mapValueToPathItem(petId))" + let petIdPostEscape = petIdPreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" + localVariablePath = localVariablePath.replacingOccurrences(of: "{petId}", with: petIdPostEscape, options: .literal, range: nil) + let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath + let localVariableFormParams: [String: Any?] = [ + "name": name?.encodeToJSON(), + "status": status?.encodeToJSON(), + ] + + let localVariableNonNullParameters = APIHelper.rejectNil(localVariableFormParams) + let localVariableParameters = APIHelper.convertBoolToString(localVariableNonNullParameters) + + let localVariableUrlComponents = URLComponents(string: localVariableURLString) + + let localVariableNillableHeaders: [String: Any?] = [ + "Content-Type": "application/x-www-form-urlencoded", + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() + + return localVariableRequestBuilder.init(method: "POST", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } + + /** + uploads an image + + - parameter petId: (path) ID of pet to update + - parameter additionalMetadata: (form) Additional data to pass to server (optional) + - parameter file: (form) file to upload (optional) + - parameter apiResponseQueue: The queue on which api response is dispatched. + - parameter completion: completion handler to receive the data and the error objects + */ + open class func uploadFile(petId: Int64, additionalMetadata: String? = nil, file: Data? = nil, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: ApiResponse?, _ error: Error?) -> Void)) { + uploadFileWithRequestBuilder(petId: petId, additionalMetadata: additionalMetadata, file: file).execute(apiResponseQueue) { result in + switch result { + case let .success(response): + completion(response.body, nil) + case let .failure(error): + completion(nil, error) + } + } + } + + /** + uploads an image + - POST /pet/{petId}/uploadImage + - OAuth: + - type: oauth2 + - name: petstore_auth + - parameter petId: (path) ID of pet to update + - parameter additionalMetadata: (form) Additional data to pass to server (optional) + - parameter file: (form) file to upload (optional) + - returns: RequestBuilder + */ + open class func uploadFileWithRequestBuilder(petId: Int64, additionalMetadata: String? = nil, file: Data? = nil) -> RequestBuilder { + var localVariablePath = "/pet/{petId}/uploadImage" + let petIdPreEscape = "\(APIHelper.mapValueToPathItem(petId))" + let petIdPostEscape = petIdPreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" + localVariablePath = localVariablePath.replacingOccurrences(of: "{petId}", with: petIdPostEscape, options: .literal, range: nil) + let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath + let localVariableFormParams: [String: Any?] = [ + "additionalMetadata": additionalMetadata?.encodeToJSON(), + "file": file?.encodeToJSON(), + ] + + let localVariableNonNullParameters = APIHelper.rejectNil(localVariableFormParams) + let localVariableParameters = APIHelper.convertBoolToString(localVariableNonNullParameters) + + let localVariableUrlComponents = URLComponents(string: localVariableURLString) + + let localVariableNillableHeaders: [String: Any?] = [ + "Content-Type": "multipart/form-data", + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getBuilder() + + return localVariableRequestBuilder.init(method: "POST", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } +} + + +// +// UserAPI.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation +import Combine +// import Runtime + + +open class UserAPI { + private let transport: Transport + + public init(_ transport: Transport) { + self.transport = transport + } + /** + Create user + - POST /user + - This can only be done by the logged in user. + - API Key: + - type: apiKey api_key + - name: api_key + - parameter user: (body) Created user object + - returns: Future + */ + open func createUser(user: User) -> Future { + } + /** + Creates list of users with given input array + - POST /user/createWithArray + - API Key: + - type: apiKey api_key + - name: api_key + - parameter user: (body) List of user object + - returns: Future + */ + open func createUsersWithArrayInput(user: [User]) -> Future { + } + /** + Creates list of users with given input array + - POST /user/createWithList + - API Key: + - type: apiKey api_key + - name: api_key + - parameter user: (body) List of user object + - returns: Future + */ + open func createUsersWithListInput(user: [User]) -> Future { + } + /** + Delete user + - DELETE /user/{username} + - This can only be done by the logged in user. + - API Key: + - type: apiKey api_key + - name: api_key + - parameter username: (path) The name that needs to be deleted + - returns: Future + */ + open func deleteUser(username: String) -> Future { + } + /** + Get user by user name + - GET /user/{username} + - parameter username: (path) The name that needs to be fetched. Use user1 for testing. + - returns: Future + */ + open func getUserByName(username: String) -> Future { + } + /** + Logs user into the system + - GET /user/login + - responseHeaders: [Set-Cookie(String), X-Rate-Limit(Int), X-Expires-After(Date)] + - parameter username: () The user name for login + - parameter password: () The password for login in clear text + - returns: Future + */ + open func loginUser(username: String, password: String) -> Future { + } + /** + Logs out current logged in user session + - GET /user/logout + - API Key: + - type: apiKey api_key + - name: api_key + - returns: Future + */ + open func logoutUser() -> Future { + } + /** + Updated user + - PUT /user/{username} + - This can only be done by the logged in user. + - API Key: + - type: apiKey api_key + - name: api_key + - parameter username: (path) name that need to be deleted + - parameter user: (body) Updated user object + - returns: Future + */ + open func updateUser(username: String, user: User) -> Future { + } +} +//// + +/** +- + - API Key: + - type: apiKey api_key + - name: api_key + - OAuth: + - type: oauth2 + - name: petstore_auth +- returns: RequestBuilder + */ +open class func WithRequestBuilder() -> RequestBuilder { +let localVariablePath = "" + let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath + let localVariableParameters: [String: Any]? = nil + + let localVariableUrlComponents = URLComponents(string: localVariableURLString) + + let localVariableNillableHeaders: [String: Any?] = [ + : + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() + + return localVariableRequestBuilder.init(method: "", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } + +import Foundation +#if canImport(AnyCodable) +import AnyCodable +#endif + +open class UserAPI { + + /** + Create user + + - parameter user: (body) Created user object + - parameter apiResponseQueue: The queue on which api response is dispatched. + - parameter completion: completion handler to receive the data and the error objects + */ + open class func createUser(user: User, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Void?, _ error: Error?) -> Void)) { + createUserWithRequestBuilder(user: user).execute(apiResponseQueue) { result in + switch result { + case .success: + completion((), nil) + case let .failure(error): + completion(nil, error) + } + } + } + + /** + Create user + - POST /user + - This can only be done by the logged in user. + - API Key: + - type: apiKey api_key + - name: api_key + - parameter user: (body) Created user object + - returns: RequestBuilder + */ + open class func createUserWithRequestBuilder(user: User) -> RequestBuilder { + let localVariablePath = "/user" + let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath + let localVariableParameters = JSONEncodingHelper.encodingParameters(forEncodableObject: user) + + let localVariableUrlComponents = URLComponents(string: localVariableURLString) + + let localVariableNillableHeaders: [String: Any?] = [ + : + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() + + return localVariableRequestBuilder.init(method: "POST", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } + + /** + Creates list of users with given input array + + - parameter user: (body) List of user object + - parameter apiResponseQueue: The queue on which api response is dispatched. + - parameter completion: completion handler to receive the data and the error objects + */ + open class func createUsersWithArrayInput(user: [User], apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Void?, _ error: Error?) -> Void)) { + createUsersWithArrayInputWithRequestBuilder(user: user).execute(apiResponseQueue) { result in + switch result { + case .success: + completion((), nil) + case let .failure(error): + completion(nil, error) + } + } + } + + /** + Creates list of users with given input array + - POST /user/createWithArray + - API Key: + - type: apiKey api_key + - name: api_key + - parameter user: (body) List of user object + - returns: RequestBuilder + */ + open class func createUsersWithArrayInputWithRequestBuilder(user: [User]) -> RequestBuilder { + let localVariablePath = "/user/createWithArray" + let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath + let localVariableParameters = JSONEncodingHelper.encodingParameters(forEncodableObject: user) + + let localVariableUrlComponents = URLComponents(string: localVariableURLString) + + let localVariableNillableHeaders: [String: Any?] = [ + : + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() + + return localVariableRequestBuilder.init(method: "POST", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } + + /** + Creates list of users with given input array + + - parameter user: (body) List of user object + - parameter apiResponseQueue: The queue on which api response is dispatched. + - parameter completion: completion handler to receive the data and the error objects + */ + open class func createUsersWithListInput(user: [User], apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Void?, _ error: Error?) -> Void)) { + createUsersWithListInputWithRequestBuilder(user: user).execute(apiResponseQueue) { result in + switch result { + case .success: + completion((), nil) + case let .failure(error): + completion(nil, error) + } + } + } + + /** + Creates list of users with given input array + - POST /user/createWithList + - API Key: + - type: apiKey api_key + - name: api_key + - parameter user: (body) List of user object + - returns: RequestBuilder + */ + open class func createUsersWithListInputWithRequestBuilder(user: [User]) -> RequestBuilder { + let localVariablePath = "/user/createWithList" + let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath + let localVariableParameters = JSONEncodingHelper.encodingParameters(forEncodableObject: user) + + let localVariableUrlComponents = URLComponents(string: localVariableURLString) + + let localVariableNillableHeaders: [String: Any?] = [ + : + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() + + return localVariableRequestBuilder.init(method: "POST", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } + + /** + Delete user + + - parameter username: (path) The name that needs to be deleted + - parameter apiResponseQueue: The queue on which api response is dispatched. + - parameter completion: completion handler to receive the data and the error objects + */ + open class func deleteUser(username: String, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Void?, _ error: Error?) -> Void)) { + deleteUserWithRequestBuilder(username: username).execute(apiResponseQueue) { result in + switch result { + case .success: + completion((), nil) + case let .failure(error): + completion(nil, error) + } + } + } + + /** + Delete user + - DELETE /user/{username} + - This can only be done by the logged in user. + - API Key: + - type: apiKey api_key + - name: api_key + - parameter username: (path) The name that needs to be deleted + - returns: RequestBuilder + */ + open class func deleteUserWithRequestBuilder(username: String) -> RequestBuilder { + var localVariablePath = "/user/{username}" + let usernamePreEscape = "\(APIHelper.mapValueToPathItem(username))" + let usernamePostEscape = usernamePreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" + localVariablePath = localVariablePath.replacingOccurrences(of: "{username}", with: usernamePostEscape, options: .literal, range: nil) + let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath + let localVariableParameters: [String: Any]? = nil + + let localVariableUrlComponents = URLComponents(string: localVariableURLString) + + let localVariableNillableHeaders: [String: Any?] = [ + : + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() + + return localVariableRequestBuilder.init(method: "DELETE", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } + + /** + Get user by user name + + - parameter username: (path) The name that needs to be fetched. Use user1 for testing. + - parameter apiResponseQueue: The queue on which api response is dispatched. + - parameter completion: completion handler to receive the data and the error objects + */ + open class func getUserByName(username: String, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: User?, _ error: Error?) -> Void)) { + getUserByNameWithRequestBuilder(username: username).execute(apiResponseQueue) { result in + switch result { + case let .success(response): + completion(response.body, nil) + case let .failure(error): + completion(nil, error) + } + } + } + + /** + Get user by user name + - GET /user/{username} + - parameter username: (path) The name that needs to be fetched. Use user1 for testing. + - returns: RequestBuilder + */ + open class func getUserByNameWithRequestBuilder(username: String) -> RequestBuilder { + var localVariablePath = "/user/{username}" + let usernamePreEscape = "\(APIHelper.mapValueToPathItem(username))" + let usernamePostEscape = usernamePreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" + localVariablePath = localVariablePath.replacingOccurrences(of: "{username}", with: usernamePostEscape, options: .literal, range: nil) + let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath + let localVariableParameters: [String: Any]? = nil + + let localVariableUrlComponents = URLComponents(string: localVariableURLString) + + let localVariableNillableHeaders: [String: Any?] = [ + : + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getBuilder() + + return localVariableRequestBuilder.init(method: "GET", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } + + /** + Logs user into the system + + - parameter username: (query) The user name for login + - parameter password: (query) The password for login in clear text + - parameter apiResponseQueue: The queue on which api response is dispatched. + - parameter completion: completion handler to receive the data and the error objects + */ + open class func loginUser(username: String, password: String, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: String?, _ error: Error?) -> Void)) { + loginUserWithRequestBuilder(username: username, password: password).execute(apiResponseQueue) { result in + switch result { + case let .success(response): + completion(response.body, nil) + case let .failure(error): + completion(nil, error) + } + } + } + + /** + Logs user into the system + - GET /user/login + - responseHeaders: [Set-Cookie(String), X-Rate-Limit(Int), X-Expires-After(Date)] + - parameter username: (query) The user name for login + - parameter password: (query) The password for login in clear text + - returns: RequestBuilder + */ + open class func loginUserWithRequestBuilder(username: String, password: String) -> RequestBuilder { + let localVariablePath = "/user/login" + let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath + let localVariableParameters: [String: Any]? = nil + + var localVariableUrlComponents = URLComponents(string: localVariableURLString) + localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems([ + "username": username.encodeToJSON(), + "password": password.encodeToJSON(), + ]) + + let localVariableNillableHeaders: [String: Any?] = [ + : + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getBuilder() + + return localVariableRequestBuilder.init(method: "GET", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } + + /** + Logs out current logged in user session + + - parameter apiResponseQueue: The queue on which api response is dispatched. + - parameter completion: completion handler to receive the data and the error objects + */ + open class func logoutUser(apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Void?, _ error: Error?) -> Void)) { + logoutUserWithRequestBuilder().execute(apiResponseQueue) { result in + switch result { + case .success: + completion((), nil) + case let .failure(error): + completion(nil, error) + } + } + } + + /** + Logs out current logged in user session + - GET /user/logout + - API Key: + - type: apiKey api_key + - name: api_key + - returns: RequestBuilder + */ + open class func logoutUserWithRequestBuilder() -> RequestBuilder { + let localVariablePath = "/user/logout" + let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath + let localVariableParameters: [String: Any]? = nil + + let localVariableUrlComponents = URLComponents(string: localVariableURLString) + + let localVariableNillableHeaders: [String: Any?] = [ + : + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() + + return localVariableRequestBuilder.init(method: "GET", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } + + /** + Updated user + + - parameter username: (path) name that need to be deleted + - parameter user: (body) Updated user object + - parameter apiResponseQueue: The queue on which api response is dispatched. + - parameter completion: completion handler to receive the data and the error objects + */ + open class func updateUser(username: String, user: User, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Void?, _ error: Error?) -> Void)) { + updateUserWithRequestBuilder(username: username, user: user).execute(apiResponseQueue) { result in + switch result { + case .success: + completion((), nil) + case let .failure(error): + completion(nil, error) + } + } + } + + /** + Updated user + - PUT /user/{username} + - This can only be done by the logged in user. + - API Key: + - type: apiKey api_key + - name: api_key + - parameter username: (path) name that need to be deleted + - parameter user: (body) Updated user object + - returns: RequestBuilder + */ + open class func updateUserWithRequestBuilder(username: String, user: User) -> RequestBuilder { + var localVariablePath = "/user/{username}" + let usernamePreEscape = "\(APIHelper.mapValueToPathItem(username))" + let usernamePostEscape = usernamePreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" + localVariablePath = localVariablePath.replacingOccurrences(of: "{username}", with: usernamePostEscape, options: .literal, range: nil) + let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath + let localVariableParameters = JSONEncodingHelper.encodingParameters(forEncodableObject: user) + + let localVariableUrlComponents = URLComponents(string: localVariableURLString) + + let localVariableNillableHeaders: [String: Any?] = [ + : + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() + + return localVariableRequestBuilder.init(method: "PUT", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } +} + + +// +// StoreAPI.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation +import Combine +// import Runtime + + +open class StoreAPI { + private let transport: Transport + + public init(_ transport: Transport) { + self.transport = transport + } + /** + Delete purchase order by ID + - DELETE /store/order/{orderId} + - For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors + - parameter orderId: (path) ID of the order that needs to be deleted + - returns: Future + */ + open func deleteOrder(orderId: String) -> Future { + } + /** + Returns pet inventories by status + - GET /store/inventory + - Returns a map of status codes to quantities + - API Key: + - type: apiKey api_key + - name: api_key + - returns: Future<[String: Int], Never> + */ + open func getInventory() -> Future<[String: Int], Never> { + } + /** + Find purchase order by ID + - GET /store/order/{orderId} + - For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions + - parameter orderId: (path) ID of pet that needs to be fetched + - returns: Future + */ + open func getOrderById(orderId: Int64) -> Future { + } + /** + Place an order for a pet + - POST /store/order + - parameter order: (body) order placed for purchasing the pet + - returns: Future + */ + open func placeOrder(order: Order) -> Future { + } +} +//// + +/** +- + - API Key: + - type: apiKey api_key + - name: api_key + - OAuth: + - type: oauth2 + - name: petstore_auth +- returns: RequestBuilder + */ +open class func WithRequestBuilder() -> RequestBuilder { +let localVariablePath = "" + let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath + let localVariableParameters: [String: Any]? = nil + + let localVariableUrlComponents = URLComponents(string: localVariableURLString) + + let localVariableNillableHeaders: [String: Any?] = [ + : + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() + + return localVariableRequestBuilder.init(method: "", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } + +import Foundation +#if canImport(AnyCodable) +import AnyCodable +#endif + +open class StoreAPI { + + /** + Delete purchase order by ID + + - parameter orderId: (path) ID of the order that needs to be deleted + - parameter apiResponseQueue: The queue on which api response is dispatched. + - parameter completion: completion handler to receive the data and the error objects + */ + open class func deleteOrder(orderId: String, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Void?, _ error: Error?) -> Void)) { + deleteOrderWithRequestBuilder(orderId: orderId).execute(apiResponseQueue) { result in + switch result { + case .success: + completion((), nil) + case let .failure(error): + completion(nil, error) + } + } + } + + /** + Delete purchase order by ID + - DELETE /store/order/{orderId} + - For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors + - parameter orderId: (path) ID of the order that needs to be deleted + - returns: RequestBuilder + */ + open class func deleteOrderWithRequestBuilder(orderId: String) -> RequestBuilder { + var localVariablePath = "/store/order/{orderId}" + let orderIdPreEscape = "\(APIHelper.mapValueToPathItem(orderId))" + let orderIdPostEscape = orderIdPreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" + localVariablePath = localVariablePath.replacingOccurrences(of: "{orderId}", with: orderIdPostEscape, options: .literal, range: nil) + let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath + let localVariableParameters: [String: Any]? = nil + + let localVariableUrlComponents = URLComponents(string: localVariableURLString) + + let localVariableNillableHeaders: [String: Any?] = [ + : + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() + + return localVariableRequestBuilder.init(method: "DELETE", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } + + /** + Returns pet inventories by status + + - parameter apiResponseQueue: The queue on which api response is dispatched. + - parameter completion: completion handler to receive the data and the error objects + */ + open class func getInventory(apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: [String: Int]?, _ error: Error?) -> Void)) { + getInventoryWithRequestBuilder().execute(apiResponseQueue) { result in + switch result { + case let .success(response): + completion(response.body, nil) + case let .failure(error): + completion(nil, error) + } + } + } + + /** + Returns pet inventories by status + - GET /store/inventory + - Returns a map of status codes to quantities + - API Key: + - type: apiKey api_key + - name: api_key + - returns: RequestBuilder<[String: Int]> + */ + open class func getInventoryWithRequestBuilder() -> RequestBuilder<[String: Int]> { + let localVariablePath = "/store/inventory" + let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath + let localVariableParameters: [String: Any]? = nil + + let localVariableUrlComponents = URLComponents(string: localVariableURLString) + + let localVariableNillableHeaders: [String: Any?] = [ + : + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder<[String: Int]>.Type = OpenAPIClientAPI.requestBuilderFactory.getBuilder() + + return localVariableRequestBuilder.init(method: "GET", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } + + /** + Find purchase order by ID + + - parameter orderId: (path) ID of pet that needs to be fetched + - parameter apiResponseQueue: The queue on which api response is dispatched. + - parameter completion: completion handler to receive the data and the error objects + */ + open class func getOrderById(orderId: Int64, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Order?, _ error: Error?) -> Void)) { + getOrderByIdWithRequestBuilder(orderId: orderId).execute(apiResponseQueue) { result in + switch result { + case let .success(response): + completion(response.body, nil) + case let .failure(error): + completion(nil, error) + } + } + } + + /** + Find purchase order by ID + - GET /store/order/{orderId} + - For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions + - parameter orderId: (path) ID of pet that needs to be fetched + - returns: RequestBuilder + */ + open class func getOrderByIdWithRequestBuilder(orderId: Int64) -> RequestBuilder { + var localVariablePath = "/store/order/{orderId}" + let orderIdPreEscape = "\(APIHelper.mapValueToPathItem(orderId))" + let orderIdPostEscape = orderIdPreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" + localVariablePath = localVariablePath.replacingOccurrences(of: "{orderId}", with: orderIdPostEscape, options: .literal, range: nil) + let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath + let localVariableParameters: [String: Any]? = nil + + let localVariableUrlComponents = URLComponents(string: localVariableURLString) + + let localVariableNillableHeaders: [String: Any?] = [ + : + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getBuilder() + + return localVariableRequestBuilder.init(method: "GET", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } + + /** + Place an order for a pet + + - parameter order: (body) order placed for purchasing the pet + - parameter apiResponseQueue: The queue on which api response is dispatched. + - parameter completion: completion handler to receive the data and the error objects + */ + open class func placeOrder(order: Order, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Order?, _ error: Error?) -> Void)) { + placeOrderWithRequestBuilder(order: order).execute(apiResponseQueue) { result in + switch result { + case let .success(response): + completion(response.body, nil) + case let .failure(error): + completion(nil, error) + } + } + } + + /** + Place an order for a pet + - POST /store/order + - parameter order: (body) order placed for purchasing the pet + - returns: RequestBuilder + */ + open class func placeOrderWithRequestBuilder(order: Order) -> RequestBuilder { + let localVariablePath = "/store/order" + let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath + let localVariableParameters = JSONEncodingHelper.encodingParameters(forEncodableObject: order) + + let localVariableUrlComponents = URLComponents(string: localVariableURLString) + + let localVariableNillableHeaders: [String: Any?] = [ + : + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getBuilder() + + return localVariableRequestBuilder.init(method: "POST", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } +} diff --git a/modules/openapi-generator/src/main/resources/swift-alt/Runtime.swift b/modules/openapi-generator/src/main/resources/swift-alt/Runtime.swift new file mode 100644 index 000000000000..65f3d797d7ed --- /dev/null +++ b/modules/openapi-generator/src/main/resources/swift-alt/Runtime.swift @@ -0,0 +1,149 @@ +//struct FeedbackData: Codable { +//} +// +//struct Feedback: Codable { +// let user: String +// let currentDate: Date +// let param: String +// let data: FeedbackData +//} +// +//struct FeedbackOutput: Codable { +//} +// +//struct SupportService { +// let transport: Transport +// +// init(_ transport: Transport) { +// self.transport = transport +// } +// +// func sendFeedback(_ feedback: Feedback) -> AnyPublisher, Never> { +// +// let url: URL = transport.baseURL.appending("/feedback") +// + feedback.user.encode.urlEncode + +// "&" + feedback.currentDate.encode.urlEncode +// +// var request = URLRequest(url: url) +// +// request.httpMethod = "POST" +// request.setValue(feedback.param, forHTTPHeaderField: "param") +// request.httpBody = try? JSONEncoder().encode(feedback.data) +// +// return transport.send(request, auth: .httpBearer) +// .map { +// map($0) +// } +// .eraseToAnyPublisher() +// } +// +// private func map(_ response: TransportResponse) -> Result { +// // 200, 401, 403 +// switch response.response.statusCode { +// case 200: +// if let data = response.data, let value = try? JSONDecoder().decode(FeedbackOutput.self, from: data) { +// return .success(value) +// } +// default: +// return .failure(response.error ?? .unknown) +// } +// } +//} +// +//class SwooAuthService { +//} + +/// Runtime + +import Foundation +import Combine + +public enum SecurityScheme { + case none + // Other schemes not supported yet https://swagger.io/docs/specification/authentication/ +} + +public protocol HTTPAuth { + func bearer() -> Future +} + +public enum TransportError: Error { + case noInternetConnection + case unknown +} + +public struct TransportResponse { + public let data: Data? + public let response: HTTPURLResponse? + public let error: TransportError? +} + +public protocol Transport { + var baseURL: URL { get } + func send(request: URLRequest, securityScheme: SecurityScheme) -> Future +} + +public class URLSessionTransport: Transport { + let session: URLSession + let auth: HTTPAuth + public var baseURL: URL + public var commonHeaders: [String: String] = [:] + + public init(session: URLSession = .shared, baseURL: URL, auth: HTTPAuth) { + self.session = session + self.auth = auth + self.baseURL = baseURL + } + + public func send(request: URLRequest, securityScheme: SecurityScheme) -> Future { + Future { promise in + // TODO: add headers to requests + promise(.success(TransportResponse(data: nil, response: nil, error: nil))) + } + } +} + +/// Client + +//class SwooHTTPAuth: HTTPAuth { +// private(set) var bearer: String? +// +// func bearer() -> Future { +// Future { promise in promise(.success("")) } +// } +// +//// func bearer() -> Future { +//// guard let bearer = _bearer else { +//// return renew() +//// } +//// return Future { promice in +//// .. +//// } +//// } +// +// func renew() -> Future { +// +// } +//} +// +//enum Config { +// static let authBaseURL = "https://swoo.auth.com" +// static let feedbackBaseURL = "https://swoo.feedback.com" +//} +// +//let authTransport = DefaultTransport(Config.authBaseURL) +//let authService = SwooAuthService(authTransport) +//let swooHTTPAuth = SwooHTTPAuth(authService: authService) +// +//let transport = URLSessionTransport(baseURL: Config.feedbackBaseURL, auth: swooHTTPAuth) +//let service = SupportService(transport) +// +//service.sendFeedback(Feedback(user: "User", currentDate: .now(), param: "param", data: .init())) +// .sink { result in +// .. +// } +// .store(...) + +// Open questions +// - cancellation - is it really needed? +// - httpauth - should the bearer be future or just for renew procedure? diff --git a/modules/openapi-generator/src/main/resources/swift-alt/_converted_param.mustache b/modules/openapi-generator/src/main/resources/swift-alt/_converted_param.mustache new file mode 100644 index 000000000000..458b624d1410 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/swift-alt/_converted_param.mustache @@ -0,0 +1 @@ +{{#isArray}}{{paramName}}{{^required}}?{{/required}}.joined(separator: ", "){{/isArray}}{{^isArray}}{{paramName}}{{/isArray}} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/swift-alt/api.mustache b/modules/openapi-generator/src/main/resources/swift-alt/api.mustache index 9708cffcca11..80257dab5684 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/api.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/api.mustache @@ -3,7 +3,7 @@ // // Generated by openapi-generator // https://openapi-generator.tech -// +// Run in root folder to build example mvn clean package -DskipTests; ./bin/generate-samples.sh bin/configs/swift-alt-petstore-new.yaml import Foundation import Combine @@ -12,18 +12,29 @@ import Combine {{#description}} /** {{{.}}} */{{/description}} open class {{classname}} { + private let encoder: JSONEncoder = { + let encoder = JSONEncoder() + encoder.dateEncodingStrategy = .formatted(OpenISO8601DateFormatter()) + encoder.outputFormatting = .prettyPrinted + return encoder + }() + private let decoder: JSONDecoder = { + let decoder = JSONDecoder() + decoder.dateDecodingStrategy = .formatted(OpenISO8601DateFormatter()) + return decoder + }() private let transport: Transport public init(_ transport: Transport) { self.transport = transport } {{#operation}} - + /** {{#summary}} {{{.}}} {{/summary}} - - {{httpMethod}} {{{path}}}{{#notes}} + - {{httpMethod}} {{{path}}}{{#notes}} - {{{.}}}{{/notes}}{{#subresourceOperation}} - subresourceOperation: {{.}}{{/subresourceOperation}}{{#defaultResponse}} - defaultResponse: {{.}}{{/defaultResponse}} @@ -39,521 +50,98 @@ open class {{classname}} { - externalDocs: {{.}} {{/externalDocs}} {{#allParams}} - - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} {{/allParams}} - - returns: Future<{{{returnType}}}{{^returnType}}Void{{/returnType}}, Never> {{description}} + - returns: AnyPublisher, Never> {{description}} */ - open func {{operationId}}({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}) -> Future<{{{returnType}}}{{^returnType}}Void{{/returnType}}, Never> { - } -{{/operation}} -} -//// - -/** -{{#summary}} - {{{.}}} -{{/summary}} -- {{httpMethod}} {{{path}}}{{#notes}} - - {{{.}}}{{/notes}}{{#subresourceOperation}} - - subresourceOperation: {{.}}{{/subresourceOperation}}{{#defaultResponse}} - - defaultResponse: {{.}}{{/defaultResponse}} -{{#authMethods}} - - {{#isBasic}}BASIC{{/isBasic}}{{#isOAuth}}OAuth{{/isOAuth}}{{#isApiKey}}API Key{{/isApiKey}}: - - type: {{type}}{{#keyParamName}} {{keyParamName}} {{#isKeyInQuery}}(QUERY){{/isKeyInQuery}}{{#isKeyInHeaer}}(HEADER){{/isKeyInHeaer}}{{/keyParamName}} - - name: {{name}} -{{/authMethods}} -{{#hasResponseHeaders}} - - responseHeaders: [{{#responseHeaders}}{{{baseName}}}({{{dataType}}}){{^-last}}, {{/-last}}{{/responseHeaders}}] -{{/hasResponseHeaders}} -{{#externalDocs}} - - externalDocs: {{.}} -{{/externalDocs}} -{{#allParams}} - - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} -{{/allParams}} -- returns: RequestBuilder<{{{returnType}}}{{^returnType}}Void{{/returnType}}> {{description}} - */ -{{#isDeprecated}} - @available(*, deprecated, message: "This operation is deprecated.") -{{/isDeprecated}} -{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class func {{operationId}}WithRequestBuilder({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}) -> RequestBuilder<{{{returnType}}}{{^returnType}}Void{{/returnType}}> { -{{^pathParams}}let{{/pathParams}}{{#pathParams}}{{#-first}}var{{/-first}}{{/pathParams}} localVariablePath = "{{{path}}}"{{#pathParams}} - let {{paramName}}PreEscape = "\({{#isEnum}}{{paramName}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}.rawValue{{/isContainer}}{{/isEnum}}{{^isEnum}}APIHelper.mapValueToPathItem({{paramName}}){{/isEnum}})" - let {{paramName}}PostEscape = {{paramName}}PreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" - localVariablePath = localVariablePath.replacingOccurrences(of: "{{=<% %>=}}{<%baseName%>}<%={{ }}=%>", with: {{paramName}}PostEscape, options: .literal, range: nil){{/pathParams}} - let localVariableURLString = {{projectName}}API.basePath + localVariablePath -{{#bodyParam}} - let localVariableParameters = JSONEncodingHelper.encodingParameters(forEncodableObject: {{paramName}}) -{{/bodyParam}} -{{^bodyParam}} - {{#hasFormParams}} - let localVariableFormParams: [String: Any?] = [ - {{#formParams}} - {{> _param}}, - {{/formParams}} - ] - - let localVariableNonNullParameters = APIHelper.rejectNil(localVariableFormParams) - let localVariableParameters = APIHelper.convertBoolToString(localVariableNonNullParameters) - {{/hasFormParams}} - {{^hasFormParams}} - let localVariableParameters: [String: Any]? = nil - {{/hasFormParams}} -{{/bodyParam}}{{#hasQueryParams}} - var localVariableUrlComponents = URLComponents(string: localVariableURLString) - localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems([{{^queryParams}}:{{/queryParams}} - {{#queryParams}} - {{> _param}}, - {{/queryParams}} - ]){{/hasQueryParams}}{{^hasQueryParams}} - let localVariableUrlComponents = URLComponents(string: localVariableURLString){{/hasQueryParams}} - - let localVariableNillableHeaders: [String: Any?] = [{{^headerParams}}{{^hasFormParams}} - :{{/hasFormParams}}{{/headerParams}}{{#hasFormParams}} - "Content-Type": {{^consumes}}"multipart/form-data"{{/consumes}}{{#consumes.0}}"{{{mediaType}}}"{{/consumes.0}},{{/hasFormParams}}{{#headerParams}} - {{> _param}},{{/headerParams}} - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder<{{{returnType}}}{{^returnType}}Void{{/returnType}}>.Type = {{projectName}}API.requestBuilderFactory.{{#returnType}}getBuilder(){{/returnType}}{{^returnType}}getNonDecodableBuilder(){{/returnType}} - - return localVariableRequestBuilder.init(method: "{{httpMethod}}", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) - } - -import Foundation{{#usePromiseKit}} -import PromiseKit{{/usePromiseKit}}{{#useRxSwift}} -import RxSwift{{/useRxSwift}}{{#useCombine}} -#if canImport(Combine) -import Combine -#endif{{/useCombine}}{{#useVapor}} -import Vapor{{/useVapor}} -#if canImport(AnyCodable) -import AnyCodable -#endif{{#swiftUseApiNamespace}} - -extension {{projectName}}API { -{{/swiftUseApiNamespace}} - -{{#description}} -/** {{{.}}} */{{/description}} -{{#objcCompatible}}@objc {{/objcCompatible}}{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class {{classname}}{{#objcCompatible}} : NSObject{{/objcCompatible}} { -{{#operation}} - - {{#allParams}} - {{#isEnum}} - /** - * enum for parameter {{paramName}} - */ - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} enum {{enumName}}_{{operationId}}: {{^isContainer}}{{{dataType}}}{{/isContainer}}{{#isContainer}}String{{/isContainer}}, CaseIterable{{#useVapor}}, Content{{/useVapor}} { - {{#allowableValues}} - {{#enumVars}} - case {{name}} = {{{value}}} - {{/enumVars}} - {{/allowableValues}} - } - - {{/isEnum}} - {{/allParams}} -{{^useVapor}} -{{^usePromiseKit}} -{{^useRxSwift}} -{{^useResult}} -{{^useCombine}} -{{^useAsyncAwait}} - /** - {{#summary}} - {{{.}}} - {{/summary}}{{#allParams}} - - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}} - - parameter apiResponseQueue: The queue on which api response is dispatched. - - parameter completion: completion handler to receive the data and the error objects - */ - {{#isDeprecated}} - @available(*, deprecated, message: "This operation is deprecated.") - {{/isDeprecated}} - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class func {{operationId}}({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}apiResponseQueue: DispatchQueue = {{projectName}}API.apiResponseQueue, completion: @escaping ((_ data: {{{returnType}}}{{^returnType}}Void{{/returnType}}?, _ error: Error?) -> Void)) { - {{operationId}}WithRequestBuilder({{#allParams}}{{paramName}}: {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}).execute(apiResponseQueue) { result in - switch result { - {{#returnType}} - case let .success(response): - completion(response.body, nil) - {{/returnType}} - {{^returnType}} - case .success: - completion((), nil) - {{/returnType}} - case let .failure(error): - completion(nil, error) - } - } - } -{{/useAsyncAwait}} -{{/useCombine}} -{{/useResult}} -{{/useRxSwift}} -{{/usePromiseKit}} -{{/useVapor}} -{{#usePromiseKit}} - /** - {{#summary}} - {{{.}}} - {{/summary}}{{#allParams}} - - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}} - - parameter apiResponseQueue: The queue on which api response is dispatched. - - returns: Promise<{{{returnType}}}{{^returnType}}Void{{/returnType}}> - */ - {{#isDeprecated}} - @available(*, deprecated, message: "This operation is deprecated.") - {{/isDeprecated}} - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class func {{operationId}}({{#allParams}} {{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}apiResponseQueue: DispatchQueue = {{projectName}}API.apiResponseQueue) -> Promise<{{{returnType}}}{{^returnType}}Void{{/returnType}}> { - let deferred = Promise<{{{returnType}}}{{^returnType}}Void{{/returnType}}>.pending() - {{operationId}}WithRequestBuilder({{#allParams}}{{paramName}}: {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}).execute(apiResponseQueue) { result in - switch result { - {{#returnType}} - case let .success(response): - deferred.resolver.fulfill(response.body!) - {{/returnType}} - {{^returnType}} - case .success: - deferred.resolver.fulfill(()) - {{/returnType}} - case let .failure(error): - deferred.resolver.reject(error) - } - } - return deferred.promise - } -{{/usePromiseKit}} -{{#useRxSwift}} - /** - {{#summary}} - {{{.}}} - {{/summary}}{{#allParams}} - - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}} - - parameter apiResponseQueue: The queue on which api response is dispatched. - - returns: Observable<{{{returnType}}}{{^returnType}}Void{{/returnType}}> - */ - {{#isDeprecated}} - @available(*, deprecated, message: "This operation is deprecated.") - {{/isDeprecated}} - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class func {{operationId}}({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}apiResponseQueue: DispatchQueue = {{projectName}}API.apiResponseQueue) -> Observable<{{{returnType}}}{{^returnType}}Void{{/returnType}}> { - return Observable.create { observer -> Disposable in - {{operationId}}WithRequestBuilder({{#allParams}}{{paramName}}: {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}).execute(apiResponseQueue) { result in - switch result { - {{#returnType}} - case let .success(response): - observer.onNext(response.body!) - {{/returnType}} - {{^returnType}} - case .success: - observer.onNext(()) - {{/returnType}} - case let .failure(error): - observer.onError(error) - } - observer.onCompleted() - } - return Disposables.create() + open func {{operationId}}({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}) -> AnyPublisher, Never> { + // Creating final URL with query items and path + var components = URLComponents() + components.path = "{{path}}" + {{#pathParams}} + {{! TODO: Convert param name to string if needed (can be nil, can be container) }} + .replacingOccurrences(of: "{{=<% %>=}}{<%baseName%>}<%={{ }}=%>", with: "\({{paramName}})") + {{/pathParams}} + {{#hasQueryParams}}components.queryItems = [ + {{#queryParams}} + {{! TODO: Convert value to string if needed (can be nil, can be container) }} + URLQueryItem(name: "{{paramName}}", value: {{#isArray}}{{paramName}}{{^required}}?{{/required}}.joined(separator: ", "){{/isArray}}{{^isArray}}{{paramName}}{{/isArray}}){{^-last}}, {{/-last}} + {{/queryParams}} + ]{{/hasQueryParams}} + guard let url = components.url(relativeTo: transport.baseURL) else { + {{! TODO: Process error correctly }} + fatalError("URL is nil") } - } -{{/useRxSwift}} -{{#useCombine}} - /** - {{#summary}} - {{{.}}} - {{/summary}}{{#allParams}} - - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}} - - parameter apiResponseQueue: The queue on which api response is dispatched. - - returns: AnyPublisher<{{{returnType}}}{{^returnType}}Void{{/returnType}}, Error> - */ - #if canImport(Combine) - {{#isDeprecated}} - @available(*, deprecated, message: "This operation is deprecated.") - {{/isDeprecated}} - @available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *) - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class func {{operationId}}({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}apiResponseQueue: DispatchQueue = {{projectName}}API.apiResponseQueue) -> AnyPublisher<{{{returnType}}}{{^returnType}}Void{{/returnType}}, Error> { - return Future<{{{returnType}}}{{^returnType}}Void{{/returnType}}, Error> { promise in - {{operationId}}WithRequestBuilder({{#allParams}}{{paramName}}: {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}).execute(apiResponseQueue) { result in - switch result { - {{#returnType}} - case let .success(response): - promise(.success(response.body!)) - {{/returnType}} - {{^returnType}} - case .success: - promise(.success(())) - {{/returnType}} - case let .failure(error): - promise(.failure(error)) - } - } - }.eraseToAnyPublisher() - } - #endif -{{/useCombine}} -{{#useAsyncAwait}} - /** - {{#summary}} - {{{.}}} - {{/summary}}{{#allParams}} - - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}} - - parameter apiResponseQueue: The queue on which api response is dispatched. - - returns: {{{returnType}}}{{^returnType}}Void{{/returnType}} - */ - {{#isDeprecated}} - @available(*, deprecated, message: "This operation is deprecated.") - {{/isDeprecated}} - @available(macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0, *) - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class func {{operationId}}({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}apiResponseQueue: DispatchQueue = {{projectName}}API.apiResponseQueue) async throws{{#returnType}} -> {{{returnType}}}{{/returnType}} { - return try await withCheckedThrowingContinuation { continuation in - {{operationId}}WithRequestBuilder({{#allParams}}{{paramName}}: {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}).execute(apiResponseQueue) { result in - switch result { - {{#returnType}} - case let .success(response): - continuation.resume(returning: response.body!) - {{/returnType}} - {{^returnType}} - case .success: - continuation.resume(returning: ()) - {{/returnType}} - case let .failure(error): - continuation.resume(throwing: error) + + var request = URLRequest(url: url) + request.httpMethod = "{{httpMethod}}" + {{#hasHeaderParams}}// Setting headers + request.allHTTPHeaderFields = [{{^headerParams}}{{^hasFormParams}} + :{{/hasFormParams}}{{/headerParams}}{{#hasFormParams}} + "Content-Type": {{^consumes}}"multipart/form-data"{{/consumes}}{{#consumes.0}}"{{{mediaType}}}"{{/consumes.0}},{{/hasFormParams}}{{#headerParams}} + {{! TODO: Convert value to string if needed (can be nil, can be container) }} + "{{baseName}}": {{paramName}}{{^-last}}, {{/-last}}{{/headerParams}} + ].compactMapValues { $0 }{{/hasHeaderParams}} + {{#hasBodyParam}}{{#bodyParam}}// Setting body parameters {{! TODO: Convert value to data if needed (can be nil, can be Data already) }} + request.httpBody = try? encoder.encode({{paramName}}){{/bodyParam}}{{/hasBodyParam}} + // Getting auth type {{! TODO: Set proper auth type) }} + let securityScheme: SecurityScheme = .none + return transport.send(request: request, securityScheme: securityScheme) + .map { response -> Result<{{{returnType}}}{{^returnType}}Void{{/returnType}}, Error> in + {{! TODO: Check responses properly }} + if response.response?.statusCode == 200 { + {{#returnType}} + if let data = response.data { + return Result { try self.decoder.decode({{{returnType}}}.self, from: data) } + } else { + return .failure(TransportError.unknown) + } + {{/returnType}} + {{^returnType}} + return .success(()) + {{/returnType}} + } else { + return .failure(response.error ?? TransportError.unknown) } } - } - } -{{/useAsyncAwait}} -{{#useResult}} - /** - {{#summary}} - {{{.}}} - {{/summary}}{{#allParams}} - - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}} - - parameter apiResponseQueue: The queue on which api response is dispatched. - - parameter completion: completion handler to receive the result - */ - {{#isDeprecated}} - @available(*, deprecated, message: "This operation is deprecated.") - {{/isDeprecated}} - open class func {{operationId}}({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}apiResponseQueue: DispatchQueue = {{projectName}}API.apiResponseQueue, completion: @escaping ((_ result: Swift.Result<{{{returnType}}}{{^returnType}}Void{{/returnType}}, ErrorResponse>) -> Void)) { - {{operationId}}WithRequestBuilder({{#allParams}}{{paramName}}: {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}).execute(apiResponseQueue) { result in - switch result { - {{#returnType}} - case let .success(response): - completion(.success(response.body!)) - {{/returnType}} - {{^returnType}} - case .success: - completion(.success(())) - {{/returnType}} - case let .failure(error): - completion(.failure(error)) - } - } + .eraseToAnyPublisher() } -{{/useResult}} -{{#useVapor}} - /** - {{#summary}} - {{{.}}} - {{/summary}} - {{httpMethod}} {{{path}}}{{#notes}} - {{{.}}}{{/notes}}{{#subresourceOperation}} - subresourceOperation: {{.}}{{/subresourceOperation}}{{#defaultResponse}} - defaultResponse: {{.}}{{/defaultResponse}} - {{#authMethods}} - - {{#isBasic}}BASIC{{/isBasic}}{{#isOAuth}}OAuth{{/isOAuth}}{{#isApiKey}}API Key{{/isApiKey}}: - - type: {{type}}{{#keyParamName}} {{keyParamName}} {{#isKeyInQuery}}(QUERY){{/isKeyInQuery}}{{#isKeyInHeaer}}(HEADER){{/isKeyInHeaer}}{{/keyParamName}} - - name: {{name}} - {{/authMethods}} - {{#hasResponseHeaders}} - - responseHeaders: [{{#responseHeaders}}{{{baseName}}}({{{dataType}}}){{^-last}}, {{/-last}}{{/responseHeaders}}] - {{/hasResponseHeaders}} - {{#externalDocs}} - - externalDocs: {{.}} - {{/externalDocs}} - {{#allParams}} - - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{{description}}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} - {{/allParams}} - - returns: `EventLoopFuture` of `ClientResponse` {{{description}}} - */ - {{#isDeprecated}} - @available(*, deprecated, message: "This operation is deprecated.") - {{/isDeprecated}} - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class func {{operationId}}Raw({{#allParams}}{{paramName}}: {{#isEnum}}{{#isArray}}[{{enumName}}_{{operationId}}]{{/isArray}}{{^isArray}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isArray}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}headers: HTTPHeaders = {{projectName}}API.customHeaders, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { - {{^pathParams}}let{{/pathParams}}{{#pathParams}}{{#-first}}var{{/-first}}{{/pathParams}} localVariablePath = "{{{path}}}"{{#pathParams}} - let {{paramName}}PreEscape = String(describing: {{#isEnum}}{{paramName}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}.rawValue{{/isContainer}}{{/isEnum}}{{^isEnum}}{{paramName}}{{/isEnum}}) - let {{paramName}}PostEscape = {{paramName}}PreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" - localVariablePath = localVariablePath.replacingOccurrences(of: "{{=<% %>=}}{<%baseName%>}<%={{ }}=%>", with: {{paramName}}PostEscape, options: .literal, range: nil){{/pathParams}} - let localVariableURLString = {{projectName}}API.basePath + localVariablePath - - guard let localVariableApiClient = {{#swiftUseApiNamespace}}{{projectName}}API.{{/swiftUseApiNamespace}}Configuration.apiClient else { - fatalError("Configuration.apiClient is not set.") - } +{{/operation}} +} +{{/operations}} - return localVariableApiClient.send(.{{httpMethod}}, headers: headers, to: URI(string: localVariableURLString)) { localVariableRequest in - try {{#swiftUseApiNamespace}}{{projectName}}API.{{/swiftUseApiNamespace}}Configuration.apiWrapper(&localVariableRequest) - {{#hasHeaderParams}}{{#headerParams}} - localVariableRequest.headers.add(name: "{{baseName}}", value: {{#isArray}}{{paramName}}{{^required}}?{{/required}}.map { $0{{#isEnum}}.rawValue{{/isEnum}}.description }.description{{/isArray}}{{^isArray}}{{#isEnum}}{{paramName}}{{^required}}?{{/required}}.rawValue.description{{/isEnum}}{{^isEnum}}{{paramName}}{{^required}}?{{/required}}.description{{/isEnum}}{{/isArray}}{{^required}} ?? ""{{/required}}) - {{/headerParams}}{{/hasHeaderParams}} - {{#hasQueryParams}}struct QueryParams: Content { - {{#queryParams}} - var {{paramName}}: {{#isEnum}}{{#isArray}}[{{enumName}}_{{operationId}}]{{/isArray}}{{^isArray}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isArray}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}?{{/required}} - {{/queryParams}} - enum CodingKeys: String, CodingKey { - {{#queryParams}} - case {{paramName}}{{#baseName}} = "{{.}}"{{/baseName}} - {{/queryParams}} - } - } - try localVariableRequest.query.encode(QueryParams({{#queryParams}}{{paramName}}: {{paramName}}{{^-last}}, {{/-last}}{{/queryParams}})){{/hasQueryParams}} - {{#hasBodyParam}} - {{#bodyParam}}{{#required}}{{#isBinary}}localVariableRequest.body = ByteBuffer(data: {{paramName}}){{/isBinary}}{{^isBinary}}{{#isFile}}localVariableRequest.body = ByteBuffer(data: {{paramName}}){{/isFile}}try localVariableRequest.content.encode({{paramName}}, using: Configuration.contentConfiguration.requireEncoder(for: {{{dataType}}}.defaultContentType)){{/isBinary}}{{/required}}{{^required}}if let localVariableBody = {{paramName}} { - {{#isBinary}}localVariableRequest.body = ByteBuffer(data: localVariableBody){{/isBinary}}{{^isBinary}}{{#isFile}}localVariableRequest.body = ByteBuffer(data: localVariableBody){{/isFile}}try localVariableRequest.content.encode(localVariableBody, using: Configuration.contentConfiguration.requireEncoder(for: {{{dataType}}}.defaultContentType)){{/isBinary}} - }{{/required}}{{/bodyParam}} - {{/hasBodyParam}} - {{#hasFormParams}}struct FormParams: Content { - static let defaultContentType = Vapor.HTTPMediaType.formData - {{#formParams}} - var {{paramName}}: {{#isEnum}}{{#isArray}}[{{enumName}}_{{operationId}}]{{/isArray}}{{^isArray}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isArray}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}?{{/required}} - {{/formParams}} - } - try localVariableRequest.content.encode(FormParams({{#formParams}}{{paramName}}: {{paramName}}{{^-last}}, {{/-last}}{{/formParams}}), using: Configuration.contentConfiguration.requireEncoder(for: FormParams.defaultContentType)){{/hasFormParams}} - try beforeSend(&localVariableRequest) - } +private class OpenISO8601DateFormatter: DateFormatter { + static let withoutSeconds: DateFormatter = { + let formatter = DateFormatter() + formatter.calendar = Calendar(identifier: .iso8601) + formatter.locale = Locale(identifier: "en_US_POSIX") + formatter.timeZone = TimeZone(secondsFromGMT: 0) + formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ" + return formatter + }() + + private func setup() { + calendar = Calendar(identifier: .iso8601) + locale = Locale(identifier: "en_US_POSIX") + timeZone = TimeZone(secondsFromGMT: 0) + dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ" } - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} enum {{#lambda.titlecase}}{{operationId}}{{/lambda.titlecase}} { - {{#responses}} - case http{{code}}({{#dataType}}value: {{{.}}}, {{/dataType}}raw: ClientResponse) - {{/responses}} - {{^hasDefaultResponse}} - case http0(raw: ClientResponse) - {{/hasDefaultResponse}} + override init() { + super.init() + setup() } - /** - {{#summary}} - {{{.}}} - {{/summary}} - {{httpMethod}} {{{path}}}{{#notes}} - {{{.}}}{{/notes}}{{#subresourceOperation}} - subresourceOperation: {{.}}{{/subresourceOperation}}{{#defaultResponse}} - defaultResponse: {{.}}{{/defaultResponse}} - {{#authMethods}} - - {{#isBasic}}BASIC{{/isBasic}}{{#isOAuth}}OAuth{{/isOAuth}}{{#isApiKey}}API Key{{/isApiKey}}: - - type: {{type}}{{#keyParamName}} {{keyParamName}} {{#isKeyInQuery}}(QUERY){{/isKeyInQuery}}{{#isKeyInHeaer}}(HEADER){{/isKeyInHeaer}}{{/keyParamName}} - - name: {{name}} - {{/authMethods}} - {{#hasResponseHeaders}} - - responseHeaders: [{{#responseHeaders}}{{{baseName}}}({{{dataType}}}){{^-last}}, {{/-last}}{{/responseHeaders}}] - {{/hasResponseHeaders}} - {{#externalDocs}} - - externalDocs: {{.}} - {{/externalDocs}} - {{#allParams}} - - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{{description}}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} - {{/allParams}} - - returns: `EventLoopFuture` of `{{#lambda.titlecase}}{{operationId}}{{/lambda.titlecase}}` {{{description}}} - */ - {{#isDeprecated}} - @available(*, deprecated, message: "This operation is deprecated.") - {{/isDeprecated}} - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class func {{operationId}}({{#allParams}}{{paramName}}: {{#isEnum}}{{#isArray}}[{{enumName}}_{{operationId}}]{{/isArray}}{{^isArray}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isArray}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}headers: HTTPHeaders = {{projectName}}API.customHeaders, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture<{{#lambda.titlecase}}{{operationId}}{{/lambda.titlecase}}> { - return {{operationId}}Raw({{#allParams}}{{paramName}}: {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}headers: headers, beforeSend: beforeSend).flatMapThrowing { response -> {{#lambda.titlecase}}{{operationId}}{{/lambda.titlecase}} in - switch response.status.code { - {{#responses}} - {{#isDefault}}default{{/isDefault}}{{^isDefault}}case {{code}}{{/isDefault}}: - return .http{{code}}({{#dataType}}value: {{#isBinary}}Data(buffer: response.body ?? ByteBuffer()){{/isBinary}}{{^isBinary}}{{#isFile}}Data(buffer: response.body ?? ByteBuffer()){{/isFile}}{{^isFile}}try response.content.decode({{{dataType}}}.self, using: Configuration.contentConfiguration.requireDecoder(for: {{{dataType}}}.defaultContentType)){{/isFile}}{{/isBinary}}, {{/dataType}}raw: response) - {{/responses}} - {{^hasDefaultResponse}} - default: - return .http0(raw: response) - {{/hasDefaultResponse}} - } - } + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + setup() } -{{/useVapor}} -{{^useVapor}} - - /** - {{#summary}} - {{{.}}} - {{/summary}} - - {{httpMethod}} {{{path}}}{{#notes}} - - {{{.}}}{{/notes}}{{#subresourceOperation}} - - subresourceOperation: {{.}}{{/subresourceOperation}}{{#defaultResponse}} - - defaultResponse: {{.}}{{/defaultResponse}} - {{#authMethods}} - - {{#isBasic}}BASIC{{/isBasic}}{{#isOAuth}}OAuth{{/isOAuth}}{{#isApiKey}}API Key{{/isApiKey}}: - - type: {{type}}{{#keyParamName}} {{keyParamName}} {{#isKeyInQuery}}(QUERY){{/isKeyInQuery}}{{#isKeyInHeaer}}(HEADER){{/isKeyInHeaer}}{{/keyParamName}} - - name: {{name}} - {{/authMethods}} - {{#hasResponseHeaders}} - - responseHeaders: [{{#responseHeaders}}{{{baseName}}}({{{dataType}}}){{^-last}}, {{/-last}}{{/responseHeaders}}] - {{/hasResponseHeaders}} - {{#externalDocs}} - - externalDocs: {{.}} - {{/externalDocs}} - {{#allParams}} - - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} - {{/allParams}} - - returns: RequestBuilder<{{{returnType}}}{{^returnType}}Void{{/returnType}}> {{description}} - */ - {{#isDeprecated}} - @available(*, deprecated, message: "This operation is deprecated.") - {{/isDeprecated}} - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class func {{operationId}}WithRequestBuilder({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}) -> RequestBuilder<{{{returnType}}}{{^returnType}}Void{{/returnType}}> { - {{^pathParams}}let{{/pathParams}}{{#pathParams}}{{#-first}}var{{/-first}}{{/pathParams}} localVariablePath = "{{{path}}}"{{#pathParams}} - let {{paramName}}PreEscape = "\({{#isEnum}}{{paramName}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}.rawValue{{/isContainer}}{{/isEnum}}{{^isEnum}}APIHelper.mapValueToPathItem({{paramName}}){{/isEnum}})" - let {{paramName}}PostEscape = {{paramName}}PreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" - localVariablePath = localVariablePath.replacingOccurrences(of: "{{=<% %>=}}{<%baseName%>}<%={{ }}=%>", with: {{paramName}}PostEscape, options: .literal, range: nil){{/pathParams}} - let localVariableURLString = {{projectName}}API.basePath + localVariablePath - {{#bodyParam}} - let localVariableParameters = JSONEncodingHelper.encodingParameters(forEncodableObject: {{paramName}}) - {{/bodyParam}} - {{^bodyParam}} - {{#hasFormParams}} - let localVariableFormParams: [String: Any?] = [ - {{#formParams}} - {{> _param}}, - {{/formParams}} - ] - - let localVariableNonNullParameters = APIHelper.rejectNil(localVariableFormParams) - let localVariableParameters = APIHelper.convertBoolToString(localVariableNonNullParameters) - {{/hasFormParams}} - {{^hasFormParams}} - let localVariableParameters: [String: Any]? = nil - {{/hasFormParams}} -{{/bodyParam}}{{#hasQueryParams}} - var localVariableUrlComponents = URLComponents(string: localVariableURLString) - localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems([{{^queryParams}}:{{/queryParams}} - {{#queryParams}} - {{> _param}}, - {{/queryParams}} - ]){{/hasQueryParams}}{{^hasQueryParams}} - let localVariableUrlComponents = URLComponents(string: localVariableURLString){{/hasQueryParams}} - - let localVariableNillableHeaders: [String: Any?] = [{{^headerParams}}{{^hasFormParams}} - :{{/hasFormParams}}{{/headerParams}}{{#hasFormParams}} - "Content-Type": {{^consumes}}"multipart/form-data"{{/consumes}}{{#consumes.0}}"{{{mediaType}}}"{{/consumes.0}},{{/hasFormParams}}{{#headerParams}} - {{> _param}},{{/headerParams}} - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder<{{{returnType}}}{{^returnType}}Void{{/returnType}}>.Type = {{projectName}}API.requestBuilderFactory.{{#returnType}}getBuilder(){{/returnType}}{{^returnType}}getNonDecodableBuilder(){{/returnType}} - - return localVariableRequestBuilder.init(method: "{{httpMethod}}", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + override func date(from string: String) -> Date? { + if let result = super.date(from: string) { + return result + } + return OpenISO8601DateFormatter.withoutSeconds.date(from: string) } -{{/useVapor}} -{{/operation}} -} -{{#swiftUseApiNamespace}} -} -{{/swiftUseApiNamespace}} -{{/operations}} +} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/swift-alt/api_old.mustache b/modules/openapi-generator/src/main/resources/swift-alt/api_old.mustache new file mode 100644 index 000000000000..65042a07213e --- /dev/null +++ b/modules/openapi-generator/src/main/resources/swift-alt/api_old.mustache @@ -0,0 +1,515 @@ +{{#operations}}// +// {{classname}}.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +/** +{{#summary}} + {{{.}}} +{{/summary}} +- {{httpMethod}} {{{path}}}{{#notes}} + - {{{.}}}{{/notes}}{{#subresourceOperation}} + - subresourceOperation: {{.}}{{/subresourceOperation}}{{#defaultResponse}} + - defaultResponse: {{.}}{{/defaultResponse}} +{{#authMethods}} + - {{#isBasic}}BASIC{{/isBasic}}{{#isOAuth}}OAuth{{/isOAuth}}{{#isApiKey}}API Key{{/isApiKey}}: + - type: {{type}}{{#keyParamName}} {{keyParamName}} {{#isKeyInQuery}}(QUERY){{/isKeyInQuery}}{{#isKeyInHeaer}}(HEADER){{/isKeyInHeaer}}{{/keyParamName}} + - name: {{name}} +{{/authMethods}} +{{#hasResponseHeaders}} + - responseHeaders: [{{#responseHeaders}}{{{baseName}}}({{{dataType}}}){{^-last}}, {{/-last}}{{/responseHeaders}}] +{{/hasResponseHeaders}} +{{#externalDocs}} + - externalDocs: {{.}} +{{/externalDocs}} +{{#allParams}} + - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} +{{/allParams}} +- returns: RequestBuilder<{{{returnType}}}{{^returnType}}Void{{/returnType}}> {{description}} + */ +{{#isDeprecated}} + @available(*, deprecated, message: "This operation is deprecated.") +{{/isDeprecated}} +{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class func {{operationId}}WithRequestBuilder({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}) -> RequestBuilder<{{{returnType}}}{{^returnType}}Void{{/returnType}}> { +{{^pathParams}}let{{/pathParams}}{{#pathParams}}{{#-first}}var{{/-first}}{{/pathParams}} localVariablePath = "{{{path}}}"{{#pathParams}} + let {{paramName}}PreEscape = "\({{#isEnum}}{{paramName}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}.rawValue{{/isContainer}}{{/isEnum}}{{^isEnum}}APIHelper.mapValueToPathItem({{paramName}}){{/isEnum}})" + let {{paramName}}PostEscape = {{paramName}}PreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" + localVariablePath = localVariablePath.replacingOccurrences(of: "{{=<% %>=}}{<%baseName%>}<%={{ }}=%>", with: {{paramName}}PostEscape, options: .literal, range: nil){{/pathParams}} + let localVariableURLString = {{projectName}}API.basePath + localVariablePath +{{#bodyParam}} + let localVariableParameters = JSONEncodingHelper.encodingParameters(forEncodableObject: {{paramName}}) +{{/bodyParam}} +{{^bodyParam}} + {{#hasFormParams}} + let localVariableFormParams: [String: Any?] = [ + {{#formParams}} + {{> _param}}, + {{/formParams}} + ] + + let localVariableNonNullParameters = APIHelper.rejectNil(localVariableFormParams) + let localVariableParameters = APIHelper.convertBoolToString(localVariableNonNullParameters) + {{/hasFormParams}} + {{^hasFormParams}} + let localVariableParameters: [String: Any]? = nil + {{/hasFormParams}} +{{/bodyParam}}{{#hasQueryParams}} + var localVariableUrlComponents = URLComponents(string: localVariableURLString) + localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems([{{^queryParams}}:{{/queryParams}} + {{#queryParams}} + {{> _param}}, + {{/queryParams}} + ]){{/hasQueryParams}}{{^hasQueryParams}} + let localVariableUrlComponents = URLComponents(string: localVariableURLString){{/hasQueryParams}} + + let localVariableNillableHeaders: [String: Any?] = [{{^headerParams}}{{^hasFormParams}} + :{{/hasFormParams}}{{/headerParams}}{{#hasFormParams}} + "Content-Type": {{^consumes}}"multipart/form-data"{{/consumes}}{{#consumes.0}}"{{{mediaType}}}"{{/consumes.0}},{{/hasFormParams}}{{#headerParams}} + {{> _param}},{{/headerParams}} + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder<{{{returnType}}}{{^returnType}}Void{{/returnType}}>.Type = {{projectName}}API.requestBuilderFactory.{{#returnType}}getBuilder(){{/returnType}}{{^returnType}}getNonDecodableBuilder(){{/returnType}} + + return localVariableRequestBuilder.init(method: "{{httpMethod}}", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } + +import Foundation{{#usePromiseKit}} +import PromiseKit{{/usePromiseKit}}{{#useRxSwift}} +import RxSwift{{/useRxSwift}}{{#useCombine}} +#if canImport(Combine) +import Combine +#endif{{/useCombine}}{{#useVapor}} +import Vapor{{/useVapor}} +#if canImport(AnyCodable) +import AnyCodable +#endif{{#swiftUseApiNamespace}} + +extension {{projectName}}API { +{{/swiftUseApiNamespace}} + +{{#description}} +/** {{{.}}} */{{/description}} +{{#objcCompatible}}@objc {{/objcCompatible}}{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class {{classname}}{{#objcCompatible}} : NSObject{{/objcCompatible}} { +{{#operation}} + + {{#allParams}} + {{#isEnum}} + /** + * enum for parameter {{paramName}} + */ + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} enum {{enumName}}_{{operationId}}: {{^isContainer}}{{{dataType}}}{{/isContainer}}{{#isContainer}}String{{/isContainer}}, CaseIterable{{#useVapor}}, Content{{/useVapor}} { + {{#allowableValues}} + {{#enumVars}} + case {{name}} = {{{value}}} + {{/enumVars}} + {{/allowableValues}} + } + + {{/isEnum}} + {{/allParams}} +{{^useVapor}} +{{^usePromiseKit}} +{{^useRxSwift}} +{{^useResult}} +{{^useCombine}} +{{^useAsyncAwait}} + /** + {{#summary}} + {{{.}}} + {{/summary}}{{#allParams}} + - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}} + - parameter apiResponseQueue: The queue on which api response is dispatched. + - parameter completion: completion handler to receive the data and the error objects + */ + {{#isDeprecated}} + @available(*, deprecated, message: "This operation is deprecated.") + {{/isDeprecated}} + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class func {{operationId}}({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}apiResponseQueue: DispatchQueue = {{projectName}}API.apiResponseQueue, completion: @escaping ((_ data: {{{returnType}}}{{^returnType}}Void{{/returnType}}?, _ error: Error?) -> Void)) { + {{operationId}}WithRequestBuilder({{#allParams}}{{paramName}}: {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}).execute(apiResponseQueue) { result in + switch result { + {{#returnType}} + case let .success(response): + completion(response.body, nil) + {{/returnType}} + {{^returnType}} + case .success: + completion((), nil) + {{/returnType}} + case let .failure(error): + completion(nil, error) + } + } + } +{{/useAsyncAwait}} +{{/useCombine}} +{{/useResult}} +{{/useRxSwift}} +{{/usePromiseKit}} +{{/useVapor}} +{{#usePromiseKit}} + /** + {{#summary}} + {{{.}}} + {{/summary}}{{#allParams}} + - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}} + - parameter apiResponseQueue: The queue on which api response is dispatched. + - returns: Promise<{{{returnType}}}{{^returnType}}Void{{/returnType}}> + */ + {{#isDeprecated}} + @available(*, deprecated, message: "This operation is deprecated.") + {{/isDeprecated}} + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class func {{operationId}}({{#allParams}} {{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}apiResponseQueue: DispatchQueue = {{projectName}}API.apiResponseQueue) -> Promise<{{{returnType}}}{{^returnType}}Void{{/returnType}}> { + let deferred = Promise<{{{returnType}}}{{^returnType}}Void{{/returnType}}>.pending() + {{operationId}}WithRequestBuilder({{#allParams}}{{paramName}}: {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}).execute(apiResponseQueue) { result in + switch result { + {{#returnType}} + case let .success(response): + deferred.resolver.fulfill(response.body!) + {{/returnType}} + {{^returnType}} + case .success: + deferred.resolver.fulfill(()) + {{/returnType}} + case let .failure(error): + deferred.resolver.reject(error) + } + } + return deferred.promise + } +{{/usePromiseKit}} +{{#useRxSwift}} + /** + {{#summary}} + {{{.}}} + {{/summary}}{{#allParams}} + - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}} + - parameter apiResponseQueue: The queue on which api response is dispatched. + - returns: Observable<{{{returnType}}}{{^returnType}}Void{{/returnType}}> + */ + {{#isDeprecated}} + @available(*, deprecated, message: "This operation is deprecated.") + {{/isDeprecated}} + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class func {{operationId}}({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}apiResponseQueue: DispatchQueue = {{projectName}}API.apiResponseQueue) -> Observable<{{{returnType}}}{{^returnType}}Void{{/returnType}}> { + return Observable.create { observer -> Disposable in + {{operationId}}WithRequestBuilder({{#allParams}}{{paramName}}: {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}).execute(apiResponseQueue) { result in + switch result { + {{#returnType}} + case let .success(response): + observer.onNext(response.body!) + {{/returnType}} + {{^returnType}} + case .success: + observer.onNext(()) + {{/returnType}} + case let .failure(error): + observer.onError(error) + } + observer.onCompleted() + } + return Disposables.create() + } + } +{{/useRxSwift}} +{{#useCombine}} + /** + {{#summary}} + {{{.}}} + {{/summary}}{{#allParams}} + - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}} + - parameter apiResponseQueue: The queue on which api response is dispatched. + - returns: AnyPublisher<{{{returnType}}}{{^returnType}}Void{{/returnType}}, Error> + */ + #if canImport(Combine) + {{#isDeprecated}} + @available(*, deprecated, message: "This operation is deprecated.") + {{/isDeprecated}} + @available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *) + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class func {{operationId}}({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}apiResponseQueue: DispatchQueue = {{projectName}}API.apiResponseQueue) -> AnyPublisher<{{{returnType}}}{{^returnType}}Void{{/returnType}}, Error> { + return Future<{{{returnType}}}{{^returnType}}Void{{/returnType}}, Error> { promise in + {{operationId}}WithRequestBuilder({{#allParams}}{{paramName}}: {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}).execute(apiResponseQueue) { result in + switch result { + {{#returnType}} + case let .success(response): + promise(.success(response.body!)) + {{/returnType}} + {{^returnType}} + case .success: + promise(.success(())) + {{/returnType}} + case let .failure(error): + promise(.failure(error)) + } + } + }.eraseToAnyPublisher() + } + #endif +{{/useCombine}} +{{#useAsyncAwait}} + /** + {{#summary}} + {{{.}}} + {{/summary}}{{#allParams}} + - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}} + - parameter apiResponseQueue: The queue on which api response is dispatched. + - returns: {{{returnType}}}{{^returnType}}Void{{/returnType}} + */ + {{#isDeprecated}} + @available(*, deprecated, message: "This operation is deprecated.") + {{/isDeprecated}} + @available(macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0, *) + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class func {{operationId}}({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}apiResponseQueue: DispatchQueue = {{projectName}}API.apiResponseQueue) async throws{{#returnType}} -> {{{returnType}}}{{/returnType}} { + return try await withCheckedThrowingContinuation { continuation in + {{operationId}}WithRequestBuilder({{#allParams}}{{paramName}}: {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}).execute(apiResponseQueue) { result in + switch result { + {{#returnType}} + case let .success(response): + continuation.resume(returning: response.body!) + {{/returnType}} + {{^returnType}} + case .success: + continuation.resume(returning: ()) + {{/returnType}} + case let .failure(error): + continuation.resume(throwing: error) + } + } + } + } +{{/useAsyncAwait}} +{{#useResult}} + /** + {{#summary}} + {{{.}}} + {{/summary}}{{#allParams}} + - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}} + - parameter apiResponseQueue: The queue on which api response is dispatched. + - parameter completion: completion handler to receive the result + */ + {{#isDeprecated}} + @available(*, deprecated, message: "This operation is deprecated.") + {{/isDeprecated}} + open class func {{operationId}}({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}apiResponseQueue: DispatchQueue = {{projectName}}API.apiResponseQueue, completion: @escaping ((_ result: Swift.Result<{{{returnType}}}{{^returnType}}Void{{/returnType}}, ErrorResponse>) -> Void)) { + {{operationId}}WithRequestBuilder({{#allParams}}{{paramName}}: {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}).execute(apiResponseQueue) { result in + switch result { + {{#returnType}} + case let .success(response): + completion(.success(response.body!)) + {{/returnType}} + {{^returnType}} + case .success: + completion(.success(())) + {{/returnType}} + case let .failure(error): + completion(.failure(error)) + } + } + } +{{/useResult}} +{{#useVapor}} + /** + {{#summary}} + {{{.}}} + {{/summary}} + {{httpMethod}} {{{path}}}{{#notes}} + {{{.}}}{{/notes}}{{#subresourceOperation}} + subresourceOperation: {{.}}{{/subresourceOperation}}{{#defaultResponse}} + defaultResponse: {{.}}{{/defaultResponse}} + {{#authMethods}} + - {{#isBasic}}BASIC{{/isBasic}}{{#isOAuth}}OAuth{{/isOAuth}}{{#isApiKey}}API Key{{/isApiKey}}: + - type: {{type}}{{#keyParamName}} {{keyParamName}} {{#isKeyInQuery}}(QUERY){{/isKeyInQuery}}{{#isKeyInHeaer}}(HEADER){{/isKeyInHeaer}}{{/keyParamName}} + - name: {{name}} + {{/authMethods}} + {{#hasResponseHeaders}} + - responseHeaders: [{{#responseHeaders}}{{{baseName}}}({{{dataType}}}){{^-last}}, {{/-last}}{{/responseHeaders}}] + {{/hasResponseHeaders}} + {{#externalDocs}} + - externalDocs: {{.}} + {{/externalDocs}} + {{#allParams}} + - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{{description}}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + {{/allParams}} + - returns: `EventLoopFuture` of `ClientResponse` {{{description}}} + */ + {{#isDeprecated}} + @available(*, deprecated, message: "This operation is deprecated.") + {{/isDeprecated}} + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class func {{operationId}}Raw({{#allParams}}{{paramName}}: {{#isEnum}}{{#isArray}}[{{enumName}}_{{operationId}}]{{/isArray}}{{^isArray}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isArray}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}headers: HTTPHeaders = {{projectName}}API.customHeaders, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + {{^pathParams}}let{{/pathParams}}{{#pathParams}}{{#-first}}var{{/-first}}{{/pathParams}} localVariablePath = "{{{path}}}"{{#pathParams}} + let {{paramName}}PreEscape = String(describing: {{#isEnum}}{{paramName}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}.rawValue{{/isContainer}}{{/isEnum}}{{^isEnum}}{{paramName}}{{/isEnum}}) + let {{paramName}}PostEscape = {{paramName}}PreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" + localVariablePath = localVariablePath.replacingOccurrences(of: "{{=<% %>=}}{<%baseName%>}<%={{ }}=%>", with: {{paramName}}PostEscape, options: .literal, range: nil){{/pathParams}} + let localVariableURLString = {{projectName}}API.basePath + localVariablePath + + guard let localVariableApiClient = {{#swiftUseApiNamespace}}{{projectName}}API.{{/swiftUseApiNamespace}}Configuration.apiClient else { + fatalError("Configuration.apiClient is not set.") + } + + return localVariableApiClient.send(.{{httpMethod}}, headers: headers, to: URI(string: localVariableURLString)) { localVariableRequest in + try {{#swiftUseApiNamespace}}{{projectName}}API.{{/swiftUseApiNamespace}}Configuration.apiWrapper(&localVariableRequest) + {{#hasHeaderParams}}{{#headerParams}} + localVariableRequest.headers.add(name: "{{baseName}}", value: {{#isArray}}{{paramName}}{{^required}}?{{/required}}.map { $0{{#isEnum}}.rawValue{{/isEnum}}.description }.description{{/isArray}}{{^isArray}}{{#isEnum}}{{paramName}}{{^required}}?{{/required}}.rawValue.description{{/isEnum}}{{^isEnum}}{{paramName}}{{^required}}?{{/required}}.description{{/isEnum}}{{/isArray}}{{^required}} ?? ""{{/required}}) + {{/headerParams}}{{/hasHeaderParams}} + {{#hasQueryParams}}struct QueryParams: Content { + {{#queryParams}} + var {{paramName}}: {{#isEnum}}{{#isArray}}[{{enumName}}_{{operationId}}]{{/isArray}}{{^isArray}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isArray}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}?{{/required}} + {{/queryParams}} + + enum CodingKeys: String, CodingKey { + {{#queryParams}} + case {{paramName}}{{#baseName}} = "{{.}}"{{/baseName}} + {{/queryParams}} + } + } + try localVariableRequest.query.encode(QueryParams({{#queryParams}}{{paramName}}: {{paramName}}{{^-last}}, {{/-last}}{{/queryParams}})){{/hasQueryParams}} + {{#hasBodyParam}} + {{#bodyParam}}{{#required}}{{#isBinary}}localVariableRequest.body = ByteBuffer(data: {{paramName}}){{/isBinary}}{{^isBinary}}{{#isFile}}localVariableRequest.body = ByteBuffer(data: {{paramName}}){{/isFile}}try localVariableRequest.content.encode({{paramName}}, using: Configuration.contentConfiguration.requireEncoder(for: {{{dataType}}}.defaultContentType)){{/isBinary}}{{/required}}{{^required}}if let localVariableBody = {{paramName}} { + {{#isBinary}}localVariableRequest.body = ByteBuffer(data: localVariableBody){{/isBinary}}{{^isBinary}}{{#isFile}}localVariableRequest.body = ByteBuffer(data: localVariableBody){{/isFile}}try localVariableRequest.content.encode(localVariableBody, using: Configuration.contentConfiguration.requireEncoder(for: {{{dataType}}}.defaultContentType)){{/isBinary}} + }{{/required}}{{/bodyParam}} + {{/hasBodyParam}} + {{#hasFormParams}}struct FormParams: Content { + static let defaultContentType = Vapor.HTTPMediaType.formData + {{#formParams}} + var {{paramName}}: {{#isEnum}}{{#isArray}}[{{enumName}}_{{operationId}}]{{/isArray}}{{^isArray}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isArray}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}?{{/required}} + {{/formParams}} + } + try localVariableRequest.content.encode(FormParams({{#formParams}}{{paramName}}: {{paramName}}{{^-last}}, {{/-last}}{{/formParams}}), using: Configuration.contentConfiguration.requireEncoder(for: FormParams.defaultContentType)){{/hasFormParams}} + try beforeSend(&localVariableRequest) + } + } + + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} enum {{#lambda.titlecase}}{{operationId}}{{/lambda.titlecase}} { + {{#responses}} + case http{{code}}({{#dataType}}value: {{{.}}}, {{/dataType}}raw: ClientResponse) + {{/responses}} + {{^hasDefaultResponse}} + case http0(raw: ClientResponse) + {{/hasDefaultResponse}} + } + + /** + {{#summary}} + {{{.}}} + {{/summary}} + {{httpMethod}} {{{path}}}{{#notes}} + {{{.}}}{{/notes}}{{#subresourceOperation}} + subresourceOperation: {{.}}{{/subresourceOperation}}{{#defaultResponse}} + defaultResponse: {{.}}{{/defaultResponse}} + {{#authMethods}} + - {{#isBasic}}BASIC{{/isBasic}}{{#isOAuth}}OAuth{{/isOAuth}}{{#isApiKey}}API Key{{/isApiKey}}: + - type: {{type}}{{#keyParamName}} {{keyParamName}} {{#isKeyInQuery}}(QUERY){{/isKeyInQuery}}{{#isKeyInHeaer}}(HEADER){{/isKeyInHeaer}}{{/keyParamName}} + - name: {{name}} + {{/authMethods}} + {{#hasResponseHeaders}} + - responseHeaders: [{{#responseHeaders}}{{{baseName}}}({{{dataType}}}){{^-last}}, {{/-last}}{{/responseHeaders}}] + {{/hasResponseHeaders}} + {{#externalDocs}} + - externalDocs: {{.}} + {{/externalDocs}} + {{#allParams}} + - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{{description}}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + {{/allParams}} + - returns: `EventLoopFuture` of `{{#lambda.titlecase}}{{operationId}}{{/lambda.titlecase}}` {{{description}}} + */ + {{#isDeprecated}} + @available(*, deprecated, message: "This operation is deprecated.") + {{/isDeprecated}} + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class func {{operationId}}({{#allParams}}{{paramName}}: {{#isEnum}}{{#isArray}}[{{enumName}}_{{operationId}}]{{/isArray}}{{^isArray}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isArray}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}headers: HTTPHeaders = {{projectName}}API.customHeaders, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture<{{#lambda.titlecase}}{{operationId}}{{/lambda.titlecase}}> { + return {{operationId}}Raw({{#allParams}}{{paramName}}: {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}headers: headers, beforeSend: beforeSend).flatMapThrowing { response -> {{#lambda.titlecase}}{{operationId}}{{/lambda.titlecase}} in + switch response.status.code { + {{#responses}} + {{#isDefault}}default{{/isDefault}}{{^isDefault}}case {{code}}{{/isDefault}}: + return .http{{code}}({{#dataType}}value: {{#isBinary}}Data(buffer: response.body ?? ByteBuffer()){{/isBinary}}{{^isBinary}}{{#isFile}}Data(buffer: response.body ?? ByteBuffer()){{/isFile}}{{^isFile}}try response.content.decode({{{dataType}}}.self, using: Configuration.contentConfiguration.requireDecoder(for: {{{dataType}}}.defaultContentType)){{/isFile}}{{/isBinary}}, {{/dataType}}raw: response) + {{/responses}} + {{^hasDefaultResponse}} + default: + return .http0(raw: response) + {{/hasDefaultResponse}} + } + } + } + +{{/useVapor}} +{{^useVapor}} + + /** + {{#summary}} + {{{.}}} + {{/summary}} + - {{httpMethod}} {{{path}}}{{#notes}} + - {{{.}}}{{/notes}}{{#subresourceOperation}} + - subresourceOperation: {{.}}{{/subresourceOperation}}{{#defaultResponse}} + - defaultResponse: {{.}}{{/defaultResponse}} + {{#authMethods}} + - {{#isBasic}}BASIC{{/isBasic}}{{#isOAuth}}OAuth{{/isOAuth}}{{#isApiKey}}API Key{{/isApiKey}}: + - type: {{type}}{{#keyParamName}} {{keyParamName}} {{#isKeyInQuery}}(QUERY){{/isKeyInQuery}}{{#isKeyInHeaer}}(HEADER){{/isKeyInHeaer}}{{/keyParamName}} + - name: {{name}} + {{/authMethods}} + {{#hasResponseHeaders}} + - responseHeaders: [{{#responseHeaders}}{{{baseName}}}({{{dataType}}}){{^-last}}, {{/-last}}{{/responseHeaders}}] + {{/hasResponseHeaders}} + {{#externalDocs}} + - externalDocs: {{.}} + {{/externalDocs}} + {{#allParams}} + - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + {{/allParams}} + - returns: RequestBuilder<{{{returnType}}}{{^returnType}}Void{{/returnType}}> {{description}} + */ + {{#isDeprecated}} + @available(*, deprecated, message: "This operation is deprecated.") + {{/isDeprecated}} + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class func {{operationId}}WithRequestBuilder({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}) -> RequestBuilder<{{{returnType}}}{{^returnType}}Void{{/returnType}}> { + {{^pathParams}}let{{/pathParams}}{{#pathParams}}{{#-first}}var{{/-first}}{{/pathParams}} localVariablePath = "{{{path}}}"{{#pathParams}} + let {{paramName}}PreEscape = "\({{#isEnum}}{{paramName}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}.rawValue{{/isContainer}}{{/isEnum}}{{^isEnum}}APIHelper.mapValueToPathItem({{paramName}}){{/isEnum}})" + let {{paramName}}PostEscape = {{paramName}}PreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" + localVariablePath = localVariablePath.replacingOccurrences(of: "{{=<% %>=}}{<%baseName%>}<%={{ }}=%>", with: {{paramName}}PostEscape, options: .literal, range: nil){{/pathParams}} + let localVariableURLString = {{projectName}}API.basePath + localVariablePath + {{#bodyParam}} + let localVariableParameters = JSONEncodingHelper.encodingParameters(forEncodableObject: {{paramName}}) + {{/bodyParam}} + {{^bodyParam}} + {{#hasFormParams}} + let localVariableFormParams: [String: Any?] = [ + {{#formParams}} + {{> _param}}, + {{/formParams}} + ] + + let localVariableNonNullParameters = APIHelper.rejectNil(localVariableFormParams) + let localVariableParameters = APIHelper.convertBoolToString(localVariableNonNullParameters) + {{/hasFormParams}} + {{^hasFormParams}} + let localVariableParameters: [String: Any]? = nil + {{/hasFormParams}} +{{/bodyParam}}{{#hasQueryParams}} + var localVariableUrlComponents = URLComponents(string: localVariableURLString) + localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems([{{^queryParams}}:{{/queryParams}} + {{#queryParams}} + {{> _param}}, + {{/queryParams}} + ]){{/hasQueryParams}}{{^hasQueryParams}} + let localVariableUrlComponents = URLComponents(string: localVariableURLString){{/hasQueryParams}} + + let localVariableNillableHeaders: [String: Any?] = [{{^headerParams}}{{^hasFormParams}} + :{{/hasFormParams}}{{/headerParams}}{{#hasFormParams}} + "Content-Type": {{^consumes}}"multipart/form-data"{{/consumes}}{{#consumes.0}}"{{{mediaType}}}"{{/consumes.0}},{{/hasFormParams}}{{#headerParams}} + {{> _param}},{{/headerParams}} + ] + + let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) + + let localVariableRequestBuilder: RequestBuilder<{{{returnType}}}{{^returnType}}Void{{/returnType}}>.Type = {{projectName}}API.requestBuilderFactory.{{#returnType}}getBuilder(){{/returnType}}{{^returnType}}getNonDecodableBuilder(){{/returnType}} + + return localVariableRequestBuilder.init(method: "{{httpMethod}}", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + } +{{/useVapor}} +{{/operation}} +} +{{#swiftUseApiNamespace}} +} +{{/swiftUseApiNamespace}} +{{/operations}} diff --git a/samples/client/petstore/swift/alt/OpenAPIClient.xcodeproj/project.pbxproj b/samples/client/petstore/swift/alt/OpenAPIClient.xcodeproj/project.pbxproj index aa50ef688273..1f721253a4b6 100644 --- a/samples/client/petstore/swift/alt/OpenAPIClient.xcodeproj/project.pbxproj +++ b/samples/client/petstore/swift/alt/OpenAPIClient.xcodeproj/project.pbxproj @@ -8,7 +8,10 @@ /* Begin PBXBuildFile section */ 07AD66F44F142A25134285D2 /* Tag.swift in Sources */ = {isa = PBXBuildFile; fileRef = 004F49F830DBCE73EE547625 /* Tag.swift */; }; - 2BD3B8D12727080900E16037 /* Runtime.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2BD3B8D02727080900E16037 /* Runtime.swift */; }; + 2BD3B8D727271A1300E16037 /* Runtime.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2BD3B8D627271A1300E16037 /* Runtime.swift */; }; + 2BD3B8DA27271C7F00E16037 /* StoreAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2BD3B8D527270A5E00E16037 /* StoreAPI.swift */; }; + 2BD3B8DB27271C7F00E16037 /* UserAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2BD3B8D427270A5E00E16037 /* UserAPI.swift */; }; + 2BD3B8DC27271C7F00E16037 /* PetAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2BD3B8D327270A5E00E16037 /* PetAPI.swift */; }; 5FDB83D7EF01DBFD3E8B6AD6 /* ApiResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F0D02E61CF4C58B24BC1581 /* ApiResponse.swift */; }; 615F8910ABA037FBFA0BC09F /* User.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA84FDE7CC165FCEDC532CE0 /* User.swift */; }; 8BB28EBA3F247E1FC0AEB946 /* Pet.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6443F80E261022596B8ABA4 /* Pet.swift */; }; @@ -18,10 +21,11 @@ /* Begin PBXFileReference section */ 004F49F830DBCE73EE547625 /* Tag.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tag.swift; sourceTree = ""; }; - 2BD3B8D02727080900E16037 /* Runtime.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Runtime.swift; path = "../../../../../../../../../wallet-client-ios/Runtime.swift"; sourceTree = ""; }; 2BD3B8D327270A5E00E16037 /* PetAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PetAPI.swift; sourceTree = ""; }; 2BD3B8D427270A5E00E16037 /* UserAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAPI.swift; sourceTree = ""; }; 2BD3B8D527270A5E00E16037 /* StoreAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoreAPI.swift; sourceTree = ""; }; + 2BD3B8D627271A1300E16037 /* Runtime.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Runtime.swift; path = "../../../../../../../../modules/openapi-generator/src/main/resources/swift-alt/Runtime.swift"; sourceTree = ""; }; + 2BD3B8D827271B0300E16037 /* Old.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Old.swift; path = "../../../../../../../../modules/openapi-generator/src/main/resources/swift-alt/Old.swift"; sourceTree = ""; }; 557E9F1F7D8EE8697FFC77CA /* Order.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Order.swift; sourceTree = ""; }; 5A68201A010940B069E402C4 /* OpenAPIClient.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = OpenAPIClient.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 7F0D02E61CF4C58B24BC1581 /* ApiResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApiResponse.swift; sourceTree = ""; }; @@ -63,7 +67,8 @@ 58C164DF5107AE40B4ED3435 /* OpenAPIs */ = { isa = PBXGroup; children = ( - 2BD3B8D02727080900E16037 /* Runtime.swift */, + 2BD3B8D827271B0300E16037 /* Old.swift */, + 2BD3B8D627271A1300E16037 /* Runtime.swift */, 2BD3B8D227270A5E00E16037 /* APIs */, D3393B2ECC9C8AA58D9CC6B5 /* Models */, ); @@ -182,13 +187,16 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 2BD3B8DA27271C7F00E16037 /* StoreAPI.swift in Sources */, 5FDB83D7EF01DBFD3E8B6AD6 /* ApiResponse.swift in Sources */, B3B33292169982AB380577B9 /* Category.swift in Sources */, - 2BD3B8D12727080900E16037 /* Runtime.swift in Sources */, D2051AFBDBA23137A85FCA3B /* Order.swift in Sources */, + 2BD3B8D727271A1300E16037 /* Runtime.swift in Sources */, 8BB28EBA3F247E1FC0AEB946 /* Pet.swift in Sources */, 07AD66F44F142A25134285D2 /* Tag.swift in Sources */, 615F8910ABA037FBFA0BC09F /* User.swift in Sources */, + 2BD3B8DC27271C7F00E16037 /* PetAPI.swift in Sources */, + 2BD3B8DB27271C7F00E16037 /* UserAPI.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/samples/client/petstore/swift/alt/OpenAPIClient.xcodeproj/project.xcworkspace/xcuserdata/a.davydov.xcuserdatad/UserInterfaceState.xcuserstate b/samples/client/petstore/swift/alt/OpenAPIClient.xcodeproj/project.xcworkspace/xcuserdata/a.davydov.xcuserdatad/UserInterfaceState.xcuserstate index 738e80166dbd60e61c6d4741879e61bf94fdb997..5984e04175053c6a950dc04580c3d2397d367cf5 100644 GIT binary patch literal 36691 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 z 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 + - returns: AnyPublisher, Never> */ - open func addPet(pet: Pet) -> Future { + open func addPet(pet: Pet) -> AnyPublisher, Never> { + // Creating final URL with query items and path + var components = URLComponents() + components.path = "/pet" + + guard let url = components.url(relativeTo: transport.baseURL) else { + fatalError("URL is nil") + } + + var request = URLRequest(url: url) + request.httpMethod = "POST" + + // Setting body parameters + request.httpBody = try? encoder.encode(pet) + // Getting auth type + let securityScheme: SecurityScheme = .none + return transport.send(request: request, securityScheme: securityScheme) + .map { response -> Result in + if response.response?.statusCode == 200 { + if let data = response.data { + return Result { try self.decoder.decode(Pet.self, from: data) } + } else { + return .failure(TransportError.unknown) + } + } else { + return .failure(response.error ?? TransportError.unknown) + } + } + .eraseToAnyPublisher() } + /** Deletes a pet - - DELETE /pet/{petId} + - DELETE /pet/{petId} - OAuth: - type: oauth2 - name: petstore_auth - parameter petId: (path) Pet id to delete - parameter apiKey: (header) (optional) - - returns: Future + - returns: AnyPublisher, Never> */ - open func deletePet(petId: Int64, apiKey: String? = nil) -> Future { + open func deletePet(petId: Int64, apiKey: String? = nil) -> AnyPublisher, Never> { + // Creating final URL with query items and path + var components = URLComponents() + components.path = "/pet/{petId}" + .replacingOccurrences(of: "{petId}", with: "\(petId)") + + guard let url = components.url(relativeTo: transport.baseURL) else { + fatalError("URL is nil") + } + + var request = URLRequest(url: url) + request.httpMethod = "DELETE" + // Setting headers + request.allHTTPHeaderFields = [ + "api_key": apiKey + ].compactMapValues { $0 } + + // Getting auth type + let securityScheme: SecurityScheme = .none + return transport.send(request: request, securityScheme: securityScheme) + .map { response -> Result in + if response.response?.statusCode == 200 { + return .success(()) + } else { + return .failure(response.error ?? TransportError.unknown) + } + } + .eraseToAnyPublisher() } + /** Finds Pets by status - - GET /pet/findByStatus + - GET /pet/findByStatus - Multiple status values can be provided with comma separated strings - OAuth: - type: oauth2 - name: petstore_auth - - parameter status: () Status values that need to be considered for filter - - returns: Future<[Pet], Never> + - parameter status: (query) Status values that need to be considered for filter + - returns: AnyPublisher, Never> */ - open func findPetsByStatus(status: [String]) -> Future<[Pet], Never> { + open func findPetsByStatus(status: [String]) -> AnyPublisher, Never> { + // Creating final URL with query items and path + var components = URLComponents() + components.path = "/pet/findByStatus" + components.queryItems = [ + URLQueryItem(name: "status", value: status.joined(separator: ", ")) + ] + guard let url = components.url(relativeTo: transport.baseURL) else { + fatalError("URL is nil") + } + + var request = URLRequest(url: url) + request.httpMethod = "GET" + + + // Getting auth type + let securityScheme: SecurityScheme = .none + return transport.send(request: request, securityScheme: securityScheme) + .map { response -> Result<[Pet], Error> in + if response.response?.statusCode == 200 { + if let data = response.data { + return Result { try self.decoder.decode([Pet].self, from: data) } + } else { + return .failure(TransportError.unknown) + } + } else { + return .failure(response.error ?? TransportError.unknown) + } + } + .eraseToAnyPublisher() } + /** Finds Pets by tags - - GET /pet/findByTags + - GET /pet/findByTags - Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. - OAuth: - type: oauth2 - name: petstore_auth - - parameter tags: () Tags to filter by - - returns: Future<[Pet], Never> + - parameter tags: (query) Tags to filter by + - returns: AnyPublisher, Never> */ - open func findPetsByTags(tags: [String]) -> Future<[Pet], Never> { + open func findPetsByTags(tags: [String]) -> AnyPublisher, Never> { + // Creating final URL with query items and path + var components = URLComponents() + components.path = "/pet/findByTags" + components.queryItems = [ + URLQueryItem(name: "tags", value: tags.joined(separator: ", ")) + ] + guard let url = components.url(relativeTo: transport.baseURL) else { + fatalError("URL is nil") + } + + var request = URLRequest(url: url) + request.httpMethod = "GET" + + + // Getting auth type + let securityScheme: SecurityScheme = .none + return transport.send(request: request, securityScheme: securityScheme) + .map { response -> Result<[Pet], Error> in + if response.response?.statusCode == 200 { + if let data = response.data { + return Result { try self.decoder.decode([Pet].self, from: data) } + } else { + return .failure(TransportError.unknown) + } + } else { + return .failure(response.error ?? TransportError.unknown) + } + } + .eraseToAnyPublisher() } + /** Find pet by ID - - GET /pet/{petId} + - GET /pet/{petId} - Returns a single pet - API Key: - type: apiKey api_key - name: api_key - parameter petId: (path) ID of pet to return - - returns: Future + - returns: AnyPublisher, Never> */ - open func getPetById(petId: Int64) -> Future { + open func getPetById(petId: Int64) -> AnyPublisher, Never> { + // Creating final URL with query items and path + var components = URLComponents() + components.path = "/pet/{petId}" + .replacingOccurrences(of: "{petId}", with: "\(petId)") + + guard let url = components.url(relativeTo: transport.baseURL) else { + fatalError("URL is nil") + } + + var request = URLRequest(url: url) + request.httpMethod = "GET" + + + // Getting auth type + let securityScheme: SecurityScheme = .none + return transport.send(request: request, securityScheme: securityScheme) + .map { response -> Result in + if response.response?.statusCode == 200 { + if let data = response.data { + return Result { try self.decoder.decode(Pet.self, from: data) } + } else { + return .failure(TransportError.unknown) + } + } else { + return .failure(response.error ?? TransportError.unknown) + } + } + .eraseToAnyPublisher() } + /** Update an existing pet - - PUT /pet + - PUT /pet - OAuth: - type: oauth2 - name: petstore_auth - parameter pet: (body) Pet object that needs to be added to the store - - returns: Future + - returns: AnyPublisher, Never> */ - open func updatePet(pet: Pet) -> Future { + open func updatePet(pet: Pet) -> AnyPublisher, Never> { + // Creating final URL with query items and path + var components = URLComponents() + components.path = "/pet" + + guard let url = components.url(relativeTo: transport.baseURL) else { + fatalError("URL is nil") + } + + var request = URLRequest(url: url) + request.httpMethod = "PUT" + + // Setting body parameters + request.httpBody = try? encoder.encode(pet) + // Getting auth type + let securityScheme: SecurityScheme = .none + return transport.send(request: request, securityScheme: securityScheme) + .map { response -> Result in + if response.response?.statusCode == 200 { + if let data = response.data { + return Result { try self.decoder.decode(Pet.self, from: data) } + } else { + return .failure(TransportError.unknown) + } + } else { + return .failure(response.error ?? TransportError.unknown) + } + } + .eraseToAnyPublisher() } + /** Updates a pet in the store with form data - - POST /pet/{petId} + - POST /pet/{petId} - OAuth: - type: oauth2 - name: petstore_auth - parameter petId: (path) ID of pet that needs to be updated - parameter name: (form) Updated name of the pet (optional) - parameter status: (form) Updated status of the pet (optional) - - returns: Future + - returns: AnyPublisher, Never> */ - open func updatePetWithForm(petId: Int64, name: String? = nil, status: String? = nil) -> Future { + open func updatePetWithForm(petId: Int64, name: String? = nil, status: String? = nil) -> AnyPublisher, Never> { + // Creating final URL with query items and path + var components = URLComponents() + components.path = "/pet/{petId}" + .replacingOccurrences(of: "{petId}", with: "\(petId)") + + guard let url = components.url(relativeTo: transport.baseURL) else { + fatalError("URL is nil") + } + + var request = URLRequest(url: url) + request.httpMethod = "POST" + + + // Getting auth type + let securityScheme: SecurityScheme = .none + return transport.send(request: request, securityScheme: securityScheme) + .map { response -> Result in + if response.response?.statusCode == 200 { + return .success(()) + } else { + return .failure(response.error ?? TransportError.unknown) + } + } + .eraseToAnyPublisher() } + /** uploads an image - - POST /pet/{petId}/uploadImage + - POST /pet/{petId}/uploadImage - OAuth: - type: oauth2 - name: petstore_auth - parameter petId: (path) ID of pet to update - parameter additionalMetadata: (form) Additional data to pass to server (optional) - parameter file: (form) file to upload (optional) - - returns: Future + - returns: AnyPublisher, Never> */ - open func uploadFile(petId: Int64, additionalMetadata: String? = nil, file: Data? = nil) -> Future { - } -} -//// - -/** -- - - API Key: - - type: apiKey api_key - - name: api_key - - OAuth: - - type: oauth2 - - name: petstore_auth -- returns: RequestBuilder - */ -open class func WithRequestBuilder() -> RequestBuilder { -let localVariablePath = "" - let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath - let localVariableParameters: [String: Any]? = nil - - let localVariableUrlComponents = URLComponents(string: localVariableURLString) - - let localVariableNillableHeaders: [String: Any?] = [ - : - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() - - return localVariableRequestBuilder.init(method: "", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) - } - -import Foundation -#if canImport(AnyCodable) -import AnyCodable -#endif - -open class PetAPI { - - /** - Add a new pet to the store - - - parameter pet: (body) Pet object that needs to be added to the store - - parameter apiResponseQueue: The queue on which api response is dispatched. - - parameter completion: completion handler to receive the data and the error objects - */ - open class func addPet(pet: Pet, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Pet?, _ error: Error?) -> Void)) { - addPetWithRequestBuilder(pet: pet).execute(apiResponseQueue) { result in - switch result { - case let .success(response): - completion(response.body, nil) - case let .failure(error): - completion(nil, error) - } - } - } - - /** - Add a new pet to the store - - POST /pet - - OAuth: - - type: oauth2 - - name: petstore_auth - - parameter pet: (body) Pet object that needs to be added to the store - - returns: RequestBuilder - */ - open class func addPetWithRequestBuilder(pet: Pet) -> RequestBuilder { - let localVariablePath = "/pet" - let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath - let localVariableParameters = JSONEncodingHelper.encodingParameters(forEncodableObject: pet) - - let localVariableUrlComponents = URLComponents(string: localVariableURLString) - - let localVariableNillableHeaders: [String: Any?] = [ - : - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getBuilder() - - return localVariableRequestBuilder.init(method: "POST", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) - } - - /** - Deletes a pet - - - parameter petId: (path) Pet id to delete - - parameter apiKey: (header) (optional) - - parameter apiResponseQueue: The queue on which api response is dispatched. - - parameter completion: completion handler to receive the data and the error objects - */ - open class func deletePet(petId: Int64, apiKey: String? = nil, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Void?, _ error: Error?) -> Void)) { - deletePetWithRequestBuilder(petId: petId, apiKey: apiKey).execute(apiResponseQueue) { result in - switch result { - case .success: - completion((), nil) - case let .failure(error): - completion(nil, error) - } - } - } - - /** - Deletes a pet - - DELETE /pet/{petId} - - OAuth: - - type: oauth2 - - name: petstore_auth - - parameter petId: (path) Pet id to delete - - parameter apiKey: (header) (optional) - - returns: RequestBuilder - */ - open class func deletePetWithRequestBuilder(petId: Int64, apiKey: String? = nil) -> RequestBuilder { - var localVariablePath = "/pet/{petId}" - let petIdPreEscape = "\(APIHelper.mapValueToPathItem(petId))" - let petIdPostEscape = petIdPreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" - localVariablePath = localVariablePath.replacingOccurrences(of: "{petId}", with: petIdPostEscape, options: .literal, range: nil) - let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath - let localVariableParameters: [String: Any]? = nil - - let localVariableUrlComponents = URLComponents(string: localVariableURLString) - - let localVariableNillableHeaders: [String: Any?] = [ - "api_key": apiKey?.encodeToJSON(), - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() - - return localVariableRequestBuilder.init(method: "DELETE", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) - } - - /** - * enum for parameter status - */ - public enum Status_findPetsByStatus: String, CaseIterable { - case available = "available" - case pending = "pending" - case sold = "sold" - } - - /** - Finds Pets by status - - - parameter status: (query) Status values that need to be considered for filter - - parameter apiResponseQueue: The queue on which api response is dispatched. - - parameter completion: completion handler to receive the data and the error objects - */ - open class func findPetsByStatus(status: [String], apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: [Pet]?, _ error: Error?) -> Void)) { - findPetsByStatusWithRequestBuilder(status: status).execute(apiResponseQueue) { result in - switch result { - case let .success(response): - completion(response.body, nil) - case let .failure(error): - completion(nil, error) - } - } - } - - /** - Finds Pets by status - - GET /pet/findByStatus - - Multiple status values can be provided with comma separated strings - - OAuth: - - type: oauth2 - - name: petstore_auth - - parameter status: (query) Status values that need to be considered for filter - - returns: RequestBuilder<[Pet]> - */ - open class func findPetsByStatusWithRequestBuilder(status: [String]) -> RequestBuilder<[Pet]> { - let localVariablePath = "/pet/findByStatus" - let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath - let localVariableParameters: [String: Any]? = nil - - var localVariableUrlComponents = URLComponents(string: localVariableURLString) - localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems([ - "status": status.encodeToJSON(), - ]) - - let localVariableNillableHeaders: [String: Any?] = [ - : - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder<[Pet]>.Type = OpenAPIClientAPI.requestBuilderFactory.getBuilder() - - return localVariableRequestBuilder.init(method: "GET", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) - } - - /** - Finds Pets by tags - - - parameter tags: (query) Tags to filter by - - parameter apiResponseQueue: The queue on which api response is dispatched. - - parameter completion: completion handler to receive the data and the error objects - */ - @available(*, deprecated, message: "This operation is deprecated.") - open class func findPetsByTags(tags: [String], apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: [Pet]?, _ error: Error?) -> Void)) { - findPetsByTagsWithRequestBuilder(tags: tags).execute(apiResponseQueue) { result in - switch result { - case let .success(response): - completion(response.body, nil) - case let .failure(error): - completion(nil, error) - } - } - } - - /** - Finds Pets by tags - - GET /pet/findByTags - - Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. - - OAuth: - - type: oauth2 - - name: petstore_auth - - parameter tags: (query) Tags to filter by - - returns: RequestBuilder<[Pet]> - */ - @available(*, deprecated, message: "This operation is deprecated.") - open class func findPetsByTagsWithRequestBuilder(tags: [String]) -> RequestBuilder<[Pet]> { - let localVariablePath = "/pet/findByTags" - let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath - let localVariableParameters: [String: Any]? = nil - - var localVariableUrlComponents = URLComponents(string: localVariableURLString) - localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems([ - "tags": tags.encodeToJSON(), - ]) - - let localVariableNillableHeaders: [String: Any?] = [ - : - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder<[Pet]>.Type = OpenAPIClientAPI.requestBuilderFactory.getBuilder() - - return localVariableRequestBuilder.init(method: "GET", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) - } - - /** - Find pet by ID - - - parameter petId: (path) ID of pet to return - - parameter apiResponseQueue: The queue on which api response is dispatched. - - parameter completion: completion handler to receive the data and the error objects - */ - open class func getPetById(petId: Int64, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Pet?, _ error: Error?) -> Void)) { - getPetByIdWithRequestBuilder(petId: petId).execute(apiResponseQueue) { result in - switch result { - case let .success(response): - completion(response.body, nil) - case let .failure(error): - completion(nil, error) - } + open func uploadFile(petId: Int64, additionalMetadata: String? = nil, file: Data? = nil) -> AnyPublisher, Never> { + // Creating final URL with query items and path + var components = URLComponents() + components.path = "/pet/{petId}/uploadImage" + .replacingOccurrences(of: "{petId}", with: "\(petId)") + + guard let url = components.url(relativeTo: transport.baseURL) else { + fatalError("URL is nil") } - } - - /** - Find pet by ID - - GET /pet/{petId} - - Returns a single pet - - API Key: - - type: apiKey api_key - - name: api_key - - parameter petId: (path) ID of pet to return - - returns: RequestBuilder - */ - open class func getPetByIdWithRequestBuilder(petId: Int64) -> RequestBuilder { - var localVariablePath = "/pet/{petId}" - let petIdPreEscape = "\(APIHelper.mapValueToPathItem(petId))" - let petIdPostEscape = petIdPreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" - localVariablePath = localVariablePath.replacingOccurrences(of: "{petId}", with: petIdPostEscape, options: .literal, range: nil) - let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath - let localVariableParameters: [String: Any]? = nil - - let localVariableUrlComponents = URLComponents(string: localVariableURLString) - - let localVariableNillableHeaders: [String: Any?] = [ - : - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getBuilder() - - return localVariableRequestBuilder.init(method: "GET", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) - } - - /** - Update an existing pet - - - parameter pet: (body) Pet object that needs to be added to the store - - parameter apiResponseQueue: The queue on which api response is dispatched. - - parameter completion: completion handler to receive the data and the error objects - */ - open class func updatePet(pet: Pet, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Pet?, _ error: Error?) -> Void)) { - updatePetWithRequestBuilder(pet: pet).execute(apiResponseQueue) { result in - switch result { - case let .success(response): - completion(response.body, nil) - case let .failure(error): - completion(nil, error) + var request = URLRequest(url: url) + request.httpMethod = "POST" + + + // Getting auth type + let securityScheme: SecurityScheme = .none + return transport.send(request: request, securityScheme: securityScheme) + .map { response -> Result in + if response.response?.statusCode == 200 { + if let data = response.data { + return Result { try self.decoder.decode(ApiResponse.self, from: data) } + } else { + return .failure(TransportError.unknown) + } + } else { + return .failure(response.error ?? TransportError.unknown) + } } - } + .eraseToAnyPublisher() } +} - /** - Update an existing pet - - PUT /pet - - OAuth: - - type: oauth2 - - name: petstore_auth - - parameter pet: (body) Pet object that needs to be added to the store - - returns: RequestBuilder - */ - open class func updatePetWithRequestBuilder(pet: Pet) -> RequestBuilder { - let localVariablePath = "/pet" - let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath - let localVariableParameters = JSONEncodingHelper.encodingParameters(forEncodableObject: pet) - - let localVariableUrlComponents = URLComponents(string: localVariableURLString) - - let localVariableNillableHeaders: [String: Any?] = [ - : - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getBuilder() - return localVariableRequestBuilder.init(method: "PUT", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) +private class OpenISO8601DateFormatter: DateFormatter { + static let withoutSeconds: DateFormatter = { + let formatter = DateFormatter() + formatter.calendar = Calendar(identifier: .iso8601) + formatter.locale = Locale(identifier: "en_US_POSIX") + formatter.timeZone = TimeZone(secondsFromGMT: 0) + formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ" + return formatter + }() + + private func setup() { + calendar = Calendar(identifier: .iso8601) + locale = Locale(identifier: "en_US_POSIX") + timeZone = TimeZone(secondsFromGMT: 0) + dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ" } - /** - Updates a pet in the store with form data - - - parameter petId: (path) ID of pet that needs to be updated - - parameter name: (form) Updated name of the pet (optional) - - parameter status: (form) Updated status of the pet (optional) - - parameter apiResponseQueue: The queue on which api response is dispatched. - - parameter completion: completion handler to receive the data and the error objects - */ - open class func updatePetWithForm(petId: Int64, name: String? = nil, status: String? = nil, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Void?, _ error: Error?) -> Void)) { - updatePetWithFormWithRequestBuilder(petId: petId, name: name, status: status).execute(apiResponseQueue) { result in - switch result { - case .success: - completion((), nil) - case let .failure(error): - completion(nil, error) - } - } + override init() { + super.init() + setup() } - /** - Updates a pet in the store with form data - - POST /pet/{petId} - - OAuth: - - type: oauth2 - - name: petstore_auth - - parameter petId: (path) ID of pet that needs to be updated - - parameter name: (form) Updated name of the pet (optional) - - parameter status: (form) Updated status of the pet (optional) - - returns: RequestBuilder - */ - open class func updatePetWithFormWithRequestBuilder(petId: Int64, name: String? = nil, status: String? = nil) -> RequestBuilder { - var localVariablePath = "/pet/{petId}" - let petIdPreEscape = "\(APIHelper.mapValueToPathItem(petId))" - let petIdPostEscape = petIdPreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" - localVariablePath = localVariablePath.replacingOccurrences(of: "{petId}", with: petIdPostEscape, options: .literal, range: nil) - let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath - let localVariableFormParams: [String: Any?] = [ - "name": name?.encodeToJSON(), - "status": status?.encodeToJSON(), - ] - - let localVariableNonNullParameters = APIHelper.rejectNil(localVariableFormParams) - let localVariableParameters = APIHelper.convertBoolToString(localVariableNonNullParameters) - - let localVariableUrlComponents = URLComponents(string: localVariableURLString) - - let localVariableNillableHeaders: [String: Any?] = [ - "Content-Type": "application/x-www-form-urlencoded", - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() - - return localVariableRequestBuilder.init(method: "POST", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + setup() } - /** - uploads an image - - - parameter petId: (path) ID of pet to update - - parameter additionalMetadata: (form) Additional data to pass to server (optional) - - parameter file: (form) file to upload (optional) - - parameter apiResponseQueue: The queue on which api response is dispatched. - - parameter completion: completion handler to receive the data and the error objects - */ - open class func uploadFile(petId: Int64, additionalMetadata: String? = nil, file: Data? = nil, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: ApiResponse?, _ error: Error?) -> Void)) { - uploadFileWithRequestBuilder(petId: petId, additionalMetadata: additionalMetadata, file: file).execute(apiResponseQueue) { result in - switch result { - case let .success(response): - completion(response.body, nil) - case let .failure(error): - completion(nil, error) - } + override func date(from string: String) -> Date? { + if let result = super.date(from: string) { + return result } + return OpenISO8601DateFormatter.withoutSeconds.date(from: string) } - - /** - uploads an image - - POST /pet/{petId}/uploadImage - - OAuth: - - type: oauth2 - - name: petstore_auth - - parameter petId: (path) ID of pet to update - - parameter additionalMetadata: (form) Additional data to pass to server (optional) - - parameter file: (form) file to upload (optional) - - returns: RequestBuilder - */ - open class func uploadFileWithRequestBuilder(petId: Int64, additionalMetadata: String? = nil, file: Data? = nil) -> RequestBuilder { - var localVariablePath = "/pet/{petId}/uploadImage" - let petIdPreEscape = "\(APIHelper.mapValueToPathItem(petId))" - let petIdPostEscape = petIdPreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" - localVariablePath = localVariablePath.replacingOccurrences(of: "{petId}", with: petIdPostEscape, options: .literal, range: nil) - let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath - let localVariableFormParams: [String: Any?] = [ - "additionalMetadata": additionalMetadata?.encodeToJSON(), - "file": file?.encodeToJSON(), - ] - - let localVariableNonNullParameters = APIHelper.rejectNil(localVariableFormParams) - let localVariableParameters = APIHelper.convertBoolToString(localVariableNonNullParameters) - - let localVariableUrlComponents = URLComponents(string: localVariableURLString) - - let localVariableNillableHeaders: [String: Any?] = [ - "Content-Type": "multipart/form-data", - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getBuilder() - - return localVariableRequestBuilder.init(method: "POST", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) - } -} +} \ No newline at end of file diff --git a/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/APIs/StoreAPI.swift b/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/APIs/StoreAPI.swift index 0482548154fb..d39da57c15eb 100644 --- a/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/APIs/StoreAPI.swift +++ b/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/APIs/StoreAPI.swift @@ -3,7 +3,7 @@ // // Generated by openapi-generator // https://openapi-generator.tech -// +// Run in root folder to build example mvn clean package -DskipTests; ./bin/generate-samples.sh bin/configs/swift-alt-petstore-new.yaml import Foundation import Combine @@ -11,261 +11,204 @@ import Combine open class StoreAPI { + private let encoder: JSONEncoder = { + let encoder = JSONEncoder() + encoder.dateEncodingStrategy = .formatted(OpenISO8601DateFormatter()) + encoder.outputFormatting = .prettyPrinted + return encoder + }() + private let decoder: JSONDecoder = { + let decoder = JSONDecoder() + decoder.dateDecodingStrategy = .formatted(OpenISO8601DateFormatter()) + return decoder + }() private let transport: Transport public init(_ transport: Transport) { self.transport = transport } + /** Delete purchase order by ID - - DELETE /store/order/{orderId} + - DELETE /store/order/{orderId} - For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors - parameter orderId: (path) ID of the order that needs to be deleted - - returns: Future + - returns: AnyPublisher, Never> */ - open func deleteOrder(orderId: String) -> Future { + open func deleteOrder(orderId: String) -> AnyPublisher, Never> { + // Creating final URL with query items and path + var components = URLComponents() + components.path = "/store/order/{orderId}" + .replacingOccurrences(of: "{orderId}", with: "\(orderId)") + + guard let url = components.url(relativeTo: transport.baseURL) else { + fatalError("URL is nil") + } + + var request = URLRequest(url: url) + request.httpMethod = "DELETE" + + + // Getting auth type + let securityScheme: SecurityScheme = .none + return transport.send(request: request, securityScheme: securityScheme) + .map { response -> Result in + if response.response?.statusCode == 200 { + return .success(()) + } else { + return .failure(response.error ?? TransportError.unknown) + } + } + .eraseToAnyPublisher() } + /** Returns pet inventories by status - - GET /store/inventory + - GET /store/inventory - Returns a map of status codes to quantities - API Key: - type: apiKey api_key - name: api_key - - returns: Future<[String: Int], Never> + - returns: AnyPublisher, Never> */ - open func getInventory() -> Future<[String: Int], Never> { + open func getInventory() -> AnyPublisher, Never> { + // Creating final URL with query items and path + var components = URLComponents() + components.path = "/store/inventory" + + guard let url = components.url(relativeTo: transport.baseURL) else { + fatalError("URL is nil") + } + + var request = URLRequest(url: url) + request.httpMethod = "GET" + + + // Getting auth type + let securityScheme: SecurityScheme = .none + return transport.send(request: request, securityScheme: securityScheme) + .map { response -> Result<[String: Int], Error> in + if response.response?.statusCode == 200 { + if let data = response.data { + return Result { try self.decoder.decode([String: Int].self, from: data) } + } else { + return .failure(TransportError.unknown) + } + } else { + return .failure(response.error ?? TransportError.unknown) + } + } + .eraseToAnyPublisher() } + /** Find purchase order by ID - - GET /store/order/{orderId} + - GET /store/order/{orderId} - For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions - parameter orderId: (path) ID of pet that needs to be fetched - - returns: Future + - returns: AnyPublisher, Never> */ - open func getOrderById(orderId: Int64) -> Future { + open func getOrderById(orderId: Int64) -> AnyPublisher, Never> { + // Creating final URL with query items and path + var components = URLComponents() + components.path = "/store/order/{orderId}" + .replacingOccurrences(of: "{orderId}", with: "\(orderId)") + + guard let url = components.url(relativeTo: transport.baseURL) else { + fatalError("URL is nil") + } + + var request = URLRequest(url: url) + request.httpMethod = "GET" + + + // Getting auth type + let securityScheme: SecurityScheme = .none + return transport.send(request: request, securityScheme: securityScheme) + .map { response -> Result in + if response.response?.statusCode == 200 { + if let data = response.data { + return Result { try self.decoder.decode(Order.self, from: data) } + } else { + return .failure(TransportError.unknown) + } + } else { + return .failure(response.error ?? TransportError.unknown) + } + } + .eraseToAnyPublisher() } + /** Place an order for a pet - - POST /store/order + - POST /store/order - parameter order: (body) order placed for purchasing the pet - - returns: Future + - returns: AnyPublisher, Never> */ - open func placeOrder(order: Order) -> Future { - } -} -//// - -/** -- - - API Key: - - type: apiKey api_key - - name: api_key - - OAuth: - - type: oauth2 - - name: petstore_auth -- returns: RequestBuilder - */ -open class func WithRequestBuilder() -> RequestBuilder { -let localVariablePath = "" - let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath - let localVariableParameters: [String: Any]? = nil - - let localVariableUrlComponents = URLComponents(string: localVariableURLString) - - let localVariableNillableHeaders: [String: Any?] = [ - : - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() - - return localVariableRequestBuilder.init(method: "", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) - } - -import Foundation -#if canImport(AnyCodable) -import AnyCodable -#endif - -open class StoreAPI { - - /** - Delete purchase order by ID - - - parameter orderId: (path) ID of the order that needs to be deleted - - parameter apiResponseQueue: The queue on which api response is dispatched. - - parameter completion: completion handler to receive the data and the error objects - */ - open class func deleteOrder(orderId: String, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Void?, _ error: Error?) -> Void)) { - deleteOrderWithRequestBuilder(orderId: orderId).execute(apiResponseQueue) { result in - switch result { - case .success: - completion((), nil) - case let .failure(error): - completion(nil, error) - } + open func placeOrder(order: Order) -> AnyPublisher, Never> { + // Creating final URL with query items and path + var components = URLComponents() + components.path = "/store/order" + + guard let url = components.url(relativeTo: transport.baseURL) else { + fatalError("URL is nil") } - } - - /** - Delete purchase order by ID - - DELETE /store/order/{orderId} - - For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors - - parameter orderId: (path) ID of the order that needs to be deleted - - returns: RequestBuilder - */ - open class func deleteOrderWithRequestBuilder(orderId: String) -> RequestBuilder { - var localVariablePath = "/store/order/{orderId}" - let orderIdPreEscape = "\(APIHelper.mapValueToPathItem(orderId))" - let orderIdPostEscape = orderIdPreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" - localVariablePath = localVariablePath.replacingOccurrences(of: "{orderId}", with: orderIdPostEscape, options: .literal, range: nil) - let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath - let localVariableParameters: [String: Any]? = nil - - let localVariableUrlComponents = URLComponents(string: localVariableURLString) - let localVariableNillableHeaders: [String: Any?] = [ - : - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() - - return localVariableRequestBuilder.init(method: "DELETE", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) - } - - /** - Returns pet inventories by status - - - parameter apiResponseQueue: The queue on which api response is dispatched. - - parameter completion: completion handler to receive the data and the error objects - */ - open class func getInventory(apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: [String: Int]?, _ error: Error?) -> Void)) { - getInventoryWithRequestBuilder().execute(apiResponseQueue) { result in - switch result { - case let .success(response): - completion(response.body, nil) - case let .failure(error): - completion(nil, error) + var request = URLRequest(url: url) + request.httpMethod = "POST" + + // Setting body parameters + request.httpBody = try? encoder.encode(order) + // Getting auth type + let securityScheme: SecurityScheme = .none + return transport.send(request: request, securityScheme: securityScheme) + .map { response -> Result in + if response.response?.statusCode == 200 { + if let data = response.data { + return Result { try self.decoder.decode(Order.self, from: data) } + } else { + return .failure(TransportError.unknown) + } + } else { + return .failure(response.error ?? TransportError.unknown) + } } - } + .eraseToAnyPublisher() } +} - /** - Returns pet inventories by status - - GET /store/inventory - - Returns a map of status codes to quantities - - API Key: - - type: apiKey api_key - - name: api_key - - returns: RequestBuilder<[String: Int]> - */ - open class func getInventoryWithRequestBuilder() -> RequestBuilder<[String: Int]> { - let localVariablePath = "/store/inventory" - let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath - let localVariableParameters: [String: Any]? = nil - - let localVariableUrlComponents = URLComponents(string: localVariableURLString) - - let localVariableNillableHeaders: [String: Any?] = [ - : - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder<[String: Int]>.Type = OpenAPIClientAPI.requestBuilderFactory.getBuilder() - return localVariableRequestBuilder.init(method: "GET", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) +private class OpenISO8601DateFormatter: DateFormatter { + static let withoutSeconds: DateFormatter = { + let formatter = DateFormatter() + formatter.calendar = Calendar(identifier: .iso8601) + formatter.locale = Locale(identifier: "en_US_POSIX") + formatter.timeZone = TimeZone(secondsFromGMT: 0) + formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ" + return formatter + }() + + private func setup() { + calendar = Calendar(identifier: .iso8601) + locale = Locale(identifier: "en_US_POSIX") + timeZone = TimeZone(secondsFromGMT: 0) + dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ" } - /** - Find purchase order by ID - - - parameter orderId: (path) ID of pet that needs to be fetched - - parameter apiResponseQueue: The queue on which api response is dispatched. - - parameter completion: completion handler to receive the data and the error objects - */ - open class func getOrderById(orderId: Int64, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Order?, _ error: Error?) -> Void)) { - getOrderByIdWithRequestBuilder(orderId: orderId).execute(apiResponseQueue) { result in - switch result { - case let .success(response): - completion(response.body, nil) - case let .failure(error): - completion(nil, error) - } - } + override init() { + super.init() + setup() } - /** - Find purchase order by ID - - GET /store/order/{orderId} - - For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions - - parameter orderId: (path) ID of pet that needs to be fetched - - returns: RequestBuilder - */ - open class func getOrderByIdWithRequestBuilder(orderId: Int64) -> RequestBuilder { - var localVariablePath = "/store/order/{orderId}" - let orderIdPreEscape = "\(APIHelper.mapValueToPathItem(orderId))" - let orderIdPostEscape = orderIdPreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" - localVariablePath = localVariablePath.replacingOccurrences(of: "{orderId}", with: orderIdPostEscape, options: .literal, range: nil) - let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath - let localVariableParameters: [String: Any]? = nil - - let localVariableUrlComponents = URLComponents(string: localVariableURLString) - - let localVariableNillableHeaders: [String: Any?] = [ - : - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getBuilder() - - return localVariableRequestBuilder.init(method: "GET", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + setup() } - /** - Place an order for a pet - - - parameter order: (body) order placed for purchasing the pet - - parameter apiResponseQueue: The queue on which api response is dispatched. - - parameter completion: completion handler to receive the data and the error objects - */ - open class func placeOrder(order: Order, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Order?, _ error: Error?) -> Void)) { - placeOrderWithRequestBuilder(order: order).execute(apiResponseQueue) { result in - switch result { - case let .success(response): - completion(response.body, nil) - case let .failure(error): - completion(nil, error) - } + override func date(from string: String) -> Date? { + if let result = super.date(from: string) { + return result } + return OpenISO8601DateFormatter.withoutSeconds.date(from: string) } - - /** - Place an order for a pet - - POST /store/order - - parameter order: (body) order placed for purchasing the pet - - returns: RequestBuilder - */ - open class func placeOrderWithRequestBuilder(order: Order) -> RequestBuilder { - let localVariablePath = "/store/order" - let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath - let localVariableParameters = JSONEncodingHelper.encodingParameters(forEncodableObject: order) - - let localVariableUrlComponents = URLComponents(string: localVariableURLString) - - let localVariableNillableHeaders: [String: Any?] = [ - : - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getBuilder() - - return localVariableRequestBuilder.init(method: "POST", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) - } -} +} \ No newline at end of file diff --git a/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/APIs/UserAPI.swift b/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/APIs/UserAPI.swift index a9dcc7267b0f..b533bd3f360d 100644 --- a/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/APIs/UserAPI.swift +++ b/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/APIs/UserAPI.swift @@ -3,7 +3,7 @@ // // Generated by openapi-generator // https://openapi-generator.tech -// +// Run in root folder to build example mvn clean package -DskipTests; ./bin/generate-samples.sh bin/configs/swift-alt-petstore-new.yaml import Foundation import Combine @@ -11,506 +11,353 @@ import Combine open class UserAPI { + private let encoder: JSONEncoder = { + let encoder = JSONEncoder() + encoder.dateEncodingStrategy = .formatted(OpenISO8601DateFormatter()) + encoder.outputFormatting = .prettyPrinted + return encoder + }() + private let decoder: JSONDecoder = { + let decoder = JSONDecoder() + decoder.dateDecodingStrategy = .formatted(OpenISO8601DateFormatter()) + return decoder + }() private let transport: Transport public init(_ transport: Transport) { self.transport = transport } + /** Create user - - POST /user + - POST /user - This can only be done by the logged in user. - API Key: - type: apiKey api_key - name: api_key - parameter user: (body) Created user object - - returns: Future + - returns: AnyPublisher, Never> */ - open func createUser(user: User) -> Future { + open func createUser(user: User) -> AnyPublisher, Never> { + // Creating final URL with query items and path + var components = URLComponents() + components.path = "/user" + + guard let url = components.url(relativeTo: transport.baseURL) else { + fatalError("URL is nil") + } + + var request = URLRequest(url: url) + request.httpMethod = "POST" + + // Setting body parameters + request.httpBody = try? encoder.encode(user) + // Getting auth type + let securityScheme: SecurityScheme = .none + return transport.send(request: request, securityScheme: securityScheme) + .map { response -> Result in + if response.response?.statusCode == 200 { + return .success(()) + } else { + return .failure(response.error ?? TransportError.unknown) + } + } + .eraseToAnyPublisher() } + /** Creates list of users with given input array - - POST /user/createWithArray + - POST /user/createWithArray - API Key: - type: apiKey api_key - name: api_key - parameter user: (body) List of user object - - returns: Future + - returns: AnyPublisher, Never> */ - open func createUsersWithArrayInput(user: [User]) -> Future { + open func createUsersWithArrayInput(user: [User]) -> AnyPublisher, Never> { + // Creating final URL with query items and path + var components = URLComponents() + components.path = "/user/createWithArray" + + guard let url = components.url(relativeTo: transport.baseURL) else { + fatalError("URL is nil") + } + + var request = URLRequest(url: url) + request.httpMethod = "POST" + + // Setting body parameters + request.httpBody = try? encoder.encode(user) + // Getting auth type + let securityScheme: SecurityScheme = .none + return transport.send(request: request, securityScheme: securityScheme) + .map { response -> Result in + if response.response?.statusCode == 200 { + return .success(()) + } else { + return .failure(response.error ?? TransportError.unknown) + } + } + .eraseToAnyPublisher() } + /** Creates list of users with given input array - - POST /user/createWithList + - POST /user/createWithList - API Key: - type: apiKey api_key - name: api_key - parameter user: (body) List of user object - - returns: Future + - returns: AnyPublisher, Never> */ - open func createUsersWithListInput(user: [User]) -> Future { + open func createUsersWithListInput(user: [User]) -> AnyPublisher, Never> { + // Creating final URL with query items and path + var components = URLComponents() + components.path = "/user/createWithList" + + guard let url = components.url(relativeTo: transport.baseURL) else { + fatalError("URL is nil") + } + + var request = URLRequest(url: url) + request.httpMethod = "POST" + + // Setting body parameters + request.httpBody = try? encoder.encode(user) + // Getting auth type + let securityScheme: SecurityScheme = .none + return transport.send(request: request, securityScheme: securityScheme) + .map { response -> Result in + if response.response?.statusCode == 200 { + return .success(()) + } else { + return .failure(response.error ?? TransportError.unknown) + } + } + .eraseToAnyPublisher() } + /** Delete user - - DELETE /user/{username} + - DELETE /user/{username} - This can only be done by the logged in user. - API Key: - type: apiKey api_key - name: api_key - parameter username: (path) The name that needs to be deleted - - returns: Future + - returns: AnyPublisher, Never> */ - open func deleteUser(username: String) -> Future { + open func deleteUser(username: String) -> AnyPublisher, Never> { + // Creating final URL with query items and path + var components = URLComponents() + components.path = "/user/{username}" + .replacingOccurrences(of: "{username}", with: "\(username)") + + guard let url = components.url(relativeTo: transport.baseURL) else { + fatalError("URL is nil") + } + + var request = URLRequest(url: url) + request.httpMethod = "DELETE" + + + // Getting auth type + let securityScheme: SecurityScheme = .none + return transport.send(request: request, securityScheme: securityScheme) + .map { response -> Result in + if response.response?.statusCode == 200 { + return .success(()) + } else { + return .failure(response.error ?? TransportError.unknown) + } + } + .eraseToAnyPublisher() } + /** Get user by user name - - GET /user/{username} + - GET /user/{username} - parameter username: (path) The name that needs to be fetched. Use user1 for testing. - - returns: Future + - returns: AnyPublisher, Never> */ - open func getUserByName(username: String) -> Future { + open func getUserByName(username: String) -> AnyPublisher, Never> { + // Creating final URL with query items and path + var components = URLComponents() + components.path = "/user/{username}" + .replacingOccurrences(of: "{username}", with: "\(username)") + + guard let url = components.url(relativeTo: transport.baseURL) else { + fatalError("URL is nil") + } + + var request = URLRequest(url: url) + request.httpMethod = "GET" + + + // Getting auth type + let securityScheme: SecurityScheme = .none + return transport.send(request: request, securityScheme: securityScheme) + .map { response -> Result in + if response.response?.statusCode == 200 { + if let data = response.data { + return Result { try self.decoder.decode(User.self, from: data) } + } else { + return .failure(TransportError.unknown) + } + } else { + return .failure(response.error ?? TransportError.unknown) + } + } + .eraseToAnyPublisher() } + /** Logs user into the system - - GET /user/login + - GET /user/login - responseHeaders: [Set-Cookie(String), X-Rate-Limit(Int), X-Expires-After(Date)] - - parameter username: () The user name for login - - parameter password: () The password for login in clear text - - returns: Future + - parameter username: (query) The user name for login + - parameter password: (query) The password for login in clear text + - returns: AnyPublisher, Never> */ - open func loginUser(username: String, password: String) -> Future { + open func loginUser(username: String, password: String) -> AnyPublisher, Never> { + // Creating final URL with query items and path + var components = URLComponents() + components.path = "/user/login" + components.queryItems = [ + URLQueryItem(name: "username", value: username), + URLQueryItem(name: "password", value: password) + ] + guard let url = components.url(relativeTo: transport.baseURL) else { + fatalError("URL is nil") + } + + var request = URLRequest(url: url) + request.httpMethod = "GET" + + + // Getting auth type + let securityScheme: SecurityScheme = .none + return transport.send(request: request, securityScheme: securityScheme) + .map { response -> Result in + if response.response?.statusCode == 200 { + if let data = response.data { + return Result { try self.decoder.decode(String.self, from: data) } + } else { + return .failure(TransportError.unknown) + } + } else { + return .failure(response.error ?? TransportError.unknown) + } + } + .eraseToAnyPublisher() } + /** Logs out current logged in user session - - GET /user/logout + - GET /user/logout - API Key: - type: apiKey api_key - name: api_key - - returns: Future + - returns: AnyPublisher, Never> */ - open func logoutUser() -> Future { + open func logoutUser() -> AnyPublisher, Never> { + // Creating final URL with query items and path + var components = URLComponents() + components.path = "/user/logout" + + guard let url = components.url(relativeTo: transport.baseURL) else { + fatalError("URL is nil") + } + + var request = URLRequest(url: url) + request.httpMethod = "GET" + + + // Getting auth type + let securityScheme: SecurityScheme = .none + return transport.send(request: request, securityScheme: securityScheme) + .map { response -> Result in + if response.response?.statusCode == 200 { + return .success(()) + } else { + return .failure(response.error ?? TransportError.unknown) + } + } + .eraseToAnyPublisher() } + /** Updated user - - PUT /user/{username} + - PUT /user/{username} - This can only be done by the logged in user. - API Key: - type: apiKey api_key - name: api_key - parameter username: (path) name that need to be deleted - parameter user: (body) Updated user object - - returns: Future + - returns: AnyPublisher, Never> */ - open func updateUser(username: String, user: User) -> Future { - } -} -//// - -/** -- - - API Key: - - type: apiKey api_key - - name: api_key - - OAuth: - - type: oauth2 - - name: petstore_auth -- returns: RequestBuilder - */ -open class func WithRequestBuilder() -> RequestBuilder { -let localVariablePath = "" - let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath - let localVariableParameters: [String: Any]? = nil - - let localVariableUrlComponents = URLComponents(string: localVariableURLString) - - let localVariableNillableHeaders: [String: Any?] = [ - : - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() - - return localVariableRequestBuilder.init(method: "", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) - } - -import Foundation -#if canImport(AnyCodable) -import AnyCodable -#endif - -open class UserAPI { - - /** - Create user - - - parameter user: (body) Created user object - - parameter apiResponseQueue: The queue on which api response is dispatched. - - parameter completion: completion handler to receive the data and the error objects - */ - open class func createUser(user: User, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Void?, _ error: Error?) -> Void)) { - createUserWithRequestBuilder(user: user).execute(apiResponseQueue) { result in - switch result { - case .success: - completion((), nil) - case let .failure(error): - completion(nil, error) - } - } - } - - /** - Create user - - POST /user - - This can only be done by the logged in user. - - API Key: - - type: apiKey api_key - - name: api_key - - parameter user: (body) Created user object - - returns: RequestBuilder - */ - open class func createUserWithRequestBuilder(user: User) -> RequestBuilder { - let localVariablePath = "/user" - let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath - let localVariableParameters = JSONEncodingHelper.encodingParameters(forEncodableObject: user) - - let localVariableUrlComponents = URLComponents(string: localVariableURLString) - - let localVariableNillableHeaders: [String: Any?] = [ - : - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() - - return localVariableRequestBuilder.init(method: "POST", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) - } - - /** - Creates list of users with given input array - - - parameter user: (body) List of user object - - parameter apiResponseQueue: The queue on which api response is dispatched. - - parameter completion: completion handler to receive the data and the error objects - */ - open class func createUsersWithArrayInput(user: [User], apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Void?, _ error: Error?) -> Void)) { - createUsersWithArrayInputWithRequestBuilder(user: user).execute(apiResponseQueue) { result in - switch result { - case .success: - completion((), nil) - case let .failure(error): - completion(nil, error) - } - } - } - - /** - Creates list of users with given input array - - POST /user/createWithArray - - API Key: - - type: apiKey api_key - - name: api_key - - parameter user: (body) List of user object - - returns: RequestBuilder - */ - open class func createUsersWithArrayInputWithRequestBuilder(user: [User]) -> RequestBuilder { - let localVariablePath = "/user/createWithArray" - let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath - let localVariableParameters = JSONEncodingHelper.encodingParameters(forEncodableObject: user) - - let localVariableUrlComponents = URLComponents(string: localVariableURLString) - - let localVariableNillableHeaders: [String: Any?] = [ - : - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() - - return localVariableRequestBuilder.init(method: "POST", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) - } - - /** - Creates list of users with given input array - - - parameter user: (body) List of user object - - parameter apiResponseQueue: The queue on which api response is dispatched. - - parameter completion: completion handler to receive the data and the error objects - */ - open class func createUsersWithListInput(user: [User], apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Void?, _ error: Error?) -> Void)) { - createUsersWithListInputWithRequestBuilder(user: user).execute(apiResponseQueue) { result in - switch result { - case .success: - completion((), nil) - case let .failure(error): - completion(nil, error) - } - } - } - - /** - Creates list of users with given input array - - POST /user/createWithList - - API Key: - - type: apiKey api_key - - name: api_key - - parameter user: (body) List of user object - - returns: RequestBuilder - */ - open class func createUsersWithListInputWithRequestBuilder(user: [User]) -> RequestBuilder { - let localVariablePath = "/user/createWithList" - let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath - let localVariableParameters = JSONEncodingHelper.encodingParameters(forEncodableObject: user) - - let localVariableUrlComponents = URLComponents(string: localVariableURLString) - - let localVariableNillableHeaders: [String: Any?] = [ - : - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() - - return localVariableRequestBuilder.init(method: "POST", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) - } - - /** - Delete user - - - parameter username: (path) The name that needs to be deleted - - parameter apiResponseQueue: The queue on which api response is dispatched. - - parameter completion: completion handler to receive the data and the error objects - */ - open class func deleteUser(username: String, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Void?, _ error: Error?) -> Void)) { - deleteUserWithRequestBuilder(username: username).execute(apiResponseQueue) { result in - switch result { - case .success: - completion((), nil) - case let .failure(error): - completion(nil, error) - } - } - } - - /** - Delete user - - DELETE /user/{username} - - This can only be done by the logged in user. - - API Key: - - type: apiKey api_key - - name: api_key - - parameter username: (path) The name that needs to be deleted - - returns: RequestBuilder - */ - open class func deleteUserWithRequestBuilder(username: String) -> RequestBuilder { - var localVariablePath = "/user/{username}" - let usernamePreEscape = "\(APIHelper.mapValueToPathItem(username))" - let usernamePostEscape = usernamePreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" - localVariablePath = localVariablePath.replacingOccurrences(of: "{username}", with: usernamePostEscape, options: .literal, range: nil) - let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath - let localVariableParameters: [String: Any]? = nil - - let localVariableUrlComponents = URLComponents(string: localVariableURLString) - - let localVariableNillableHeaders: [String: Any?] = [ - : - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() - - return localVariableRequestBuilder.init(method: "DELETE", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) - } - - /** - Get user by user name - - - parameter username: (path) The name that needs to be fetched. Use user1 for testing. - - parameter apiResponseQueue: The queue on which api response is dispatched. - - parameter completion: completion handler to receive the data and the error objects - */ - open class func getUserByName(username: String, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: User?, _ error: Error?) -> Void)) { - getUserByNameWithRequestBuilder(username: username).execute(apiResponseQueue) { result in - switch result { - case let .success(response): - completion(response.body, nil) - case let .failure(error): - completion(nil, error) - } + open func updateUser(username: String, user: User) -> AnyPublisher, Never> { + // Creating final URL with query items and path + var components = URLComponents() + components.path = "/user/{username}" + .replacingOccurrences(of: "{username}", with: "\(username)") + + guard let url = components.url(relativeTo: transport.baseURL) else { + fatalError("URL is nil") } - } - - /** - Get user by user name - - GET /user/{username} - - parameter username: (path) The name that needs to be fetched. Use user1 for testing. - - returns: RequestBuilder - */ - open class func getUserByNameWithRequestBuilder(username: String) -> RequestBuilder { - var localVariablePath = "/user/{username}" - let usernamePreEscape = "\(APIHelper.mapValueToPathItem(username))" - let usernamePostEscape = usernamePreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" - localVariablePath = localVariablePath.replacingOccurrences(of: "{username}", with: usernamePostEscape, options: .literal, range: nil) - let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath - let localVariableParameters: [String: Any]? = nil - - let localVariableUrlComponents = URLComponents(string: localVariableURLString) - - let localVariableNillableHeaders: [String: Any?] = [ - : - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getBuilder() - - return localVariableRequestBuilder.init(method: "GET", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) - } - /** - Logs user into the system - - - parameter username: (query) The user name for login - - parameter password: (query) The password for login in clear text - - parameter apiResponseQueue: The queue on which api response is dispatched. - - parameter completion: completion handler to receive the data and the error objects - */ - open class func loginUser(username: String, password: String, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: String?, _ error: Error?) -> Void)) { - loginUserWithRequestBuilder(username: username, password: password).execute(apiResponseQueue) { result in - switch result { - case let .success(response): - completion(response.body, nil) - case let .failure(error): - completion(nil, error) + var request = URLRequest(url: url) + request.httpMethod = "PUT" + + // Setting body parameters + request.httpBody = try? encoder.encode(user) + // Getting auth type + let securityScheme: SecurityScheme = .none + return transport.send(request: request, securityScheme: securityScheme) + .map { response -> Result in + if response.response?.statusCode == 200 { + return .success(()) + } else { + return .failure(response.error ?? TransportError.unknown) + } } - } + .eraseToAnyPublisher() } +} - /** - Logs user into the system - - GET /user/login - - responseHeaders: [Set-Cookie(String), X-Rate-Limit(Int), X-Expires-After(Date)] - - parameter username: (query) The user name for login - - parameter password: (query) The password for login in clear text - - returns: RequestBuilder - */ - open class func loginUserWithRequestBuilder(username: String, password: String) -> RequestBuilder { - let localVariablePath = "/user/login" - let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath - let localVariableParameters: [String: Any]? = nil - - var localVariableUrlComponents = URLComponents(string: localVariableURLString) - localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems([ - "username": username.encodeToJSON(), - "password": password.encodeToJSON(), - ]) - - let localVariableNillableHeaders: [String: Any?] = [ - : - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getBuilder() - return localVariableRequestBuilder.init(method: "GET", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) +private class OpenISO8601DateFormatter: DateFormatter { + static let withoutSeconds: DateFormatter = { + let formatter = DateFormatter() + formatter.calendar = Calendar(identifier: .iso8601) + formatter.locale = Locale(identifier: "en_US_POSIX") + formatter.timeZone = TimeZone(secondsFromGMT: 0) + formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ" + return formatter + }() + + private func setup() { + calendar = Calendar(identifier: .iso8601) + locale = Locale(identifier: "en_US_POSIX") + timeZone = TimeZone(secondsFromGMT: 0) + dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ" } - /** - Logs out current logged in user session - - - parameter apiResponseQueue: The queue on which api response is dispatched. - - parameter completion: completion handler to receive the data and the error objects - */ - open class func logoutUser(apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Void?, _ error: Error?) -> Void)) { - logoutUserWithRequestBuilder().execute(apiResponseQueue) { result in - switch result { - case .success: - completion((), nil) - case let .failure(error): - completion(nil, error) - } - } + override init() { + super.init() + setup() } - /** - Logs out current logged in user session - - GET /user/logout - - API Key: - - type: apiKey api_key - - name: api_key - - returns: RequestBuilder - */ - open class func logoutUserWithRequestBuilder() -> RequestBuilder { - let localVariablePath = "/user/logout" - let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath - let localVariableParameters: [String: Any]? = nil - - let localVariableUrlComponents = URLComponents(string: localVariableURLString) - - let localVariableNillableHeaders: [String: Any?] = [ - : - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() - - return localVariableRequestBuilder.init(method: "GET", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + setup() } - /** - Updated user - - - parameter username: (path) name that need to be deleted - - parameter user: (body) Updated user object - - parameter apiResponseQueue: The queue on which api response is dispatched. - - parameter completion: completion handler to receive the data and the error objects - */ - open class func updateUser(username: String, user: User, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Void?, _ error: Error?) -> Void)) { - updateUserWithRequestBuilder(username: username, user: user).execute(apiResponseQueue) { result in - switch result { - case .success: - completion((), nil) - case let .failure(error): - completion(nil, error) - } + override func date(from string: String) -> Date? { + if let result = super.date(from: string) { + return result } + return OpenISO8601DateFormatter.withoutSeconds.date(from: string) } - - /** - Updated user - - PUT /user/{username} - - This can only be done by the logged in user. - - API Key: - - type: apiKey api_key - - name: api_key - - parameter username: (path) name that need to be deleted - - parameter user: (body) Updated user object - - returns: RequestBuilder - */ - open class func updateUserWithRequestBuilder(username: String, user: User) -> RequestBuilder { - var localVariablePath = "/user/{username}" - let usernamePreEscape = "\(APIHelper.mapValueToPathItem(username))" - let usernamePostEscape = usernamePreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" - localVariablePath = localVariablePath.replacingOccurrences(of: "{username}", with: usernamePostEscape, options: .literal, range: nil) - let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath - let localVariableParameters = JSONEncodingHelper.encodingParameters(forEncodableObject: user) - - let localVariableUrlComponents = URLComponents(string: localVariableURLString) - - let localVariableNillableHeaders: [String: Any?] = [ - : - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() - - return localVariableRequestBuilder.init(method: "PUT", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) - } -} +} \ No newline at end of file From 33c3b58e8c9701f1599251395b7677fc8813ad04 Mon Sep 17 00:00:00 2001 From: Anton Davydov Date: Mon, 15 Nov 2021 16:26:12 +0300 Subject: [PATCH 04/33] swift-alt added transport --- bin/configs/swift-alt-petstore-new.yaml | 2 +- .../languages/SwiftAltClientCodegen.java | 20 +- .../resources/swift-alt/APIHelper.mustache | 72 - .../main/resources/swift-alt/APIs.mustache | 68 - .../swift-alt/CodableHelper.mustache | 49 - .../swift-alt/Configuration.mustache | 28 - .../resources/swift-alt/Extensions.mustache | 238 --- .../swift-alt/JSONDataEncoding.mustache | 53 - .../swift-alt/JSONEncodingHelper.mustache | 45 - .../main/resources/swift-alt/Models.mustache | 54 - .../src/main/resources/swift-alt/Old.swift | 1361 ----------------- .../OpenISO8601DateFormatter.mustache | 4 +- .../main/resources/swift-alt/Package.mustache | 24 + .../swift-alt/Package.swift.mustache | 57 - .../main/resources/swift-alt/Runtime.mustache | 135 ++ .../main/resources/swift-alt/Runtime.swift | 233 ++- .../swift-alt/SynchronizedDictionary.mustache | 36 - .../resources/swift-alt/XcodeGen.mustache | 18 - .../swift-alt/_converted_param.mustache | 1 - .../main/resources/swift-alt/_param.mustache | 1 - .../src/main/resources/swift-alt/api.mustache | 78 +- .../main/resources/swift-alt/api_old.mustache | 515 ------- .../main/resources/swift-alt/model.mustache | 3 - .../.openapi-generator-ignore | 0 .../swift-alt/.openapi-generator/FILES | 12 + .../.openapi-generator/VERSION | 0 .../contents.xcworkspacedata | 0 .../UserInterfaceState.xcuserstate | Bin 0 -> 16927 bytes .../xcschemes/xcschememanagement.plist} | 10 +- .../client/petstore/swift-alt/Package.swift | 24 + .../Sources}/APIs/PetAPI.swift | 204 +-- .../swift-alt/Sources/APIs/StoreAPI.swift | 154 ++ .../Sources}/APIs/UserAPI.swift | 200 +-- .../Sources}/Models/ApiResponse.swift | 3 - .../Sources}/Models/Category.swift | 3 - .../Sources}/Models/Order.swift | 3 - .../Sources}/Models/Pet.swift | 3 - .../Sources}/Models/Tag.swift | 3 - .../Sources}/Models/User.swift | 3 - .../Private/OpenISO8601DateFormatter.swift | 44 + .../petstore/swift-alt/Sources/Runtime.swift | 135 ++ .../swift/alt/.openapi-generator/FILES | 11 - samples/client/petstore/swift/alt/Info.plist | 22 - .../OpenAPIClient.xcodeproj/project.pbxproj | 403 ----- .../UserInterfaceState.xcuserstate | Bin 36691 -> 0 bytes .../xcschemes/OpenAPIClient.xcscheme | 94 -- .../Classes/OpenAPIs/APIs/StoreAPI.swift | 214 --- .../client/petstore/swift/alt/Package.swift | 33 - samples/client/petstore/swift/alt/README.md | 0 samples/client/petstore/swift/alt/project.yml | 15 - 50 files changed, 804 insertions(+), 3884 deletions(-) delete mode 100644 modules/openapi-generator/src/main/resources/swift-alt/APIHelper.mustache delete mode 100644 modules/openapi-generator/src/main/resources/swift-alt/APIs.mustache delete mode 100644 modules/openapi-generator/src/main/resources/swift-alt/CodableHelper.mustache delete mode 100644 modules/openapi-generator/src/main/resources/swift-alt/Configuration.mustache delete mode 100644 modules/openapi-generator/src/main/resources/swift-alt/Extensions.mustache delete mode 100644 modules/openapi-generator/src/main/resources/swift-alt/JSONDataEncoding.mustache delete mode 100644 modules/openapi-generator/src/main/resources/swift-alt/JSONEncodingHelper.mustache delete mode 100644 modules/openapi-generator/src/main/resources/swift-alt/Models.mustache delete mode 100644 modules/openapi-generator/src/main/resources/swift-alt/Old.swift create mode 100644 modules/openapi-generator/src/main/resources/swift-alt/Package.mustache delete mode 100644 modules/openapi-generator/src/main/resources/swift-alt/Package.swift.mustache create mode 100644 modules/openapi-generator/src/main/resources/swift-alt/Runtime.mustache delete mode 100644 modules/openapi-generator/src/main/resources/swift-alt/SynchronizedDictionary.mustache delete mode 100644 modules/openapi-generator/src/main/resources/swift-alt/XcodeGen.mustache delete mode 100644 modules/openapi-generator/src/main/resources/swift-alt/_converted_param.mustache delete mode 100644 modules/openapi-generator/src/main/resources/swift-alt/_param.mustache delete mode 100644 modules/openapi-generator/src/main/resources/swift-alt/api_old.mustache rename samples/client/petstore/{swift/alt => swift-alt}/.openapi-generator-ignore (100%) create mode 100644 samples/client/petstore/swift-alt/.openapi-generator/FILES rename samples/client/petstore/{swift/alt => swift-alt}/.openapi-generator/VERSION (100%) rename samples/client/petstore/{swift/alt/OpenAPIClient.xcodeproj/project.xcworkspace => swift-alt/.swiftpm/xcode/package.xcworkspace}/contents.xcworkspacedata (100%) create mode 100644 samples/client/petstore/swift-alt/.swiftpm/xcode/package.xcworkspace/xcuserdata/a.davydov.xcuserdatad/UserInterfaceState.xcuserstate rename samples/client/petstore/{swift/alt/OpenAPIClient.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist => swift-alt/.swiftpm/xcode/xcuserdata/a.davydov.xcuserdatad/xcschemes/xcschememanagement.plist} (54%) create mode 100644 samples/client/petstore/swift-alt/Package.swift rename samples/client/petstore/{swift/alt/OpenAPIClient/Classes/OpenAPIs => swift-alt/Sources}/APIs/PetAPI.swift (52%) create mode 100644 samples/client/petstore/swift-alt/Sources/APIs/StoreAPI.swift rename samples/client/petstore/{swift/alt/OpenAPIClient/Classes/OpenAPIs => swift-alt/Sources}/APIs/UserAPI.swift (54%) rename samples/client/petstore/{swift/alt/OpenAPIClient/Classes/OpenAPIs => swift-alt/Sources}/Models/ApiResponse.swift (94%) rename samples/client/petstore/{swift/alt/OpenAPIClient/Classes/OpenAPIs => swift-alt/Sources}/Models/Category.swift (93%) rename samples/client/petstore/{swift/alt/OpenAPIClient/Classes/OpenAPIs => swift-alt/Sources}/Models/Order.swift (97%) rename samples/client/petstore/{swift/alt/OpenAPIClient/Classes/OpenAPIs => swift-alt/Sources}/Models/Pet.swift (96%) rename samples/client/petstore/{swift/alt/OpenAPIClient/Classes/OpenAPIs => swift-alt/Sources}/Models/Tag.swift (93%) rename samples/client/petstore/{swift/alt/OpenAPIClient/Classes/OpenAPIs => swift-alt/Sources}/Models/User.swift (97%) create mode 100644 samples/client/petstore/swift-alt/Sources/Private/OpenISO8601DateFormatter.swift create mode 100644 samples/client/petstore/swift-alt/Sources/Runtime.swift delete mode 100644 samples/client/petstore/swift/alt/.openapi-generator/FILES delete mode 100644 samples/client/petstore/swift/alt/Info.plist delete mode 100644 samples/client/petstore/swift/alt/OpenAPIClient.xcodeproj/project.pbxproj delete mode 100644 samples/client/petstore/swift/alt/OpenAPIClient.xcodeproj/project.xcworkspace/xcuserdata/a.davydov.xcuserdatad/UserInterfaceState.xcuserstate delete mode 100644 samples/client/petstore/swift/alt/OpenAPIClient.xcodeproj/xcshareddata/xcschemes/OpenAPIClient.xcscheme delete mode 100644 samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/APIs/StoreAPI.swift delete mode 100644 samples/client/petstore/swift/alt/Package.swift delete mode 100644 samples/client/petstore/swift/alt/README.md delete mode 100644 samples/client/petstore/swift/alt/project.yml diff --git a/bin/configs/swift-alt-petstore-new.yaml b/bin/configs/swift-alt-petstore-new.yaml index 3f60f1a221ae..97e9a9c027dc 100644 --- a/bin/configs/swift-alt-petstore-new.yaml +++ b/bin/configs/swift-alt-petstore-new.yaml @@ -1,5 +1,5 @@ generatorName: swift-alt -outputDir: samples/client/petstore/swift/alt +outputDir: samples/client/petstore/swift-alt inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml templateDir: modules/openapi-generator/src/main/resources/swift-alt additionalProperties: diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java index ca36c092dec0..cac4d0690f93 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java @@ -47,8 +47,8 @@ public class SwiftAltClientCodegen extends DefaultCodegen implements CodegenConf public static final String PROJECT_NAME = "projectName"; protected String projectName = "OpenAPIClient"; - protected String swiftPackagePath = "Classes" + File.separator + "OpenAPIs"; - protected String sourceFolder = swiftPackagePath; + protected String privateFolder = "Sources/Private"; + protected String sourceFolder = "Sources"; /** * Constructor for the swift alt language codegen module. @@ -64,12 +64,15 @@ public SwiftAltClientCodegen() { outputFolder = "generated-code" + File.separator + "swift"; modelTemplateFiles.put("model.mustache", ".swift"); apiTemplateFiles.put("api.mustache", ".swift"); - supportingFiles.add(new SupportingFile("Package.swift.mustache", + supportingFiles.add(new SupportingFile("Package.mustache", "", "Package.swift")); - supportingFiles.add(new SupportingFile("XcodeGen.mustache", - "", - "project.yml")); + supportingFiles.add(new SupportingFile("Runtime.mustache", + sourceFolder, + "Runtime.swift")); + supportingFiles.add(new SupportingFile("OpenISO8601DateFormatter.mustache", + privateFolder, + "OpenISO8601DateFormatter.swift")); embeddedTemplateDir = templateDir = "swift-alt"; apiPackage = File.separator + "APIs"; modelPackage = File.separator + "Models"; @@ -281,7 +284,6 @@ public void processOpts() { } else { additionalProperties.put(PROJECT_NAME, projectName); } - sourceFolder = projectName + File.separator + sourceFolder; } @Override @@ -562,10 +564,6 @@ public CodegenModel fromModel(String name, Schema model) { public void setProjectName(String projectName) { this.projectName = projectName; } - public void setSwiftPackagePath(String swiftPackagePath) { - this.swiftPackagePath = swiftPackagePath; - } - @Override public String toEnumValue(String value, String datatype) { // for string, array of string diff --git a/modules/openapi-generator/src/main/resources/swift-alt/APIHelper.mustache b/modules/openapi-generator/src/main/resources/swift-alt/APIHelper.mustache deleted file mode 100644 index e535c7df4c44..000000000000 --- a/modules/openapi-generator/src/main/resources/swift-alt/APIHelper.mustache +++ /dev/null @@ -1,72 +0,0 @@ -// APIHelper.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech -// - -import Foundation{{#useVapor}} -import Vapor{{/useVapor}} - -{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} struct APIHelper { - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} static func rejectNil(_ source: [String: Any?]) -> [String: Any]? { - let destination = source.reduce(into: [String: Any]()) { result, item in - if let value = item.value { - result[item.key] = value - } - } - - if destination.isEmpty { - return nil - } - return destination - } - - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} static func rejectNilHeaders(_ source: [String: Any?]) -> [String: String] { - return source.reduce(into: [String: String]()) { result, item in - if let collection = item.value as? [Any?] { - result[item.key] = collection.filter { $0 != nil }.map { "\($0!)" }.joined(separator: ",") - } else if let value: Any = item.value { - result[item.key] = "\(value)" - } - } - } - - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} static func convertBoolToString(_ source: [String: Any]?) -> [String: Any]? { - guard let source = source else { - return nil - } - - return source.reduce(into: [String: Any]()) { result, item in - switch item.value { - case let x as Bool: - result[item.key] = x.description - default: - result[item.key] = item.value - } - } - } - - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} static func mapValueToPathItem(_ source: Any) -> Any { - if let collection = source as? [Any?] { - return collection.filter { $0 != nil }.map { "\($0!)" }.joined(separator: ",") - } - return source - } - - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} static func mapValuesToQueryItems(_ source: [String: Any?]) -> [URLQueryItem]? { - let destination = source.filter { $0.value != nil }.reduce(into: [URLQueryItem]()) { result, item in - if let collection = item.value as? [Any?] { - collection.filter { $0 != nil }.map { "\($0!)" }.forEach { value in - result.append(URLQueryItem(name: item.key, value: value)) - } - } else if let value = item.value { - result.append(URLQueryItem(name: item.key, value: "\(value)")) - } - } - - if destination.isEmpty { - return nil - } - return destination - } -} diff --git a/modules/openapi-generator/src/main/resources/swift-alt/APIs.mustache b/modules/openapi-generator/src/main/resources/swift-alt/APIs.mustache deleted file mode 100644 index 88a2b21b6dc7..000000000000 --- a/modules/openapi-generator/src/main/resources/swift-alt/APIs.mustache +++ /dev/null @@ -1,68 +0,0 @@ -// APIs.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech -// - -import Foundation - -{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class {{projectName}}API { - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} static var basePath = "{{{basePath}}}" - {{#useVapor}} - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} static var customHeaders: HTTPHeaders = [:] - {{/useVapor}} - {{^useVapor}} - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} static var customHeaders: [String: String] = [:] - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} static var credential: URLCredential?{{#useAlamofire}} - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} static var requestBuilderFactory: RequestBuilderFactory = AlamofireRequestBuilderFactory(){{/useAlamofire}}{{#useURLSession}} - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} static var requestBuilderFactory: RequestBuilderFactory = URLSessionRequestBuilderFactory(){{/useURLSession}} - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} static var apiResponseQueue: DispatchQueue = .main - {{/useVapor}} -}{{^useVapor}} - -{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class RequestBuilder { - var credential: URLCredential? - var headers: [String: String] - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} let parameters: [String: Any]? - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} let method: String - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} let URLString: String - - /// Optional block to obtain a reference to the request's progress instance when available.{{#useURLSession}} - /// With the URLSession http client the request's progress only works on iOS 11.0, macOS 10.13, macCatalyst 13.0, tvOS 11.0, watchOS 4.0. - /// If you need to get the request's progress in older OS versions, please use Alamofire http client.{{/useURLSession}} - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var onProgressReady: ((Progress) -> Void)? - - required {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} init(method: String, URLString: String, parameters: [String: Any]?, headers: [String: String] = [:]) { - self.method = method - self.URLString = URLString - self.parameters = parameters - self.headers = headers - - addHeaders({{projectName}}API.customHeaders) - } - - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} func addHeaders(_ aHeaders: [String: String]) { - for (header, value) in aHeaders { - headers[header] = value - } - } - - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} func execute(_ apiResponseQueue: DispatchQueue = {{projectName}}API.apiResponseQueue, _ completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { } - - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} func addHeader(name: String, value: String) -> Self { - if !value.isEmpty { - headers[name] = value - } - return self - } - - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} func addCredential() -> Self { - credential = {{projectName}}API.credential - return self - } -} - -{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} protocol RequestBuilderFactory { - func getNonDecodableBuilder() -> RequestBuilder.Type - func getBuilder() -> RequestBuilder.Type -}{{/useVapor}} diff --git a/modules/openapi-generator/src/main/resources/swift-alt/CodableHelper.mustache b/modules/openapi-generator/src/main/resources/swift-alt/CodableHelper.mustache deleted file mode 100644 index 554418a5ee6d..000000000000 --- a/modules/openapi-generator/src/main/resources/swift-alt/CodableHelper.mustache +++ /dev/null @@ -1,49 +0,0 @@ -// -// CodableHelper.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech -// - -import Foundation - -{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class CodableHelper { - private static var customDateFormatter: DateFormatter? - private static var defaultDateFormatter: DateFormatter = OpenISO8601DateFormatter() - - private static var customJSONDecoder: JSONDecoder? - private static var defaultJSONDecoder: JSONDecoder = { - let decoder = JSONDecoder() - decoder.dateDecodingStrategy = .formatted(CodableHelper.dateFormatter) - return decoder - }() - - private static var customJSONEncoder: JSONEncoder? - private static var defaultJSONEncoder: JSONEncoder = { - let encoder = JSONEncoder() - encoder.dateEncodingStrategy = .formatted(CodableHelper.dateFormatter) - encoder.outputFormatting = .prettyPrinted - return encoder - }() - - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} static var dateFormatter: DateFormatter { - get { return customDateFormatter ?? defaultDateFormatter } - set { customDateFormatter = newValue } - } - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} static var jsonDecoder: JSONDecoder { - get { return customJSONDecoder ?? defaultJSONDecoder } - set { customJSONDecoder = newValue } - } - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} static var jsonEncoder: JSONEncoder { - get { return customJSONEncoder ?? defaultJSONEncoder } - set { customJSONEncoder = newValue } - } - - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class func decode(_ type: T.Type, from data: Data) -> Swift.Result where T: Decodable { - return Swift.Result { try jsonDecoder.decode(type, from: data) } - } - - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class func encode(_ value: T) -> Swift.Result where T: Encodable { - return Swift.Result { try jsonEncoder.encode(value) } - } -} diff --git a/modules/openapi-generator/src/main/resources/swift-alt/Configuration.mustache b/modules/openapi-generator/src/main/resources/swift-alt/Configuration.mustache deleted file mode 100644 index d563d11b4acd..000000000000 --- a/modules/openapi-generator/src/main/resources/swift-alt/Configuration.mustache +++ /dev/null @@ -1,28 +0,0 @@ -// Configuration.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech -// - -import Foundation{{#useVapor}} -import Vapor{{/useVapor}} - -{{#swiftUseApiNamespace}} -@available(*, deprecated, renamed: "{{projectName}}API.Configuration") -{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} typealias Configuration = {{projectName}}API.Configuration - -extension {{projectName}}API { -{{/swiftUseApiNamespace}} -{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class Configuration { - {{#useVapor}}{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} static var apiClient: Vapor.Client? = nil - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} static var apiWrapper: (inout Vapor.ClientRequest) throws -> () = { _ in } - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} static var contentConfiguration = ContentConfiguration.default(){{/useVapor}}{{^useVapor}} - // This value is used to configure the date formatter that is used to serialize dates into JSON format. - // You must set it prior to encoding any dates, and it will only be read once. - @available(*, unavailable, message: "To set a different date format, use CodableHelper.dateFormatter instead.") - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} static var dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"{{/useVapor}} -} -{{#swiftUseApiNamespace}} -} - -{{/swiftUseApiNamespace}} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/swift-alt/Extensions.mustache b/modules/openapi-generator/src/main/resources/swift-alt/Extensions.mustache deleted file mode 100644 index 7f5d8b582f7e..000000000000 --- a/modules/openapi-generator/src/main/resources/swift-alt/Extensions.mustache +++ /dev/null @@ -1,238 +0,0 @@ -// Extensions.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech -// - -import Foundation -#if canImport(AnyCodable) -import AnyCodable -#endif{{#usePromiseKit}} -import PromiseKit{{/usePromiseKit}}{{#useVapor}} -import Vapor{{/useVapor}}{{^useVapor}} - -extension Bool: JSONEncodable { - func encodeToJSON() -> Any { return self as Any } -} - -extension Float: JSONEncodable { - func encodeToJSON() -> Any { return self as Any } -} - -extension Int: JSONEncodable { - func encodeToJSON() -> Any { return self as Any } -} - -extension Int32: JSONEncodable { - func encodeToJSON() -> Any { return NSNumber(value: self as Int32) } -} - -extension Int64: JSONEncodable { - func encodeToJSON() -> Any { return NSNumber(value: self as Int64) } -} - -extension Double: JSONEncodable { - func encodeToJSON() -> Any { return self as Any } -} - -extension String: JSONEncodable { - func encodeToJSON() -> Any { return self as Any } -} - -extension RawRepresentable where RawValue: JSONEncodable { - func encodeToJSON() -> Any { return self.rawValue as Any } -} - -private func encodeIfPossible(_ object: T) -> Any { - if let encodableObject = object as? JSONEncodable { - return encodableObject.encodeToJSON() - } else { - return object as Any - } -} - -extension Array: JSONEncodable { - func encodeToJSON() -> Any { - return self.map(encodeIfPossible) - } -} - -extension Set: JSONEncodable { - func encodeToJSON() -> Any { - return Array(self).encodeToJSON() - } -} - -extension Dictionary: JSONEncodable { - func encodeToJSON() -> Any { - var dictionary = [AnyHashable: Any]() - for (key, value) in self { - dictionary[key] = encodeIfPossible(value) - } - return dictionary as Any - } -} - -extension Data: JSONEncodable { - func encodeToJSON() -> Any { - return self.base64EncodedString(options: Data.Base64EncodingOptions()) - } -} - -extension Date: JSONEncodable { - func encodeToJSON() -> Any { - return CodableHelper.dateFormatter.string(from: self) as Any - } -} - -extension URL: JSONEncodable { - func encodeToJSON() -> Any { - return self - } -} - -extension UUID: JSONEncodable { - func encodeToJSON() -> Any { - return self.uuidString - } -}{{/useVapor}}{{#generateModelAdditionalProperties}} - -extension String: CodingKey { - - public var stringValue: String { - return self - } - - public init?(stringValue: String) { - self.init(stringLiteral: stringValue) - } - - public var intValue: Int? { - return nil - } - - public init?(intValue: Int) { - return nil - } - -} - -extension KeyedEncodingContainerProtocol { - - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} mutating func encodeArray(_ values: [T], forKey key: Self.Key) throws where T: Encodable { - var arrayContainer = nestedUnkeyedContainer(forKey: key) - try arrayContainer.encode(contentsOf: values) - } - - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} mutating func encodeArrayIfPresent(_ values: [T]?, forKey key: Self.Key) throws where T: Encodable { - if let values = values { - try encodeArray(values, forKey: key) - } - } - - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} mutating func encodeMap(_ pairs: [Self.Key: T]) throws where T: Encodable { - for (key, value) in pairs { - try encode(value, forKey: key) - } - } - - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} mutating func encodeMapIfPresent(_ pairs: [Self.Key: T]?) throws where T: Encodable { - if let pairs = pairs { - try encodeMap(pairs) - } - } - -} - -extension KeyedDecodingContainerProtocol { - - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} func decodeArray(_ type: T.Type, forKey key: Self.Key) throws -> [T] where T: Decodable { - var tmpArray = [T]() - - var nestedContainer = try nestedUnkeyedContainer(forKey: key) - while !nestedContainer.isAtEnd { - let arrayValue = try nestedContainer.decode(T.self) - tmpArray.append(arrayValue) - } - - return tmpArray - } - - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} func decodeArrayIfPresent(_ type: T.Type, forKey key: Self.Key) throws -> [T]? where T: Decodable { - var tmpArray: [T]? - - if contains(key) { - tmpArray = try decodeArray(T.self, forKey: key) - } - - return tmpArray - } - - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} func decodeMap(_ type: T.Type, excludedKeys: Set) throws -> [Self.Key: T] where T: Decodable { - var map: [Self.Key: T] = [:] - - for key in allKeys { - if !excludedKeys.contains(key) { - let value = try decode(T.self, forKey: key) - map[key] = value - } - } - - return map - } - -}{{/generateModelAdditionalProperties}}{{^useVapor}} - -extension HTTPURLResponse { - var isStatusCodeSuccessful: Bool { - return Array(200 ..< 300).contains(statusCode) - } -}{{/useVapor}}{{#usePromiseKit}} - -extension RequestBuilder { - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} func execute() -> Promise> { - let deferred = Promise>.pending() - self.execute { result in - switch result { - case let .success(response): - deferred.resolver.fulfill(response) - case let .failure(error): - deferred.resolver.reject(error) - } - } - return deferred.promise - } -}{{/usePromiseKit}}{{#useVapor}} - -extension UUID: Content { } - -extension URL: Content { } - -extension Bool: Content { } - -extension Set: ResponseEncodable where Element: Content { - public func encodeResponse(for request: Vapor.Request) -> EventLoopFuture { - let response = Vapor.Response() - do { - try response.content.encode(Array(self)) - } catch { - return request.eventLoop.makeFailedFuture(error) - } - return request.eventLoop.makeSucceededFuture(response) - } -} - -extension Set: RequestDecodable where Element: Content { - public static func decodeRequest(_ request: Vapor.Request) -> EventLoopFuture { - do { - let content = try request.content.decode([Element].self) - return request.eventLoop.makeSucceededFuture(Set(content)) - } catch { - return request.eventLoop.makeFailedFuture(error) - } - } -} - -extension Set: Content where Element: Content { } - -extension AnyCodable: Content {}{{/useVapor}} diff --git a/modules/openapi-generator/src/main/resources/swift-alt/JSONDataEncoding.mustache b/modules/openapi-generator/src/main/resources/swift-alt/JSONDataEncoding.mustache deleted file mode 100644 index e227058129b5..000000000000 --- a/modules/openapi-generator/src/main/resources/swift-alt/JSONDataEncoding.mustache +++ /dev/null @@ -1,53 +0,0 @@ -// -// JSONDataEncoding.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech -// - -import Foundation - -{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} struct JSONDataEncoding { - - // MARK: Properties - - private static let jsonDataKey = "jsonData" - - // MARK: Encoding - - /// Creates a URL request by encoding parameters and applying them onto an existing request. - /// - /// - parameter urlRequest: The request to have parameters applied. - /// - parameter parameters: The parameters to apply. This should have a single key/value - /// pair with "jsonData" as the key and a Data object as the value. - /// - /// - throws: An `Error` if the encoding process encounters an error. - /// - /// - returns: The encoded request. - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} func encode(_ urlRequest: URLRequest, with parameters: [String: Any]?) -> URLRequest { - var urlRequest = urlRequest - - guard let jsonData = parameters?[JSONDataEncoding.jsonDataKey] as? Data, !jsonData.isEmpty else { - return urlRequest - } - - if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil { - urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type") - } - - urlRequest.httpBody = jsonData - - return urlRequest - } - - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} static func encodingParameters(jsonData: Data?) -> [String: Any]? { - var returnedParams: [String: Any]? - if let jsonData = jsonData, !jsonData.isEmpty { - var params: [String: Any] = [:] - params[jsonDataKey] = jsonData - returnedParams = params - } - return returnedParams - } - -} diff --git a/modules/openapi-generator/src/main/resources/swift-alt/JSONEncodingHelper.mustache b/modules/openapi-generator/src/main/resources/swift-alt/JSONEncodingHelper.mustache deleted file mode 100644 index 0eae73e1b39d..000000000000 --- a/modules/openapi-generator/src/main/resources/swift-alt/JSONEncodingHelper.mustache +++ /dev/null @@ -1,45 +0,0 @@ -// -// JSONEncodingHelper.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech -// - -import Foundation - -{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class JSONEncodingHelper { - - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class func encodingParameters(forEncodableObject encodableObj: T?) -> [String: Any]? { - var params: [String: Any]? - - // Encode the Encodable object - if let encodableObj = encodableObj { - let encodeResult = CodableHelper.encode(encodableObj) - do { - let data = try encodeResult.get() - params = JSONDataEncoding.encodingParameters(jsonData: data) - } catch { - print(error.localizedDescription) - } - } - - return params - } - - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class func encodingParameters(forEncodableObject encodableObj: Any?) -> [String: Any]? { - var params: [String: Any]? - - if let encodableObj = encodableObj { - do { - let data = try JSONSerialization.data(withJSONObject: encodableObj, options: .prettyPrinted) - params = JSONDataEncoding.encodingParameters(jsonData: data) - } catch { - print(error.localizedDescription) - return nil - } - } - - return params - } - -} diff --git a/modules/openapi-generator/src/main/resources/swift-alt/Models.mustache b/modules/openapi-generator/src/main/resources/swift-alt/Models.mustache deleted file mode 100644 index 74ce973b2872..000000000000 --- a/modules/openapi-generator/src/main/resources/swift-alt/Models.mustache +++ /dev/null @@ -1,54 +0,0 @@ -// Models.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech -// - -import Foundation - -protocol JSONEncodable { - func encodeToJSON() -> Any -} - -{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} enum ErrorResponse: Error { - case error(Int, Data?, URLResponse?, Error) -} - -{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} enum DownloadException: Error { - case responseDataMissing - case responseFailed - case requestMissing - case requestMissingPath - case requestMissingURL -} - -{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} enum DecodableRequestBuilderError: Error { - case emptyDataResponse - case nilHTTPResponse - case unsuccessfulHTTPStatusCode - case jsonDecoding(DecodingError) - case generalError(Error) -} - -{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class Response { - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} let statusCode: Int - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} let header: [String: String] - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} let body: T? - - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} init(statusCode: Int, header: [String: String], body: T?) { - self.statusCode = statusCode - self.header = header - self.body = body - } - - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} convenience init(response: HTTPURLResponse, body: T?) { - let rawHeader = response.allHeaderFields - var header = [String: String]() - for (key, value) in rawHeader { - if let key = key.base as? String, let value = value as? String { - header[key] = value - } - } - self.init(statusCode: response.statusCode, header: header, body: body) - } -} diff --git a/modules/openapi-generator/src/main/resources/swift-alt/Old.swift b/modules/openapi-generator/src/main/resources/swift-alt/Old.swift deleted file mode 100644 index 6bbe1b0aa9f9..000000000000 --- a/modules/openapi-generator/src/main/resources/swift-alt/Old.swift +++ /dev/null @@ -1,1361 +0,0 @@ -// -// PetAPI.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech -// - -import Foundation -import Combine -// import Runtime - - -open class PetAPI { - private let transport: Transport - - public init(_ transport: Transport) { - self.transport = transport - } - /** - Add a new pet to the store - - POST /pet - - OAuth: - - type: oauth2 - - name: petstore_auth - - parameter pet: (body) Pet object that needs to be added to the store - - returns: Future - */ - open func addPet(pet: Pet) -> AnyPublisher, Never> { - var request = URLRequest(url: transport.baseURL) - return transport.send(request: request, authType: .none) - .eraseToAnyPublisher() - - } - /** - Deletes a pet - - DELETE /pet/{petId} - - OAuth: - - type: oauth2 - - name: petstore_auth - - parameter petId: (path) Pet id to delete - - parameter apiKey: (header) (optional) - - returns: Future - */ - open func deletePet(petId: Int64, apiKey: String? = nil) -> Future { - } - /** - Finds Pets by status - - GET /pet/findByStatus - - Multiple status values can be provided with comma separated strings - - OAuth: - - type: oauth2 - - name: petstore_auth - - parameter status: () Status values that need to be considered for filter - - returns: Future<[Pet], Never> - */ - open func findPetsByStatus(status: [String]) -> Future<[Pet], Never> { - } - /** - Finds Pets by tags - - GET /pet/findByTags - - Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. - - OAuth: - - type: oauth2 - - name: petstore_auth - - parameter tags: () Tags to filter by - - returns: Future<[Pet], Never> - */ - open func findPetsByTags(tags: [String]) -> Future<[Pet], Never> { - } - /** - Find pet by ID - - GET /pet/{petId} - - Returns a single pet - - API Key: - - type: apiKey api_key - - name: api_key - - parameter petId: (path) ID of pet to return - - returns: Future - */ - open func getPetById(petId: Int64) -> Future { - } - /** - Update an existing pet - - PUT /pet - - OAuth: - - type: oauth2 - - name: petstore_auth - - parameter pet: (body) Pet object that needs to be added to the store - - returns: Future - */ - open func updatePet(pet: Pet) -> Future { - } - /** - Updates a pet in the store with form data - - POST /pet/{petId} - - OAuth: - - type: oauth2 - - name: petstore_auth - - parameter petId: (path) ID of pet that needs to be updated - - parameter name: (form) Updated name of the pet (optional) - - parameter status: (form) Updated status of the pet (optional) - - returns: Future - */ - open func updatePetWithForm(petId: Int64, name: String? = nil, status: String? = nil) -> Future { - } - /** - uploads an image - - POST /pet/{petId}/uploadImage - - OAuth: - - type: oauth2 - - name: petstore_auth - - parameter petId: (path) ID of pet to update - - parameter additionalMetadata: (form) Additional data to pass to server (optional) - - parameter file: (form) file to upload (optional) - - returns: Future - */ - open func uploadFile(petId: Int64, additionalMetadata: String? = nil, file: Data? = nil) -> Future { - } -} -//// - -/** -- - - API Key: - - type: apiKey api_key - - name: api_key - - OAuth: - - type: oauth2 - - name: petstore_auth -- returns: RequestBuilder - */ -open class func WithRequestBuilder() -> RequestBuilder { -let localVariablePath = "" - let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath - let localVariableParameters: [String: Any]? = nil - - let localVariableUrlComponents = URLComponents(string: localVariableURLString) - - let localVariableNillableHeaders: [String: Any?] = [ - : - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() - - return localVariableRequestBuilder.init(method: "", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) - } - -import Foundation -#if canImport(AnyCodable) -import AnyCodable -#endif - -open class PetAPI { - - /** - Add a new pet to the store - - - parameter pet: (body) Pet object that needs to be added to the store - - parameter apiResponseQueue: The queue on which api response is dispatched. - - parameter completion: completion handler to receive the data and the error objects - */ - open class func addPet(pet: Pet, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Pet?, _ error: Error?) -> Void)) { - addPetWithRequestBuilder(pet: pet).execute(apiResponseQueue) { result in - switch result { - case let .success(response): - completion(response.body, nil) - case let .failure(error): - completion(nil, error) - } - } - } - - /** - Add a new pet to the store - - POST /pet - - OAuth: - - type: oauth2 - - name: petstore_auth - - parameter pet: (body) Pet object that needs to be added to the store - - returns: RequestBuilder - */ - open class func addPetWithRequestBuilder(pet: Pet) -> RequestBuilder { - let localVariablePath = "/pet" - let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath - let localVariableParameters = JSONEncodingHelper.encodingParameters(forEncodableObject: pet) - - let localVariableUrlComponents = URLComponents(string: localVariableURLString) - - let localVariableNillableHeaders: [String: Any?] = [ - : - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getBuilder() - - return localVariableRequestBuilder.init(method: "POST", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) - } - - /** - Deletes a pet - - - parameter petId: (path) Pet id to delete - - parameter apiKey: (header) (optional) - - parameter apiResponseQueue: The queue on which api response is dispatched. - - parameter completion: completion handler to receive the data and the error objects - */ - open class func deletePet(petId: Int64, apiKey: String? = nil, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Void?, _ error: Error?) -> Void)) { - deletePetWithRequestBuilder(petId: petId, apiKey: apiKey).execute(apiResponseQueue) { result in - switch result { - case .success: - completion((), nil) - case let .failure(error): - completion(nil, error) - } - } - } - - /** - Deletes a pet - - DELETE /pet/{petId} - - OAuth: - - type: oauth2 - - name: petstore_auth - - parameter petId: (path) Pet id to delete - - parameter apiKey: (header) (optional) - - returns: RequestBuilder - */ - open class func deletePetWithRequestBuilder(petId: Int64, apiKey: String? = nil) -> RequestBuilder { - var localVariablePath = "/pet/{petId}" - let petIdPreEscape = "\(APIHelper.mapValueToPathItem(petId))" - let petIdPostEscape = petIdPreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" - localVariablePath = localVariablePath.replacingOccurrences(of: "{petId}", with: petIdPostEscape, options: .literal, range: nil) - let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath - let localVariableParameters: [String: Any]? = nil - - let localVariableUrlComponents = URLComponents(string: localVariableURLString) - - let localVariableNillableHeaders: [String: Any?] = [ - "api_key": apiKey?.encodeToJSON(), - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() - - return localVariableRequestBuilder.init(method: "DELETE", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) - } - - /** - * enum for parameter status - */ - public enum Status_findPetsByStatus: String, CaseIterable { - case available = "available" - case pending = "pending" - case sold = "sold" - } - - /** - Finds Pets by status - - - parameter status: (query) Status values that need to be considered for filter - - parameter apiResponseQueue: The queue on which api response is dispatched. - - parameter completion: completion handler to receive the data and the error objects - */ - open class func findPetsByStatus(status: [String], apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: [Pet]?, _ error: Error?) -> Void)) { - findPetsByStatusWithRequestBuilder(status: status).execute(apiResponseQueue) { result in - switch result { - case let .success(response): - completion(response.body, nil) - case let .failure(error): - completion(nil, error) - } - } - } - - /** - Finds Pets by status - - GET /pet/findByStatus - - Multiple status values can be provided with comma separated strings - - OAuth: - - type: oauth2 - - name: petstore_auth - - parameter status: (query) Status values that need to be considered for filter - - returns: RequestBuilder<[Pet]> - */ - open class func findPetsByStatusWithRequestBuilder(status: [String]) -> RequestBuilder<[Pet]> { - let localVariablePath = "/pet/findByStatus" - let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath - let localVariableParameters: [String: Any]? = nil - - var localVariableUrlComponents = URLComponents(string: localVariableURLString) - localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems([ - "status": status.encodeToJSON(), - ]) - - let localVariableNillableHeaders: [String: Any?] = [ - : - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder<[Pet]>.Type = OpenAPIClientAPI.requestBuilderFactory.getBuilder() - - return localVariableRequestBuilder.init(method: "GET", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) - } - - /** - Finds Pets by tags - - - parameter tags: (query) Tags to filter by - - parameter apiResponseQueue: The queue on which api response is dispatched. - - parameter completion: completion handler to receive the data and the error objects - */ - @available(*, deprecated, message: "This operation is deprecated.") - open class func findPetsByTags(tags: [String], apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: [Pet]?, _ error: Error?) -> Void)) { - findPetsByTagsWithRequestBuilder(tags: tags).execute(apiResponseQueue) { result in - switch result { - case let .success(response): - completion(response.body, nil) - case let .failure(error): - completion(nil, error) - } - } - } - - /** - Finds Pets by tags - - GET /pet/findByTags - - Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. - - OAuth: - - type: oauth2 - - name: petstore_auth - - parameter tags: (query) Tags to filter by - - returns: RequestBuilder<[Pet]> - */ - @available(*, deprecated, message: "This operation is deprecated.") - open class func findPetsByTagsWithRequestBuilder(tags: [String]) -> RequestBuilder<[Pet]> { - let localVariablePath = "/pet/findByTags" - let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath - let localVariableParameters: [String: Any]? = nil - - var localVariableUrlComponents = URLComponents(string: localVariableURLString) - localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems([ - "tags": tags.encodeToJSON(), - ]) - - let localVariableNillableHeaders: [String: Any?] = [ - : - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder<[Pet]>.Type = OpenAPIClientAPI.requestBuilderFactory.getBuilder() - - return localVariableRequestBuilder.init(method: "GET", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) - } - - /** - Find pet by ID - - - parameter petId: (path) ID of pet to return - - parameter apiResponseQueue: The queue on which api response is dispatched. - - parameter completion: completion handler to receive the data and the error objects - */ - open class func getPetById(petId: Int64, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Pet?, _ error: Error?) -> Void)) { - getPetByIdWithRequestBuilder(petId: petId).execute(apiResponseQueue) { result in - switch result { - case let .success(response): - completion(response.body, nil) - case let .failure(error): - completion(nil, error) - } - } - } - - /** - Find pet by ID - - GET /pet/{petId} - - Returns a single pet - - API Key: - - type: apiKey api_key - - name: api_key - - parameter petId: (path) ID of pet to return - - returns: RequestBuilder - */ - open class func getPetByIdWithRequestBuilder(petId: Int64) -> RequestBuilder { - var localVariablePath = "/pet/{petId}" - let petIdPreEscape = "\(APIHelper.mapValueToPathItem(petId))" - let petIdPostEscape = petIdPreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" - localVariablePath = localVariablePath.replacingOccurrences(of: "{petId}", with: petIdPostEscape, options: .literal, range: nil) - let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath - let localVariableParameters: [String: Any]? = nil - - let localVariableUrlComponents = URLComponents(string: localVariableURLString) - - let localVariableNillableHeaders: [String: Any?] = [ - : - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getBuilder() - - return localVariableRequestBuilder.init(method: "GET", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) - } - - /** - Update an existing pet - - - parameter pet: (body) Pet object that needs to be added to the store - - parameter apiResponseQueue: The queue on which api response is dispatched. - - parameter completion: completion handler to receive the data and the error objects - */ - open class func updatePet(pet: Pet, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Pet?, _ error: Error?) -> Void)) { - updatePetWithRequestBuilder(pet: pet).execute(apiResponseQueue) { result in - switch result { - case let .success(response): - completion(response.body, nil) - case let .failure(error): - completion(nil, error) - } - } - } - - /** - Update an existing pet - - PUT /pet - - OAuth: - - type: oauth2 - - name: petstore_auth - - parameter pet: (body) Pet object that needs to be added to the store - - returns: RequestBuilder - */ - open class func updatePetWithRequestBuilder(pet: Pet) -> RequestBuilder { - let localVariablePath = "/pet" - let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath - let localVariableParameters = JSONEncodingHelper.encodingParameters(forEncodableObject: pet) - - let localVariableUrlComponents = URLComponents(string: localVariableURLString) - - let localVariableNillableHeaders: [String: Any?] = [ - : - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getBuilder() - - return localVariableRequestBuilder.init(method: "PUT", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) - } - - /** - Updates a pet in the store with form data - - - parameter petId: (path) ID of pet that needs to be updated - - parameter name: (form) Updated name of the pet (optional) - - parameter status: (form) Updated status of the pet (optional) - - parameter apiResponseQueue: The queue on which api response is dispatched. - - parameter completion: completion handler to receive the data and the error objects - */ - open class func updatePetWithForm(petId: Int64, name: String? = nil, status: String? = nil, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Void?, _ error: Error?) -> Void)) { - updatePetWithFormWithRequestBuilder(petId: petId, name: name, status: status).execute(apiResponseQueue) { result in - switch result { - case .success: - completion((), nil) - case let .failure(error): - completion(nil, error) - } - } - } - - /** - Updates a pet in the store with form data - - POST /pet/{petId} - - OAuth: - - type: oauth2 - - name: petstore_auth - - parameter petId: (path) ID of pet that needs to be updated - - parameter name: (form) Updated name of the pet (optional) - - parameter status: (form) Updated status of the pet (optional) - - returns: RequestBuilder - */ - open class func updatePetWithFormWithRequestBuilder(petId: Int64, name: String? = nil, status: String? = nil) -> RequestBuilder { - var localVariablePath = "/pet/{petId}" - let petIdPreEscape = "\(APIHelper.mapValueToPathItem(petId))" - let petIdPostEscape = petIdPreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" - localVariablePath = localVariablePath.replacingOccurrences(of: "{petId}", with: petIdPostEscape, options: .literal, range: nil) - let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath - let localVariableFormParams: [String: Any?] = [ - "name": name?.encodeToJSON(), - "status": status?.encodeToJSON(), - ] - - let localVariableNonNullParameters = APIHelper.rejectNil(localVariableFormParams) - let localVariableParameters = APIHelper.convertBoolToString(localVariableNonNullParameters) - - let localVariableUrlComponents = URLComponents(string: localVariableURLString) - - let localVariableNillableHeaders: [String: Any?] = [ - "Content-Type": "application/x-www-form-urlencoded", - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() - - return localVariableRequestBuilder.init(method: "POST", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) - } - - /** - uploads an image - - - parameter petId: (path) ID of pet to update - - parameter additionalMetadata: (form) Additional data to pass to server (optional) - - parameter file: (form) file to upload (optional) - - parameter apiResponseQueue: The queue on which api response is dispatched. - - parameter completion: completion handler to receive the data and the error objects - */ - open class func uploadFile(petId: Int64, additionalMetadata: String? = nil, file: Data? = nil, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: ApiResponse?, _ error: Error?) -> Void)) { - uploadFileWithRequestBuilder(petId: petId, additionalMetadata: additionalMetadata, file: file).execute(apiResponseQueue) { result in - switch result { - case let .success(response): - completion(response.body, nil) - case let .failure(error): - completion(nil, error) - } - } - } - - /** - uploads an image - - POST /pet/{petId}/uploadImage - - OAuth: - - type: oauth2 - - name: petstore_auth - - parameter petId: (path) ID of pet to update - - parameter additionalMetadata: (form) Additional data to pass to server (optional) - - parameter file: (form) file to upload (optional) - - returns: RequestBuilder - */ - open class func uploadFileWithRequestBuilder(petId: Int64, additionalMetadata: String? = nil, file: Data? = nil) -> RequestBuilder { - var localVariablePath = "/pet/{petId}/uploadImage" - let petIdPreEscape = "\(APIHelper.mapValueToPathItem(petId))" - let petIdPostEscape = petIdPreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" - localVariablePath = localVariablePath.replacingOccurrences(of: "{petId}", with: petIdPostEscape, options: .literal, range: nil) - let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath - let localVariableFormParams: [String: Any?] = [ - "additionalMetadata": additionalMetadata?.encodeToJSON(), - "file": file?.encodeToJSON(), - ] - - let localVariableNonNullParameters = APIHelper.rejectNil(localVariableFormParams) - let localVariableParameters = APIHelper.convertBoolToString(localVariableNonNullParameters) - - let localVariableUrlComponents = URLComponents(string: localVariableURLString) - - let localVariableNillableHeaders: [String: Any?] = [ - "Content-Type": "multipart/form-data", - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getBuilder() - - return localVariableRequestBuilder.init(method: "POST", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) - } -} - - -// -// UserAPI.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech -// - -import Foundation -import Combine -// import Runtime - - -open class UserAPI { - private let transport: Transport - - public init(_ transport: Transport) { - self.transport = transport - } - /** - Create user - - POST /user - - This can only be done by the logged in user. - - API Key: - - type: apiKey api_key - - name: api_key - - parameter user: (body) Created user object - - returns: Future - */ - open func createUser(user: User) -> Future { - } - /** - Creates list of users with given input array - - POST /user/createWithArray - - API Key: - - type: apiKey api_key - - name: api_key - - parameter user: (body) List of user object - - returns: Future - */ - open func createUsersWithArrayInput(user: [User]) -> Future { - } - /** - Creates list of users with given input array - - POST /user/createWithList - - API Key: - - type: apiKey api_key - - name: api_key - - parameter user: (body) List of user object - - returns: Future - */ - open func createUsersWithListInput(user: [User]) -> Future { - } - /** - Delete user - - DELETE /user/{username} - - This can only be done by the logged in user. - - API Key: - - type: apiKey api_key - - name: api_key - - parameter username: (path) The name that needs to be deleted - - returns: Future - */ - open func deleteUser(username: String) -> Future { - } - /** - Get user by user name - - GET /user/{username} - - parameter username: (path) The name that needs to be fetched. Use user1 for testing. - - returns: Future - */ - open func getUserByName(username: String) -> Future { - } - /** - Logs user into the system - - GET /user/login - - responseHeaders: [Set-Cookie(String), X-Rate-Limit(Int), X-Expires-After(Date)] - - parameter username: () The user name for login - - parameter password: () The password for login in clear text - - returns: Future - */ - open func loginUser(username: String, password: String) -> Future { - } - /** - Logs out current logged in user session - - GET /user/logout - - API Key: - - type: apiKey api_key - - name: api_key - - returns: Future - */ - open func logoutUser() -> Future { - } - /** - Updated user - - PUT /user/{username} - - This can only be done by the logged in user. - - API Key: - - type: apiKey api_key - - name: api_key - - parameter username: (path) name that need to be deleted - - parameter user: (body) Updated user object - - returns: Future - */ - open func updateUser(username: String, user: User) -> Future { - } -} -//// - -/** -- - - API Key: - - type: apiKey api_key - - name: api_key - - OAuth: - - type: oauth2 - - name: petstore_auth -- returns: RequestBuilder - */ -open class func WithRequestBuilder() -> RequestBuilder { -let localVariablePath = "" - let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath - let localVariableParameters: [String: Any]? = nil - - let localVariableUrlComponents = URLComponents(string: localVariableURLString) - - let localVariableNillableHeaders: [String: Any?] = [ - : - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() - - return localVariableRequestBuilder.init(method: "", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) - } - -import Foundation -#if canImport(AnyCodable) -import AnyCodable -#endif - -open class UserAPI { - - /** - Create user - - - parameter user: (body) Created user object - - parameter apiResponseQueue: The queue on which api response is dispatched. - - parameter completion: completion handler to receive the data and the error objects - */ - open class func createUser(user: User, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Void?, _ error: Error?) -> Void)) { - createUserWithRequestBuilder(user: user).execute(apiResponseQueue) { result in - switch result { - case .success: - completion((), nil) - case let .failure(error): - completion(nil, error) - } - } - } - - /** - Create user - - POST /user - - This can only be done by the logged in user. - - API Key: - - type: apiKey api_key - - name: api_key - - parameter user: (body) Created user object - - returns: RequestBuilder - */ - open class func createUserWithRequestBuilder(user: User) -> RequestBuilder { - let localVariablePath = "/user" - let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath - let localVariableParameters = JSONEncodingHelper.encodingParameters(forEncodableObject: user) - - let localVariableUrlComponents = URLComponents(string: localVariableURLString) - - let localVariableNillableHeaders: [String: Any?] = [ - : - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() - - return localVariableRequestBuilder.init(method: "POST", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) - } - - /** - Creates list of users with given input array - - - parameter user: (body) List of user object - - parameter apiResponseQueue: The queue on which api response is dispatched. - - parameter completion: completion handler to receive the data and the error objects - */ - open class func createUsersWithArrayInput(user: [User], apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Void?, _ error: Error?) -> Void)) { - createUsersWithArrayInputWithRequestBuilder(user: user).execute(apiResponseQueue) { result in - switch result { - case .success: - completion((), nil) - case let .failure(error): - completion(nil, error) - } - } - } - - /** - Creates list of users with given input array - - POST /user/createWithArray - - API Key: - - type: apiKey api_key - - name: api_key - - parameter user: (body) List of user object - - returns: RequestBuilder - */ - open class func createUsersWithArrayInputWithRequestBuilder(user: [User]) -> RequestBuilder { - let localVariablePath = "/user/createWithArray" - let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath - let localVariableParameters = JSONEncodingHelper.encodingParameters(forEncodableObject: user) - - let localVariableUrlComponents = URLComponents(string: localVariableURLString) - - let localVariableNillableHeaders: [String: Any?] = [ - : - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() - - return localVariableRequestBuilder.init(method: "POST", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) - } - - /** - Creates list of users with given input array - - - parameter user: (body) List of user object - - parameter apiResponseQueue: The queue on which api response is dispatched. - - parameter completion: completion handler to receive the data and the error objects - */ - open class func createUsersWithListInput(user: [User], apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Void?, _ error: Error?) -> Void)) { - createUsersWithListInputWithRequestBuilder(user: user).execute(apiResponseQueue) { result in - switch result { - case .success: - completion((), nil) - case let .failure(error): - completion(nil, error) - } - } - } - - /** - Creates list of users with given input array - - POST /user/createWithList - - API Key: - - type: apiKey api_key - - name: api_key - - parameter user: (body) List of user object - - returns: RequestBuilder - */ - open class func createUsersWithListInputWithRequestBuilder(user: [User]) -> RequestBuilder { - let localVariablePath = "/user/createWithList" - let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath - let localVariableParameters = JSONEncodingHelper.encodingParameters(forEncodableObject: user) - - let localVariableUrlComponents = URLComponents(string: localVariableURLString) - - let localVariableNillableHeaders: [String: Any?] = [ - : - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() - - return localVariableRequestBuilder.init(method: "POST", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) - } - - /** - Delete user - - - parameter username: (path) The name that needs to be deleted - - parameter apiResponseQueue: The queue on which api response is dispatched. - - parameter completion: completion handler to receive the data and the error objects - */ - open class func deleteUser(username: String, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Void?, _ error: Error?) -> Void)) { - deleteUserWithRequestBuilder(username: username).execute(apiResponseQueue) { result in - switch result { - case .success: - completion((), nil) - case let .failure(error): - completion(nil, error) - } - } - } - - /** - Delete user - - DELETE /user/{username} - - This can only be done by the logged in user. - - API Key: - - type: apiKey api_key - - name: api_key - - parameter username: (path) The name that needs to be deleted - - returns: RequestBuilder - */ - open class func deleteUserWithRequestBuilder(username: String) -> RequestBuilder { - var localVariablePath = "/user/{username}" - let usernamePreEscape = "\(APIHelper.mapValueToPathItem(username))" - let usernamePostEscape = usernamePreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" - localVariablePath = localVariablePath.replacingOccurrences(of: "{username}", with: usernamePostEscape, options: .literal, range: nil) - let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath - let localVariableParameters: [String: Any]? = nil - - let localVariableUrlComponents = URLComponents(string: localVariableURLString) - - let localVariableNillableHeaders: [String: Any?] = [ - : - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() - - return localVariableRequestBuilder.init(method: "DELETE", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) - } - - /** - Get user by user name - - - parameter username: (path) The name that needs to be fetched. Use user1 for testing. - - parameter apiResponseQueue: The queue on which api response is dispatched. - - parameter completion: completion handler to receive the data and the error objects - */ - open class func getUserByName(username: String, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: User?, _ error: Error?) -> Void)) { - getUserByNameWithRequestBuilder(username: username).execute(apiResponseQueue) { result in - switch result { - case let .success(response): - completion(response.body, nil) - case let .failure(error): - completion(nil, error) - } - } - } - - /** - Get user by user name - - GET /user/{username} - - parameter username: (path) The name that needs to be fetched. Use user1 for testing. - - returns: RequestBuilder - */ - open class func getUserByNameWithRequestBuilder(username: String) -> RequestBuilder { - var localVariablePath = "/user/{username}" - let usernamePreEscape = "\(APIHelper.mapValueToPathItem(username))" - let usernamePostEscape = usernamePreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" - localVariablePath = localVariablePath.replacingOccurrences(of: "{username}", with: usernamePostEscape, options: .literal, range: nil) - let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath - let localVariableParameters: [String: Any]? = nil - - let localVariableUrlComponents = URLComponents(string: localVariableURLString) - - let localVariableNillableHeaders: [String: Any?] = [ - : - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getBuilder() - - return localVariableRequestBuilder.init(method: "GET", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) - } - - /** - Logs user into the system - - - parameter username: (query) The user name for login - - parameter password: (query) The password for login in clear text - - parameter apiResponseQueue: The queue on which api response is dispatched. - - parameter completion: completion handler to receive the data and the error objects - */ - open class func loginUser(username: String, password: String, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: String?, _ error: Error?) -> Void)) { - loginUserWithRequestBuilder(username: username, password: password).execute(apiResponseQueue) { result in - switch result { - case let .success(response): - completion(response.body, nil) - case let .failure(error): - completion(nil, error) - } - } - } - - /** - Logs user into the system - - GET /user/login - - responseHeaders: [Set-Cookie(String), X-Rate-Limit(Int), X-Expires-After(Date)] - - parameter username: (query) The user name for login - - parameter password: (query) The password for login in clear text - - returns: RequestBuilder - */ - open class func loginUserWithRequestBuilder(username: String, password: String) -> RequestBuilder { - let localVariablePath = "/user/login" - let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath - let localVariableParameters: [String: Any]? = nil - - var localVariableUrlComponents = URLComponents(string: localVariableURLString) - localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems([ - "username": username.encodeToJSON(), - "password": password.encodeToJSON(), - ]) - - let localVariableNillableHeaders: [String: Any?] = [ - : - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getBuilder() - - return localVariableRequestBuilder.init(method: "GET", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) - } - - /** - Logs out current logged in user session - - - parameter apiResponseQueue: The queue on which api response is dispatched. - - parameter completion: completion handler to receive the data and the error objects - */ - open class func logoutUser(apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Void?, _ error: Error?) -> Void)) { - logoutUserWithRequestBuilder().execute(apiResponseQueue) { result in - switch result { - case .success: - completion((), nil) - case let .failure(error): - completion(nil, error) - } - } - } - - /** - Logs out current logged in user session - - GET /user/logout - - API Key: - - type: apiKey api_key - - name: api_key - - returns: RequestBuilder - */ - open class func logoutUserWithRequestBuilder() -> RequestBuilder { - let localVariablePath = "/user/logout" - let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath - let localVariableParameters: [String: Any]? = nil - - let localVariableUrlComponents = URLComponents(string: localVariableURLString) - - let localVariableNillableHeaders: [String: Any?] = [ - : - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() - - return localVariableRequestBuilder.init(method: "GET", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) - } - - /** - Updated user - - - parameter username: (path) name that need to be deleted - - parameter user: (body) Updated user object - - parameter apiResponseQueue: The queue on which api response is dispatched. - - parameter completion: completion handler to receive the data and the error objects - */ - open class func updateUser(username: String, user: User, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Void?, _ error: Error?) -> Void)) { - updateUserWithRequestBuilder(username: username, user: user).execute(apiResponseQueue) { result in - switch result { - case .success: - completion((), nil) - case let .failure(error): - completion(nil, error) - } - } - } - - /** - Updated user - - PUT /user/{username} - - This can only be done by the logged in user. - - API Key: - - type: apiKey api_key - - name: api_key - - parameter username: (path) name that need to be deleted - - parameter user: (body) Updated user object - - returns: RequestBuilder - */ - open class func updateUserWithRequestBuilder(username: String, user: User) -> RequestBuilder { - var localVariablePath = "/user/{username}" - let usernamePreEscape = "\(APIHelper.mapValueToPathItem(username))" - let usernamePostEscape = usernamePreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" - localVariablePath = localVariablePath.replacingOccurrences(of: "{username}", with: usernamePostEscape, options: .literal, range: nil) - let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath - let localVariableParameters = JSONEncodingHelper.encodingParameters(forEncodableObject: user) - - let localVariableUrlComponents = URLComponents(string: localVariableURLString) - - let localVariableNillableHeaders: [String: Any?] = [ - : - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() - - return localVariableRequestBuilder.init(method: "PUT", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) - } -} - - -// -// StoreAPI.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech -// - -import Foundation -import Combine -// import Runtime - - -open class StoreAPI { - private let transport: Transport - - public init(_ transport: Transport) { - self.transport = transport - } - /** - Delete purchase order by ID - - DELETE /store/order/{orderId} - - For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors - - parameter orderId: (path) ID of the order that needs to be deleted - - returns: Future - */ - open func deleteOrder(orderId: String) -> Future { - } - /** - Returns pet inventories by status - - GET /store/inventory - - Returns a map of status codes to quantities - - API Key: - - type: apiKey api_key - - name: api_key - - returns: Future<[String: Int], Never> - */ - open func getInventory() -> Future<[String: Int], Never> { - } - /** - Find purchase order by ID - - GET /store/order/{orderId} - - For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions - - parameter orderId: (path) ID of pet that needs to be fetched - - returns: Future - */ - open func getOrderById(orderId: Int64) -> Future { - } - /** - Place an order for a pet - - POST /store/order - - parameter order: (body) order placed for purchasing the pet - - returns: Future - */ - open func placeOrder(order: Order) -> Future { - } -} -//// - -/** -- - - API Key: - - type: apiKey api_key - - name: api_key - - OAuth: - - type: oauth2 - - name: petstore_auth -- returns: RequestBuilder - */ -open class func WithRequestBuilder() -> RequestBuilder { -let localVariablePath = "" - let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath - let localVariableParameters: [String: Any]? = nil - - let localVariableUrlComponents = URLComponents(string: localVariableURLString) - - let localVariableNillableHeaders: [String: Any?] = [ - : - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() - - return localVariableRequestBuilder.init(method: "", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) - } - -import Foundation -#if canImport(AnyCodable) -import AnyCodable -#endif - -open class StoreAPI { - - /** - Delete purchase order by ID - - - parameter orderId: (path) ID of the order that needs to be deleted - - parameter apiResponseQueue: The queue on which api response is dispatched. - - parameter completion: completion handler to receive the data and the error objects - */ - open class func deleteOrder(orderId: String, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Void?, _ error: Error?) -> Void)) { - deleteOrderWithRequestBuilder(orderId: orderId).execute(apiResponseQueue) { result in - switch result { - case .success: - completion((), nil) - case let .failure(error): - completion(nil, error) - } - } - } - - /** - Delete purchase order by ID - - DELETE /store/order/{orderId} - - For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors - - parameter orderId: (path) ID of the order that needs to be deleted - - returns: RequestBuilder - */ - open class func deleteOrderWithRequestBuilder(orderId: String) -> RequestBuilder { - var localVariablePath = "/store/order/{orderId}" - let orderIdPreEscape = "\(APIHelper.mapValueToPathItem(orderId))" - let orderIdPostEscape = orderIdPreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" - localVariablePath = localVariablePath.replacingOccurrences(of: "{orderId}", with: orderIdPostEscape, options: .literal, range: nil) - let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath - let localVariableParameters: [String: Any]? = nil - - let localVariableUrlComponents = URLComponents(string: localVariableURLString) - - let localVariableNillableHeaders: [String: Any?] = [ - : - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getNonDecodableBuilder() - - return localVariableRequestBuilder.init(method: "DELETE", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) - } - - /** - Returns pet inventories by status - - - parameter apiResponseQueue: The queue on which api response is dispatched. - - parameter completion: completion handler to receive the data and the error objects - */ - open class func getInventory(apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: [String: Int]?, _ error: Error?) -> Void)) { - getInventoryWithRequestBuilder().execute(apiResponseQueue) { result in - switch result { - case let .success(response): - completion(response.body, nil) - case let .failure(error): - completion(nil, error) - } - } - } - - /** - Returns pet inventories by status - - GET /store/inventory - - Returns a map of status codes to quantities - - API Key: - - type: apiKey api_key - - name: api_key - - returns: RequestBuilder<[String: Int]> - */ - open class func getInventoryWithRequestBuilder() -> RequestBuilder<[String: Int]> { - let localVariablePath = "/store/inventory" - let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath - let localVariableParameters: [String: Any]? = nil - - let localVariableUrlComponents = URLComponents(string: localVariableURLString) - - let localVariableNillableHeaders: [String: Any?] = [ - : - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder<[String: Int]>.Type = OpenAPIClientAPI.requestBuilderFactory.getBuilder() - - return localVariableRequestBuilder.init(method: "GET", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) - } - - /** - Find purchase order by ID - - - parameter orderId: (path) ID of pet that needs to be fetched - - parameter apiResponseQueue: The queue on which api response is dispatched. - - parameter completion: completion handler to receive the data and the error objects - */ - open class func getOrderById(orderId: Int64, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Order?, _ error: Error?) -> Void)) { - getOrderByIdWithRequestBuilder(orderId: orderId).execute(apiResponseQueue) { result in - switch result { - case let .success(response): - completion(response.body, nil) - case let .failure(error): - completion(nil, error) - } - } - } - - /** - Find purchase order by ID - - GET /store/order/{orderId} - - For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions - - parameter orderId: (path) ID of pet that needs to be fetched - - returns: RequestBuilder - */ - open class func getOrderByIdWithRequestBuilder(orderId: Int64) -> RequestBuilder { - var localVariablePath = "/store/order/{orderId}" - let orderIdPreEscape = "\(APIHelper.mapValueToPathItem(orderId))" - let orderIdPostEscape = orderIdPreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" - localVariablePath = localVariablePath.replacingOccurrences(of: "{orderId}", with: orderIdPostEscape, options: .literal, range: nil) - let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath - let localVariableParameters: [String: Any]? = nil - - let localVariableUrlComponents = URLComponents(string: localVariableURLString) - - let localVariableNillableHeaders: [String: Any?] = [ - : - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getBuilder() - - return localVariableRequestBuilder.init(method: "GET", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) - } - - /** - Place an order for a pet - - - parameter order: (body) order placed for purchasing the pet - - parameter apiResponseQueue: The queue on which api response is dispatched. - - parameter completion: completion handler to receive the data and the error objects - */ - open class func placeOrder(order: Order, apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, completion: @escaping ((_ data: Order?, _ error: Error?) -> Void)) { - placeOrderWithRequestBuilder(order: order).execute(apiResponseQueue) { result in - switch result { - case let .success(response): - completion(response.body, nil) - case let .failure(error): - completion(nil, error) - } - } - } - - /** - Place an order for a pet - - POST /store/order - - parameter order: (body) order placed for purchasing the pet - - returns: RequestBuilder - */ - open class func placeOrderWithRequestBuilder(order: Order) -> RequestBuilder { - let localVariablePath = "/store/order" - let localVariableURLString = OpenAPIClientAPI.basePath + localVariablePath - let localVariableParameters = JSONEncodingHelper.encodingParameters(forEncodableObject: order) - - let localVariableUrlComponents = URLComponents(string: localVariableURLString) - - let localVariableNillableHeaders: [String: Any?] = [ - : - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder.Type = OpenAPIClientAPI.requestBuilderFactory.getBuilder() - - return localVariableRequestBuilder.init(method: "POST", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) - } -} diff --git a/modules/openapi-generator/src/main/resources/swift-alt/OpenISO8601DateFormatter.mustache b/modules/openapi-generator/src/main/resources/swift-alt/OpenISO8601DateFormatter.mustache index 29c28dac3ffb..aeb29f3767db 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/OpenISO8601DateFormatter.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/OpenISO8601DateFormatter.mustache @@ -8,7 +8,7 @@ import Foundation // https://stackoverflow.com/a/50281094/976628 -{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} class OpenISO8601DateFormatter: DateFormatter { +class OpenISO8601DateFormatter: DateFormatter { static let withoutSeconds: DateFormatter = { let formatter = DateFormatter() formatter.calendar = Calendar(identifier: .iso8601) @@ -35,7 +35,7 @@ import Foundation setup() } - override {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} func date(from string: String) -> Date? { + override func date(from string: String) -> Date? { if let result = super.date(from: string) { return result } diff --git a/modules/openapi-generator/src/main/resources/swift-alt/Package.mustache b/modules/openapi-generator/src/main/resources/swift-alt/Package.mustache new file mode 100644 index 000000000000..17d896260a3c --- /dev/null +++ b/modules/openapi-generator/src/main/resources/swift-alt/Package.mustache @@ -0,0 +1,24 @@ +// swift-tools-version:5.1 + +import PackageDescription + +let package = Package( + name: "{{projectName}}", + platforms: [ + .iOS(.v13) + ], + products: [ + .library( + name: "{{projectName}}", + targets: ["{{projectName}}"] + ), + ], + dependencies: [], + targets: [ + .target( + name: "{{projectName}}", + dependencies: [], + path: "Sources" + ), + ] +) diff --git a/modules/openapi-generator/src/main/resources/swift-alt/Package.swift.mustache b/modules/openapi-generator/src/main/resources/swift-alt/Package.swift.mustache deleted file mode 100644 index c84db4b5c772..000000000000 --- a/modules/openapi-generator/src/main/resources/swift-alt/Package.swift.mustache +++ /dev/null @@ -1,57 +0,0 @@ -// swift-tools-version:5.1 - -import PackageDescription - -let package = Package( - name: "{{projectName}}", - platforms: [ - {{#useVapor}} - .macOS(.v10_15), - {{/useVapor}} - {{^useVapor}} - {{#useAlamofire}} - .iOS(.v10), - .macOS(.v10_12), - .tvOS(.v10), - {{/useAlamofire}} - {{^useAlamofire}} - .iOS(.v9), - .macOS(.v10_11), - .tvOS(.v9), - {{/useAlamofire}} - .watchOS(.v3), - {{/useVapor}} - ], - products: [ - // Products define the executables and libraries produced by a package, and make them visible to other packages. - .library( - name: "{{projectName}}", - targets: ["{{projectName}}"] - ), - ], - dependencies: [ - // Dependencies declare other packages that this package depends on. - .package(url: "https://github.com/Flight-School/AnyCodable", from: "0.6.1"), - {{#useAlamofire}} - .package(url: "https://github.com/Alamofire/Alamofire", from: "5.4.3"), - {{/useAlamofire}} - {{#usePromiseKit}} - .package(url: "https://github.com/mxcl/PromiseKit", from: "6.15.3"), - {{/usePromiseKit}} - {{#useRxSwift}} - .package(url: "https://github.com/ReactiveX/RxSwift", from: "6.2.0"), - {{/useRxSwift}} - {{#useVapor}} - .package(url: "https://github.com/vapor/vapor", from: "4.0.0") - {{/useVapor}} - ], - targets: [ - // Targets are the basic building blocks of a package. A target can define a module or a test suite. - // Targets can depend on other targets in this package, and on products in packages which this package depends on. - .target( - name: "{{projectName}}", - dependencies: ["AnyCodable", {{#useVapor}}"Vapor", {{/useVapor}}{{#useAlamofire}}"Alamofire", {{/useAlamofire}}{{#usePromiseKit}}"PromiseKit", {{/usePromiseKit}}{{#useRxSwift}}"RxSwift"{{/useRxSwift}}], - path: "{{swiftPackagePath}}{{^swiftPackagePath}}{{#useSPMFileStructure}}Sources/{{projectName}}{{/useSPMFileStructure}}{{^useSPMFileStructure}}{{projectName}}/Classes{{/useSPMFileStructure}}{{/swiftPackagePath}}" - ), - ] -) diff --git a/modules/openapi-generator/src/main/resources/swift-alt/Runtime.mustache b/modules/openapi-generator/src/main/resources/swift-alt/Runtime.mustache new file mode 100644 index 000000000000..0be8580bdf85 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/swift-alt/Runtime.mustache @@ -0,0 +1,135 @@ +// {{classname}}.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech + +import Foundation +import Combine + +// MARK: - Open API Scheme + +public enum SecurityScheme { + case bearer + // Other schemes not supported yet https://swagger.io/docs/specification/authentication/ +} + +// MARK: - Authenticator + +public protocol Authenticator { + func authenticate(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher + func refresh() -> AnyPublisher +} + +/// Authenticator which does not authenticate requests and does not refresh it +open class EmptyAuthenticator: Authenticator { + public func authenticate(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher { + Just(request) + .setFailureType(to: Error.self) + .eraseToAnyPublisher() + } + + public func refresh() -> AnyPublisher { + Just(()) + .setFailureType(to: Error.self) + .eraseToAnyPublisher() + } + + public init() { + } +} + +// MARK: - Transport + +public protocol Transport { + var baseURL: URL { get } + func send(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher +} + +public struct TransportResponse { + public let data: Data + public let statusCode: Int +} + +public struct TransportError: Error { + public let data: Data + public let statusCode: Int + public let nestedError: Error? +} + +public extension TransportError { + // Impossible to add authentication headers to request + static let incorrectAuthenticationCode = 601 + // Error while refreshing authentication + static let failedAuthenticationRefreshCode = 602 + // There is no HTTP URL response + static let noResponseCode = 603 +} + +public protocol URLSessionTransportDelegate: AnyObject { + func willStart(request: URLRequest) + func didFinish(request: URLRequest, response: HTTPURLResponse?) +} + +open class URLSessionTransport: Transport { + private var cancellable = Set() + let session: URLSession + let authenticator: Authenticator + // Amount of time application will refresh authentication and try performing network call again + let authenticationRetryLimit = 1 + public let baseURL: URL + public weak var delegate: URLSessionTransportDelegate? + + public init(baseURL: URL, session: URLSession = .shared, authenticator: Authenticator = EmptyAuthenticator()) { + self.baseURL = baseURL + self.session = session + self.authenticator = authenticator + } + + open func send(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher { + send(request: request, securitySchemes: securitySchemes, triesLeft: authenticationRetryLimit) + } + + func send(request: URLRequest, securitySchemes: [SecurityScheme], triesLeft: Int) -> AnyPublisher { + authenticator + // Add authentication headers if needed before request + .authenticate(request: request, securitySchemes: securitySchemes) + .mapError { + TransportError(data: Data(), statusCode: TransportError.incorrectAuthenticationCode, nestedError: $0) + } + .flatMap { request -> AnyPublisher in + self.delegate?.willStart(request: request) + // Perform network call + return URLSession.shared.dataTaskPublisher(for: request) + .mapError { TransportError(data: Data(), statusCode: $0.code.rawValue, nestedError: nil) } + .flatMap { output -> AnyPublisher in + let response = output.response as? HTTPURLResponse + self.delegate?.didFinish(request: request, response: response) + switch response?.statusCode { + case .some(200): + let transportResponse = TransportResponse(data: output.data, statusCode: 200) + return Result.success(transportResponse).publisher.eraseToAnyPublisher() + case .some(401) where triesLeft > 0: + // Refresh authentication if possible + return self.authenticator + .refresh() + .mapError { + TransportError(data: Data(), statusCode: TransportError.failedAuthenticationRefreshCode, nestedError: $0) + } + .flatMap { + // Try performing network call again + self.send(request: request, securitySchemes: securitySchemes, triesLeft: triesLeft - 1) + } + .eraseToAnyPublisher() + case let .some(status): + let error = TransportError(data: output.data, statusCode: status, nestedError: nil) + return Fail(error: error).eraseToAnyPublisher() + default: + let error = TransportError(data: output.data, statusCode: TransportError.noResponseCode, nestedError: nil) + return Fail(error: error).eraseToAnyPublisher() + } + } + .eraseToAnyPublisher() + } + .eraseToAnyPublisher() + } +} diff --git a/modules/openapi-generator/src/main/resources/swift-alt/Runtime.swift b/modules/openapi-generator/src/main/resources/swift-alt/Runtime.swift index 65f3d797d7ed..fde484e4c94f 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/Runtime.swift +++ b/modules/openapi-generator/src/main/resources/swift-alt/Runtime.swift @@ -1,149 +1,130 @@ -//struct FeedbackData: Codable { -//} -// -//struct Feedback: Codable { -// let user: String -// let currentDate: Date -// let param: String -// let data: FeedbackData -//} -// -//struct FeedbackOutput: Codable { -//} -// -//struct SupportService { -// let transport: Transport -// -// init(_ transport: Transport) { -// self.transport = transport -// } -// -// func sendFeedback(_ feedback: Feedback) -> AnyPublisher, Never> { -// -// let url: URL = transport.baseURL.appending("/feedback") -// + feedback.user.encode.urlEncode + -// "&" + feedback.currentDate.encode.urlEncode -// -// var request = URLRequest(url: url) -// -// request.httpMethod = "POST" -// request.setValue(feedback.param, forHTTPHeaderField: "param") -// request.httpBody = try? JSONEncoder().encode(feedback.data) -// -// return transport.send(request, auth: .httpBearer) -// .map { -// map($0) -// } -// .eraseToAnyPublisher() -// } -// -// private func map(_ response: TransportResponse) -> Result { -// // 200, 401, 403 -// switch response.response.statusCode { -// case 200: -// if let data = response.data, let value = try? JSONDecoder().decode(FeedbackOutput.self, from: data) { -// return .success(value) -// } -// default: -// return .failure(response.error ?? .unknown) -// } -// } -//} -// -//class SwooAuthService { -//} - -/// Runtime - import Foundation import Combine +// MARK: - Open API Scheme + public enum SecurityScheme { - case none + case bearer // Other schemes not supported yet https://swagger.io/docs/specification/authentication/ } -public protocol HTTPAuth { - func bearer() -> Future -} +// MARK: - Authenticator -public enum TransportError: Error { - case noInternetConnection - case unknown +public protocol Authenticator { + func authenticate(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher + func refresh() -> AnyPublisher } -public struct TransportResponse { - public let data: Data? - public let response: HTTPURLResponse? - public let error: TransportError? +/// Authenticator which does not authenticate requests and does not refresh it +open class EmptyAuthenticator: Authenticator { + public func authenticate(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher { + Just(request) + .setFailureType(to: Error.self) + .eraseToAnyPublisher() + } + + public func refresh() -> AnyPublisher { + Just(()) + .setFailureType(to: Error.self) + .eraseToAnyPublisher() + } + + public init() { + } } +// MARK: - Transport + public protocol Transport { var baseURL: URL { get } - func send(request: URLRequest, securityScheme: SecurityScheme) -> Future + func send(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher +} + +public struct TransportResponse { + public let data: Data + public let statusCode: Int +} + +public struct TransportError: Error { + public let data: Data + public let statusCode: Int + public let nestedError: Error? +} + +public extension TransportError { + // Impossible to add authentication headers to request + static let incorrectAuthenticationCode = 601 + // Error while refreshing authentication + static let failedAuthenticationRefreshCode = 602 + // There is no HTTP URL response + static let noResponseCode = 603 +} + +public protocol URLSessionTransportDelegate: AnyObject { + func willStart(request: URLRequest) + func didFinish(request: URLRequest, response: HTTPURLResponse?) } -public class URLSessionTransport: Transport { +open class URLSessionTransport: Transport { + private var cancellable = Set() let session: URLSession - let auth: HTTPAuth - public var baseURL: URL - public var commonHeaders: [String: String] = [:] + let authenticator: Authenticator + // Amount of time application will refresh authentication and try performing network call again + let authenticationRetryLimit = 1 + public let baseURL: URL + public weak var delegate: URLSessionTransportDelegate? - public init(session: URLSession = .shared, baseURL: URL, auth: HTTPAuth) { - self.session = session - self.auth = auth + public init(baseURL: URL, session: URLSession = .shared, authenticator: Authenticator = EmptyAuthenticator()) { self.baseURL = baseURL + self.session = session + self.authenticator = authenticator } - public func send(request: URLRequest, securityScheme: SecurityScheme) -> Future { - Future { promise in - // TODO: add headers to requests - promise(.success(TransportResponse(data: nil, response: nil, error: nil))) - } + open func send(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher { + send(request: request, securitySchemes: securitySchemes, triesLeft: authenticationRetryLimit) } -} -/// Client - -//class SwooHTTPAuth: HTTPAuth { -// private(set) var bearer: String? -// -// func bearer() -> Future { -// Future { promise in promise(.success("")) } -// } -// -//// func bearer() -> Future { -//// guard let bearer = _bearer else { -//// return renew() -//// } -//// return Future { promice in -//// .. -//// } -//// } -// -// func renew() -> Future { -// -// } -//} -// -//enum Config { -// static let authBaseURL = "https://swoo.auth.com" -// static let feedbackBaseURL = "https://swoo.feedback.com" -//} -// -//let authTransport = DefaultTransport(Config.authBaseURL) -//let authService = SwooAuthService(authTransport) -//let swooHTTPAuth = SwooHTTPAuth(authService: authService) -// -//let transport = URLSessionTransport(baseURL: Config.feedbackBaseURL, auth: swooHTTPAuth) -//let service = SupportService(transport) -// -//service.sendFeedback(Feedback(user: "User", currentDate: .now(), param: "param", data: .init())) -// .sink { result in -// .. -// } -// .store(...) - -// Open questions -// - cancellation - is it really needed? -// - httpauth - should the bearer be future or just for renew procedure? + func send(request: URLRequest, securitySchemes: [SecurityScheme], triesLeft: Int) -> AnyPublisher { + authenticator + // Add authentication headers if needed before request + .authenticate(request: request, securitySchemes: securitySchemes) + .mapError { + TransportError(data: Data(), statusCode: TransportError.incorrectAuthenticationCode, nestedError: $0) + } + .flatMap { request -> AnyPublisher in + self.delegate?.willStart(request: request) + // Perform network call + return URLSession.shared.dataTaskPublisher(for: request) + .mapError { TransportError(data: Data(), statusCode: $0.code.rawValue, nestedError: nil) } + .flatMap { output -> AnyPublisher in + let response = output.response as? HTTPURLResponse + self.delegate?.didFinish(request: request, response: response) + switch response?.statusCode { + case .some(200): + let transportResponse = TransportResponse(data: output.data, statusCode: 200) + return Result.success(transportResponse).publisher.eraseToAnyPublisher() + case .some(401) where triesLeft > 0: + // Refresh authentication if possible + return self.authenticator + .refresh() + .mapError { + TransportError(data: Data(), statusCode: TransportError.failedAuthenticationRefreshCode, nestedError: $0) + } + .flatMap { + // Try performing network call again + self.send(request: request, securitySchemes: securitySchemes, triesLeft: triesLeft - 1) + } + .eraseToAnyPublisher() + case let .some(status): + let error = TransportError(data: output.data, statusCode: status, nestedError: nil) + return Fail(error: error).eraseToAnyPublisher() + default: + let error = TransportError(data: output.data, statusCode: TransportError.noResponseCode, nestedError: nil) + return Fail(error: error).eraseToAnyPublisher() + } + } + .eraseToAnyPublisher() + } + .eraseToAnyPublisher() + } +} diff --git a/modules/openapi-generator/src/main/resources/swift-alt/SynchronizedDictionary.mustache b/modules/openapi-generator/src/main/resources/swift-alt/SynchronizedDictionary.mustache deleted file mode 100644 index acf7ff4031bd..000000000000 --- a/modules/openapi-generator/src/main/resources/swift-alt/SynchronizedDictionary.mustache +++ /dev/null @@ -1,36 +0,0 @@ -// SynchronizedDictionary.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech -// - -import Foundation - -internal struct SynchronizedDictionary { - - private var dictionary = [K: V]() - private let queue = DispatchQueue( - label: "SynchronizedDictionary", - qos: DispatchQoS.userInitiated, - attributes: [DispatchQueue.Attributes.concurrent], - autoreleaseFrequency: DispatchQueue.AutoreleaseFrequency.inherit, - target: nil - ) - - internal subscript(key: K) -> V? { - get { - var value: V? - - queue.sync { - value = self.dictionary[key] - } - - return value - } - set { - queue.sync(flags: DispatchWorkItemFlags.barrier) { - self.dictionary[key] = newValue - } - } - } -} diff --git a/modules/openapi-generator/src/main/resources/swift-alt/XcodeGen.mustache b/modules/openapi-generator/src/main/resources/swift-alt/XcodeGen.mustache deleted file mode 100644 index 31f01b8bedd6..000000000000 --- a/modules/openapi-generator/src/main/resources/swift-alt/XcodeGen.mustache +++ /dev/null @@ -1,18 +0,0 @@ -name: {{projectName}} -targets: - {{projectName}}: - type: framework - platform: iOS - deploymentTarget: "9.0" - sources: [{{swiftPackagePath}}{{^swiftPackagePath}}{{#useSPMFileStructure}}Sources{{/useSPMFileStructure}}{{^useSPMFileStructure}}{{projectName}}{{/useSPMFileStructure}}{{/swiftPackagePath}}] - info: - path: ./Info.plist - version: {{podVersion}}{{^podVersion}}{{#apiInfo}}{{version}}{{/apiInfo}}{{^apiInfo}}}0.0.1{{/apiInfo}}{{/podVersion}} - settings: - APPLICATION_EXTENSION_API_ONLY: true - scheme: {} - dependencies: - - carthage: AnyCodable{{#useAlamofire}} - - carthage: Alamofire{{/useAlamofire}}{{#usePromiseKit}} - - carthage: PromiseKit{{/usePromiseKit}}{{#useRxSwift}} - - carthage: RxSwift{{/useRxSwift}} diff --git a/modules/openapi-generator/src/main/resources/swift-alt/_converted_param.mustache b/modules/openapi-generator/src/main/resources/swift-alt/_converted_param.mustache deleted file mode 100644 index 458b624d1410..000000000000 --- a/modules/openapi-generator/src/main/resources/swift-alt/_converted_param.mustache +++ /dev/null @@ -1 +0,0 @@ -{{#isArray}}{{paramName}}{{^required}}?{{/required}}.joined(separator: ", "){{/isArray}}{{^isArray}}{{paramName}}{{/isArray}} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/swift-alt/_param.mustache b/modules/openapi-generator/src/main/resources/swift-alt/_param.mustache deleted file mode 100644 index 770458343aa9..000000000000 --- a/modules/openapi-generator/src/main/resources/swift-alt/_param.mustache +++ /dev/null @@ -1 +0,0 @@ -"{{baseName}}": {{paramName}}{{^required}}?{{/required}}.encodeToJSON() \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/swift-alt/api.mustache b/modules/openapi-generator/src/main/resources/swift-alt/api.mustache index 80257dab5684..d0b29519e378 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/api.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/api.mustache @@ -12,13 +12,13 @@ import Combine {{#description}} /** {{{.}}} */{{/description}} open class {{classname}} { - private let encoder: JSONEncoder = { + private static let encoder: JSONEncoder = { let encoder = JSONEncoder() encoder.dateEncodingStrategy = .formatted(OpenISO8601DateFormatter()) encoder.outputFormatting = .prettyPrinted return encoder }() - private let decoder: JSONDecoder = { + private static let decoder: JSONDecoder = { let decoder = JSONDecoder() decoder.dateDecodingStrategy = .formatted(OpenISO8601DateFormatter()) return decoder @@ -52,9 +52,9 @@ open class {{classname}} { {{#allParams}} - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} {{/allParams}} - - returns: AnyPublisher, Never> {{description}} + - returns: AnyPublisher<{{{returnType}}}{{^returnType}}Void{{/returnType}}, Error> {{description}} */ - open func {{operationId}}({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}) -> AnyPublisher, Never> { + open func {{operationId}}({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}) -> AnyPublisher<{{{returnType}}}{{^returnType}}Void{{/returnType}}, Error> { // Creating final URL with query items and path var components = URLComponents() components.path = "{{path}}" @@ -83,65 +83,25 @@ open class {{classname}} { "{{baseName}}": {{paramName}}{{^-last}}, {{/-last}}{{/headerParams}} ].compactMapValues { $0 }{{/hasHeaderParams}} {{#hasBodyParam}}{{#bodyParam}}// Setting body parameters {{! TODO: Convert value to data if needed (can be nil, can be Data already) }} - request.httpBody = try? encoder.encode({{paramName}}){{/bodyParam}}{{/hasBodyParam}} + request.httpBody = try? {{classname}}.encoder.encode({{paramName}}) + if request.value(forHTTPHeaderField: "Content-Type") == nil { + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + } + {{/bodyParam}}{{/hasBodyParam}} // Getting auth type {{! TODO: Set proper auth type) }} - let securityScheme: SecurityScheme = .none - return transport.send(request: request, securityScheme: securityScheme) - .map { response -> Result<{{{returnType}}}{{^returnType}}Void{{/returnType}}, Error> in + let securitySchemes: [SecurityScheme] = [{{#authMethods}}{{#isBasicBearer}}.bearer{{/isBasicBearer}}{{/authMethods}}] + return transport.send(request: request, securitySchemes: securitySchemes) + .tryMap { response in {{! TODO: Check responses properly }} - if response.response?.statusCode == 200 { - {{#returnType}} - if let data = response.data { - return Result { try self.decoder.decode({{{returnType}}}.self, from: data) } - } else { - return .failure(TransportError.unknown) - } - {{/returnType}} - {{^returnType}} - return .success(()) - {{/returnType}} - } else { - return .failure(response.error ?? TransportError.unknown) - } + {{#returnType}} + try {{classname}}.decoder.decode({{{returnType}}}.self, from: response.data) + {{/returnType}} + {{^returnType}} + return () + {{/returnType}} } .eraseToAnyPublisher() } {{/operation}} } -{{/operations}} - - -private class OpenISO8601DateFormatter: DateFormatter { - static let withoutSeconds: DateFormatter = { - let formatter = DateFormatter() - formatter.calendar = Calendar(identifier: .iso8601) - formatter.locale = Locale(identifier: "en_US_POSIX") - formatter.timeZone = TimeZone(secondsFromGMT: 0) - formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ" - return formatter - }() - - private func setup() { - calendar = Calendar(identifier: .iso8601) - locale = Locale(identifier: "en_US_POSIX") - timeZone = TimeZone(secondsFromGMT: 0) - dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ" - } - - override init() { - super.init() - setup() - } - - required init?(coder aDecoder: NSCoder) { - super.init(coder: aDecoder) - setup() - } - - override func date(from string: String) -> Date? { - if let result = super.date(from: string) { - return result - } - return OpenISO8601DateFormatter.withoutSeconds.date(from: string) - } -} \ No newline at end of file +{{/operations}} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/swift-alt/api_old.mustache b/modules/openapi-generator/src/main/resources/swift-alt/api_old.mustache deleted file mode 100644 index 65042a07213e..000000000000 --- a/modules/openapi-generator/src/main/resources/swift-alt/api_old.mustache +++ /dev/null @@ -1,515 +0,0 @@ -{{#operations}}// -// {{classname}}.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech -// - -/** -{{#summary}} - {{{.}}} -{{/summary}} -- {{httpMethod}} {{{path}}}{{#notes}} - - {{{.}}}{{/notes}}{{#subresourceOperation}} - - subresourceOperation: {{.}}{{/subresourceOperation}}{{#defaultResponse}} - - defaultResponse: {{.}}{{/defaultResponse}} -{{#authMethods}} - - {{#isBasic}}BASIC{{/isBasic}}{{#isOAuth}}OAuth{{/isOAuth}}{{#isApiKey}}API Key{{/isApiKey}}: - - type: {{type}}{{#keyParamName}} {{keyParamName}} {{#isKeyInQuery}}(QUERY){{/isKeyInQuery}}{{#isKeyInHeaer}}(HEADER){{/isKeyInHeaer}}{{/keyParamName}} - - name: {{name}} -{{/authMethods}} -{{#hasResponseHeaders}} - - responseHeaders: [{{#responseHeaders}}{{{baseName}}}({{{dataType}}}){{^-last}}, {{/-last}}{{/responseHeaders}}] -{{/hasResponseHeaders}} -{{#externalDocs}} - - externalDocs: {{.}} -{{/externalDocs}} -{{#allParams}} - - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} -{{/allParams}} -- returns: RequestBuilder<{{{returnType}}}{{^returnType}}Void{{/returnType}}> {{description}} - */ -{{#isDeprecated}} - @available(*, deprecated, message: "This operation is deprecated.") -{{/isDeprecated}} -{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class func {{operationId}}WithRequestBuilder({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}) -> RequestBuilder<{{{returnType}}}{{^returnType}}Void{{/returnType}}> { -{{^pathParams}}let{{/pathParams}}{{#pathParams}}{{#-first}}var{{/-first}}{{/pathParams}} localVariablePath = "{{{path}}}"{{#pathParams}} - let {{paramName}}PreEscape = "\({{#isEnum}}{{paramName}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}.rawValue{{/isContainer}}{{/isEnum}}{{^isEnum}}APIHelper.mapValueToPathItem({{paramName}}){{/isEnum}})" - let {{paramName}}PostEscape = {{paramName}}PreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" - localVariablePath = localVariablePath.replacingOccurrences(of: "{{=<% %>=}}{<%baseName%>}<%={{ }}=%>", with: {{paramName}}PostEscape, options: .literal, range: nil){{/pathParams}} - let localVariableURLString = {{projectName}}API.basePath + localVariablePath -{{#bodyParam}} - let localVariableParameters = JSONEncodingHelper.encodingParameters(forEncodableObject: {{paramName}}) -{{/bodyParam}} -{{^bodyParam}} - {{#hasFormParams}} - let localVariableFormParams: [String: Any?] = [ - {{#formParams}} - {{> _param}}, - {{/formParams}} - ] - - let localVariableNonNullParameters = APIHelper.rejectNil(localVariableFormParams) - let localVariableParameters = APIHelper.convertBoolToString(localVariableNonNullParameters) - {{/hasFormParams}} - {{^hasFormParams}} - let localVariableParameters: [String: Any]? = nil - {{/hasFormParams}} -{{/bodyParam}}{{#hasQueryParams}} - var localVariableUrlComponents = URLComponents(string: localVariableURLString) - localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems([{{^queryParams}}:{{/queryParams}} - {{#queryParams}} - {{> _param}}, - {{/queryParams}} - ]){{/hasQueryParams}}{{^hasQueryParams}} - let localVariableUrlComponents = URLComponents(string: localVariableURLString){{/hasQueryParams}} - - let localVariableNillableHeaders: [String: Any?] = [{{^headerParams}}{{^hasFormParams}} - :{{/hasFormParams}}{{/headerParams}}{{#hasFormParams}} - "Content-Type": {{^consumes}}"multipart/form-data"{{/consumes}}{{#consumes.0}}"{{{mediaType}}}"{{/consumes.0}},{{/hasFormParams}}{{#headerParams}} - {{> _param}},{{/headerParams}} - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder<{{{returnType}}}{{^returnType}}Void{{/returnType}}>.Type = {{projectName}}API.requestBuilderFactory.{{#returnType}}getBuilder(){{/returnType}}{{^returnType}}getNonDecodableBuilder(){{/returnType}} - - return localVariableRequestBuilder.init(method: "{{httpMethod}}", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) - } - -import Foundation{{#usePromiseKit}} -import PromiseKit{{/usePromiseKit}}{{#useRxSwift}} -import RxSwift{{/useRxSwift}}{{#useCombine}} -#if canImport(Combine) -import Combine -#endif{{/useCombine}}{{#useVapor}} -import Vapor{{/useVapor}} -#if canImport(AnyCodable) -import AnyCodable -#endif{{#swiftUseApiNamespace}} - -extension {{projectName}}API { -{{/swiftUseApiNamespace}} - -{{#description}} -/** {{{.}}} */{{/description}} -{{#objcCompatible}}@objc {{/objcCompatible}}{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class {{classname}}{{#objcCompatible}} : NSObject{{/objcCompatible}} { -{{#operation}} - - {{#allParams}} - {{#isEnum}} - /** - * enum for parameter {{paramName}} - */ - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} enum {{enumName}}_{{operationId}}: {{^isContainer}}{{{dataType}}}{{/isContainer}}{{#isContainer}}String{{/isContainer}}, CaseIterable{{#useVapor}}, Content{{/useVapor}} { - {{#allowableValues}} - {{#enumVars}} - case {{name}} = {{{value}}} - {{/enumVars}} - {{/allowableValues}} - } - - {{/isEnum}} - {{/allParams}} -{{^useVapor}} -{{^usePromiseKit}} -{{^useRxSwift}} -{{^useResult}} -{{^useCombine}} -{{^useAsyncAwait}} - /** - {{#summary}} - {{{.}}} - {{/summary}}{{#allParams}} - - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}} - - parameter apiResponseQueue: The queue on which api response is dispatched. - - parameter completion: completion handler to receive the data and the error objects - */ - {{#isDeprecated}} - @available(*, deprecated, message: "This operation is deprecated.") - {{/isDeprecated}} - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class func {{operationId}}({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}apiResponseQueue: DispatchQueue = {{projectName}}API.apiResponseQueue, completion: @escaping ((_ data: {{{returnType}}}{{^returnType}}Void{{/returnType}}?, _ error: Error?) -> Void)) { - {{operationId}}WithRequestBuilder({{#allParams}}{{paramName}}: {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}).execute(apiResponseQueue) { result in - switch result { - {{#returnType}} - case let .success(response): - completion(response.body, nil) - {{/returnType}} - {{^returnType}} - case .success: - completion((), nil) - {{/returnType}} - case let .failure(error): - completion(nil, error) - } - } - } -{{/useAsyncAwait}} -{{/useCombine}} -{{/useResult}} -{{/useRxSwift}} -{{/usePromiseKit}} -{{/useVapor}} -{{#usePromiseKit}} - /** - {{#summary}} - {{{.}}} - {{/summary}}{{#allParams}} - - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}} - - parameter apiResponseQueue: The queue on which api response is dispatched. - - returns: Promise<{{{returnType}}}{{^returnType}}Void{{/returnType}}> - */ - {{#isDeprecated}} - @available(*, deprecated, message: "This operation is deprecated.") - {{/isDeprecated}} - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class func {{operationId}}({{#allParams}} {{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}apiResponseQueue: DispatchQueue = {{projectName}}API.apiResponseQueue) -> Promise<{{{returnType}}}{{^returnType}}Void{{/returnType}}> { - let deferred = Promise<{{{returnType}}}{{^returnType}}Void{{/returnType}}>.pending() - {{operationId}}WithRequestBuilder({{#allParams}}{{paramName}}: {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}).execute(apiResponseQueue) { result in - switch result { - {{#returnType}} - case let .success(response): - deferred.resolver.fulfill(response.body!) - {{/returnType}} - {{^returnType}} - case .success: - deferred.resolver.fulfill(()) - {{/returnType}} - case let .failure(error): - deferred.resolver.reject(error) - } - } - return deferred.promise - } -{{/usePromiseKit}} -{{#useRxSwift}} - /** - {{#summary}} - {{{.}}} - {{/summary}}{{#allParams}} - - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}} - - parameter apiResponseQueue: The queue on which api response is dispatched. - - returns: Observable<{{{returnType}}}{{^returnType}}Void{{/returnType}}> - */ - {{#isDeprecated}} - @available(*, deprecated, message: "This operation is deprecated.") - {{/isDeprecated}} - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class func {{operationId}}({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}apiResponseQueue: DispatchQueue = {{projectName}}API.apiResponseQueue) -> Observable<{{{returnType}}}{{^returnType}}Void{{/returnType}}> { - return Observable.create { observer -> Disposable in - {{operationId}}WithRequestBuilder({{#allParams}}{{paramName}}: {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}).execute(apiResponseQueue) { result in - switch result { - {{#returnType}} - case let .success(response): - observer.onNext(response.body!) - {{/returnType}} - {{^returnType}} - case .success: - observer.onNext(()) - {{/returnType}} - case let .failure(error): - observer.onError(error) - } - observer.onCompleted() - } - return Disposables.create() - } - } -{{/useRxSwift}} -{{#useCombine}} - /** - {{#summary}} - {{{.}}} - {{/summary}}{{#allParams}} - - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}} - - parameter apiResponseQueue: The queue on which api response is dispatched. - - returns: AnyPublisher<{{{returnType}}}{{^returnType}}Void{{/returnType}}, Error> - */ - #if canImport(Combine) - {{#isDeprecated}} - @available(*, deprecated, message: "This operation is deprecated.") - {{/isDeprecated}} - @available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *) - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class func {{operationId}}({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}apiResponseQueue: DispatchQueue = {{projectName}}API.apiResponseQueue) -> AnyPublisher<{{{returnType}}}{{^returnType}}Void{{/returnType}}, Error> { - return Future<{{{returnType}}}{{^returnType}}Void{{/returnType}}, Error> { promise in - {{operationId}}WithRequestBuilder({{#allParams}}{{paramName}}: {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}).execute(apiResponseQueue) { result in - switch result { - {{#returnType}} - case let .success(response): - promise(.success(response.body!)) - {{/returnType}} - {{^returnType}} - case .success: - promise(.success(())) - {{/returnType}} - case let .failure(error): - promise(.failure(error)) - } - } - }.eraseToAnyPublisher() - } - #endif -{{/useCombine}} -{{#useAsyncAwait}} - /** - {{#summary}} - {{{.}}} - {{/summary}}{{#allParams}} - - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}} - - parameter apiResponseQueue: The queue on which api response is dispatched. - - returns: {{{returnType}}}{{^returnType}}Void{{/returnType}} - */ - {{#isDeprecated}} - @available(*, deprecated, message: "This operation is deprecated.") - {{/isDeprecated}} - @available(macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0, *) - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class func {{operationId}}({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}apiResponseQueue: DispatchQueue = {{projectName}}API.apiResponseQueue) async throws{{#returnType}} -> {{{returnType}}}{{/returnType}} { - return try await withCheckedThrowingContinuation { continuation in - {{operationId}}WithRequestBuilder({{#allParams}}{{paramName}}: {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}).execute(apiResponseQueue) { result in - switch result { - {{#returnType}} - case let .success(response): - continuation.resume(returning: response.body!) - {{/returnType}} - {{^returnType}} - case .success: - continuation.resume(returning: ()) - {{/returnType}} - case let .failure(error): - continuation.resume(throwing: error) - } - } - } - } -{{/useAsyncAwait}} -{{#useResult}} - /** - {{#summary}} - {{{.}}} - {{/summary}}{{#allParams}} - - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}} - - parameter apiResponseQueue: The queue on which api response is dispatched. - - parameter completion: completion handler to receive the result - */ - {{#isDeprecated}} - @available(*, deprecated, message: "This operation is deprecated.") - {{/isDeprecated}} - open class func {{operationId}}({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}apiResponseQueue: DispatchQueue = {{projectName}}API.apiResponseQueue, completion: @escaping ((_ result: Swift.Result<{{{returnType}}}{{^returnType}}Void{{/returnType}}, ErrorResponse>) -> Void)) { - {{operationId}}WithRequestBuilder({{#allParams}}{{paramName}}: {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}).execute(apiResponseQueue) { result in - switch result { - {{#returnType}} - case let .success(response): - completion(.success(response.body!)) - {{/returnType}} - {{^returnType}} - case .success: - completion(.success(())) - {{/returnType}} - case let .failure(error): - completion(.failure(error)) - } - } - } -{{/useResult}} -{{#useVapor}} - /** - {{#summary}} - {{{.}}} - {{/summary}} - {{httpMethod}} {{{path}}}{{#notes}} - {{{.}}}{{/notes}}{{#subresourceOperation}} - subresourceOperation: {{.}}{{/subresourceOperation}}{{#defaultResponse}} - defaultResponse: {{.}}{{/defaultResponse}} - {{#authMethods}} - - {{#isBasic}}BASIC{{/isBasic}}{{#isOAuth}}OAuth{{/isOAuth}}{{#isApiKey}}API Key{{/isApiKey}}: - - type: {{type}}{{#keyParamName}} {{keyParamName}} {{#isKeyInQuery}}(QUERY){{/isKeyInQuery}}{{#isKeyInHeaer}}(HEADER){{/isKeyInHeaer}}{{/keyParamName}} - - name: {{name}} - {{/authMethods}} - {{#hasResponseHeaders}} - - responseHeaders: [{{#responseHeaders}}{{{baseName}}}({{{dataType}}}){{^-last}}, {{/-last}}{{/responseHeaders}}] - {{/hasResponseHeaders}} - {{#externalDocs}} - - externalDocs: {{.}} - {{/externalDocs}} - {{#allParams}} - - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{{description}}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} - {{/allParams}} - - returns: `EventLoopFuture` of `ClientResponse` {{{description}}} - */ - {{#isDeprecated}} - @available(*, deprecated, message: "This operation is deprecated.") - {{/isDeprecated}} - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class func {{operationId}}Raw({{#allParams}}{{paramName}}: {{#isEnum}}{{#isArray}}[{{enumName}}_{{operationId}}]{{/isArray}}{{^isArray}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isArray}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}headers: HTTPHeaders = {{projectName}}API.customHeaders, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { - {{^pathParams}}let{{/pathParams}}{{#pathParams}}{{#-first}}var{{/-first}}{{/pathParams}} localVariablePath = "{{{path}}}"{{#pathParams}} - let {{paramName}}PreEscape = String(describing: {{#isEnum}}{{paramName}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}.rawValue{{/isContainer}}{{/isEnum}}{{^isEnum}}{{paramName}}{{/isEnum}}) - let {{paramName}}PostEscape = {{paramName}}PreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" - localVariablePath = localVariablePath.replacingOccurrences(of: "{{=<% %>=}}{<%baseName%>}<%={{ }}=%>", with: {{paramName}}PostEscape, options: .literal, range: nil){{/pathParams}} - let localVariableURLString = {{projectName}}API.basePath + localVariablePath - - guard let localVariableApiClient = {{#swiftUseApiNamespace}}{{projectName}}API.{{/swiftUseApiNamespace}}Configuration.apiClient else { - fatalError("Configuration.apiClient is not set.") - } - - return localVariableApiClient.send(.{{httpMethod}}, headers: headers, to: URI(string: localVariableURLString)) { localVariableRequest in - try {{#swiftUseApiNamespace}}{{projectName}}API.{{/swiftUseApiNamespace}}Configuration.apiWrapper(&localVariableRequest) - {{#hasHeaderParams}}{{#headerParams}} - localVariableRequest.headers.add(name: "{{baseName}}", value: {{#isArray}}{{paramName}}{{^required}}?{{/required}}.map { $0{{#isEnum}}.rawValue{{/isEnum}}.description }.description{{/isArray}}{{^isArray}}{{#isEnum}}{{paramName}}{{^required}}?{{/required}}.rawValue.description{{/isEnum}}{{^isEnum}}{{paramName}}{{^required}}?{{/required}}.description{{/isEnum}}{{/isArray}}{{^required}} ?? ""{{/required}}) - {{/headerParams}}{{/hasHeaderParams}} - {{#hasQueryParams}}struct QueryParams: Content { - {{#queryParams}} - var {{paramName}}: {{#isEnum}}{{#isArray}}[{{enumName}}_{{operationId}}]{{/isArray}}{{^isArray}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isArray}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}?{{/required}} - {{/queryParams}} - - enum CodingKeys: String, CodingKey { - {{#queryParams}} - case {{paramName}}{{#baseName}} = "{{.}}"{{/baseName}} - {{/queryParams}} - } - } - try localVariableRequest.query.encode(QueryParams({{#queryParams}}{{paramName}}: {{paramName}}{{^-last}}, {{/-last}}{{/queryParams}})){{/hasQueryParams}} - {{#hasBodyParam}} - {{#bodyParam}}{{#required}}{{#isBinary}}localVariableRequest.body = ByteBuffer(data: {{paramName}}){{/isBinary}}{{^isBinary}}{{#isFile}}localVariableRequest.body = ByteBuffer(data: {{paramName}}){{/isFile}}try localVariableRequest.content.encode({{paramName}}, using: Configuration.contentConfiguration.requireEncoder(for: {{{dataType}}}.defaultContentType)){{/isBinary}}{{/required}}{{^required}}if let localVariableBody = {{paramName}} { - {{#isBinary}}localVariableRequest.body = ByteBuffer(data: localVariableBody){{/isBinary}}{{^isBinary}}{{#isFile}}localVariableRequest.body = ByteBuffer(data: localVariableBody){{/isFile}}try localVariableRequest.content.encode(localVariableBody, using: Configuration.contentConfiguration.requireEncoder(for: {{{dataType}}}.defaultContentType)){{/isBinary}} - }{{/required}}{{/bodyParam}} - {{/hasBodyParam}} - {{#hasFormParams}}struct FormParams: Content { - static let defaultContentType = Vapor.HTTPMediaType.formData - {{#formParams}} - var {{paramName}}: {{#isEnum}}{{#isArray}}[{{enumName}}_{{operationId}}]{{/isArray}}{{^isArray}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isArray}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}?{{/required}} - {{/formParams}} - } - try localVariableRequest.content.encode(FormParams({{#formParams}}{{paramName}}: {{paramName}}{{^-last}}, {{/-last}}{{/formParams}}), using: Configuration.contentConfiguration.requireEncoder(for: FormParams.defaultContentType)){{/hasFormParams}} - try beforeSend(&localVariableRequest) - } - } - - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} enum {{#lambda.titlecase}}{{operationId}}{{/lambda.titlecase}} { - {{#responses}} - case http{{code}}({{#dataType}}value: {{{.}}}, {{/dataType}}raw: ClientResponse) - {{/responses}} - {{^hasDefaultResponse}} - case http0(raw: ClientResponse) - {{/hasDefaultResponse}} - } - - /** - {{#summary}} - {{{.}}} - {{/summary}} - {{httpMethod}} {{{path}}}{{#notes}} - {{{.}}}{{/notes}}{{#subresourceOperation}} - subresourceOperation: {{.}}{{/subresourceOperation}}{{#defaultResponse}} - defaultResponse: {{.}}{{/defaultResponse}} - {{#authMethods}} - - {{#isBasic}}BASIC{{/isBasic}}{{#isOAuth}}OAuth{{/isOAuth}}{{#isApiKey}}API Key{{/isApiKey}}: - - type: {{type}}{{#keyParamName}} {{keyParamName}} {{#isKeyInQuery}}(QUERY){{/isKeyInQuery}}{{#isKeyInHeaer}}(HEADER){{/isKeyInHeaer}}{{/keyParamName}} - - name: {{name}} - {{/authMethods}} - {{#hasResponseHeaders}} - - responseHeaders: [{{#responseHeaders}}{{{baseName}}}({{{dataType}}}){{^-last}}, {{/-last}}{{/responseHeaders}}] - {{/hasResponseHeaders}} - {{#externalDocs}} - - externalDocs: {{.}} - {{/externalDocs}} - {{#allParams}} - - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{{description}}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} - {{/allParams}} - - returns: `EventLoopFuture` of `{{#lambda.titlecase}}{{operationId}}{{/lambda.titlecase}}` {{{description}}} - */ - {{#isDeprecated}} - @available(*, deprecated, message: "This operation is deprecated.") - {{/isDeprecated}} - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class func {{operationId}}({{#allParams}}{{paramName}}: {{#isEnum}}{{#isArray}}[{{enumName}}_{{operationId}}]{{/isArray}}{{^isArray}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isArray}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}headers: HTTPHeaders = {{projectName}}API.customHeaders, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture<{{#lambda.titlecase}}{{operationId}}{{/lambda.titlecase}}> { - return {{operationId}}Raw({{#allParams}}{{paramName}}: {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}headers: headers, beforeSend: beforeSend).flatMapThrowing { response -> {{#lambda.titlecase}}{{operationId}}{{/lambda.titlecase}} in - switch response.status.code { - {{#responses}} - {{#isDefault}}default{{/isDefault}}{{^isDefault}}case {{code}}{{/isDefault}}: - return .http{{code}}({{#dataType}}value: {{#isBinary}}Data(buffer: response.body ?? ByteBuffer()){{/isBinary}}{{^isBinary}}{{#isFile}}Data(buffer: response.body ?? ByteBuffer()){{/isFile}}{{^isFile}}try response.content.decode({{{dataType}}}.self, using: Configuration.contentConfiguration.requireDecoder(for: {{{dataType}}}.defaultContentType)){{/isFile}}{{/isBinary}}, {{/dataType}}raw: response) - {{/responses}} - {{^hasDefaultResponse}} - default: - return .http0(raw: response) - {{/hasDefaultResponse}} - } - } - } - -{{/useVapor}} -{{^useVapor}} - - /** - {{#summary}} - {{{.}}} - {{/summary}} - - {{httpMethod}} {{{path}}}{{#notes}} - - {{{.}}}{{/notes}}{{#subresourceOperation}} - - subresourceOperation: {{.}}{{/subresourceOperation}}{{#defaultResponse}} - - defaultResponse: {{.}}{{/defaultResponse}} - {{#authMethods}} - - {{#isBasic}}BASIC{{/isBasic}}{{#isOAuth}}OAuth{{/isOAuth}}{{#isApiKey}}API Key{{/isApiKey}}: - - type: {{type}}{{#keyParamName}} {{keyParamName}} {{#isKeyInQuery}}(QUERY){{/isKeyInQuery}}{{#isKeyInHeaer}}(HEADER){{/isKeyInHeaer}}{{/keyParamName}} - - name: {{name}} - {{/authMethods}} - {{#hasResponseHeaders}} - - responseHeaders: [{{#responseHeaders}}{{{baseName}}}({{{dataType}}}){{^-last}}, {{/-last}}{{/responseHeaders}}] - {{/hasResponseHeaders}} - {{#externalDocs}} - - externalDocs: {{.}} - {{/externalDocs}} - {{#allParams}} - - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} - {{/allParams}} - - returns: RequestBuilder<{{{returnType}}}{{^returnType}}Void{{/returnType}}> {{description}} - */ - {{#isDeprecated}} - @available(*, deprecated, message: "This operation is deprecated.") - {{/isDeprecated}} - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class func {{operationId}}WithRequestBuilder({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}) -> RequestBuilder<{{{returnType}}}{{^returnType}}Void{{/returnType}}> { - {{^pathParams}}let{{/pathParams}}{{#pathParams}}{{#-first}}var{{/-first}}{{/pathParams}} localVariablePath = "{{{path}}}"{{#pathParams}} - let {{paramName}}PreEscape = "\({{#isEnum}}{{paramName}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}.rawValue{{/isContainer}}{{/isEnum}}{{^isEnum}}APIHelper.mapValueToPathItem({{paramName}}){{/isEnum}})" - let {{paramName}}PostEscape = {{paramName}}PreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" - localVariablePath = localVariablePath.replacingOccurrences(of: "{{=<% %>=}}{<%baseName%>}<%={{ }}=%>", with: {{paramName}}PostEscape, options: .literal, range: nil){{/pathParams}} - let localVariableURLString = {{projectName}}API.basePath + localVariablePath - {{#bodyParam}} - let localVariableParameters = JSONEncodingHelper.encodingParameters(forEncodableObject: {{paramName}}) - {{/bodyParam}} - {{^bodyParam}} - {{#hasFormParams}} - let localVariableFormParams: [String: Any?] = [ - {{#formParams}} - {{> _param}}, - {{/formParams}} - ] - - let localVariableNonNullParameters = APIHelper.rejectNil(localVariableFormParams) - let localVariableParameters = APIHelper.convertBoolToString(localVariableNonNullParameters) - {{/hasFormParams}} - {{^hasFormParams}} - let localVariableParameters: [String: Any]? = nil - {{/hasFormParams}} -{{/bodyParam}}{{#hasQueryParams}} - var localVariableUrlComponents = URLComponents(string: localVariableURLString) - localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems([{{^queryParams}}:{{/queryParams}} - {{#queryParams}} - {{> _param}}, - {{/queryParams}} - ]){{/hasQueryParams}}{{^hasQueryParams}} - let localVariableUrlComponents = URLComponents(string: localVariableURLString){{/hasQueryParams}} - - let localVariableNillableHeaders: [String: Any?] = [{{^headerParams}}{{^hasFormParams}} - :{{/hasFormParams}}{{/headerParams}}{{#hasFormParams}} - "Content-Type": {{^consumes}}"multipart/form-data"{{/consumes}}{{#consumes.0}}"{{{mediaType}}}"{{/consumes.0}},{{/hasFormParams}}{{#headerParams}} - {{> _param}},{{/headerParams}} - ] - - let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders) - - let localVariableRequestBuilder: RequestBuilder<{{{returnType}}}{{^returnType}}Void{{/returnType}}>.Type = {{projectName}}API.requestBuilderFactory.{{#returnType}}getBuilder(){{/returnType}}{{^returnType}}getNonDecodableBuilder(){{/returnType}} - - return localVariableRequestBuilder.init(method: "{{httpMethod}}", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters) - } -{{/useVapor}} -{{/operation}} -} -{{#swiftUseApiNamespace}} -} -{{/swiftUseApiNamespace}} -{{/operations}} diff --git a/modules/openapi-generator/src/main/resources/swift-alt/model.mustache b/modules/openapi-generator/src/main/resources/swift-alt/model.mustache index b006540ffc21..575acb79c0f8 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/model.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/model.mustache @@ -6,9 +6,6 @@ // import Foundation -#if canImport(AnyCodable) -import AnyCodable -#endif {{#description}}/** {{.}} */{{/description}} {{#vendorExtensions.x-is-one-of-interface}} diff --git a/samples/client/petstore/swift/alt/.openapi-generator-ignore b/samples/client/petstore/swift-alt/.openapi-generator-ignore similarity index 100% rename from samples/client/petstore/swift/alt/.openapi-generator-ignore rename to samples/client/petstore/swift-alt/.openapi-generator-ignore diff --git a/samples/client/petstore/swift-alt/.openapi-generator/FILES b/samples/client/petstore/swift-alt/.openapi-generator/FILES new file mode 100644 index 000000000000..180d938c5951 --- /dev/null +++ b/samples/client/petstore/swift-alt/.openapi-generator/FILES @@ -0,0 +1,12 @@ +Package.swift +Sources/APIs/PetAPI.swift +Sources/APIs/StoreAPI.swift +Sources/APIs/UserAPI.swift +Sources/Models/ApiResponse.swift +Sources/Models/Category.swift +Sources/Models/Order.swift +Sources/Models/Pet.swift +Sources/Models/Tag.swift +Sources/Models/User.swift +Sources/Private/OpenISO8601DateFormatter.swift +Sources/Runtime.swift diff --git a/samples/client/petstore/swift/alt/.openapi-generator/VERSION b/samples/client/petstore/swift-alt/.openapi-generator/VERSION similarity index 100% rename from samples/client/petstore/swift/alt/.openapi-generator/VERSION rename to samples/client/petstore/swift-alt/.openapi-generator/VERSION diff --git a/samples/client/petstore/swift/alt/OpenAPIClient.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/samples/client/petstore/swift-alt/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata similarity index 100% rename from samples/client/petstore/swift/alt/OpenAPIClient.xcodeproj/project.xcworkspace/contents.xcworkspacedata rename to samples/client/petstore/swift-alt/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata diff --git a/samples/client/petstore/swift-alt/.swiftpm/xcode/package.xcworkspace/xcuserdata/a.davydov.xcuserdatad/UserInterfaceState.xcuserstate b/samples/client/petstore/swift-alt/.swiftpm/xcode/package.xcworkspace/xcuserdata/a.davydov.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..9f357587ec122dd44bbe03c1ba3d2fd20bfb63d4 GIT binary patch literal 16927 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 literal 0 HcmV?d00001 diff --git a/samples/client/petstore/swift/alt/OpenAPIClient.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/samples/client/petstore/swift-alt/.swiftpm/xcode/xcuserdata/a.davydov.xcuserdatad/xcschemes/xcschememanagement.plist similarity index 54% rename from samples/client/petstore/swift/alt/OpenAPIClient.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist rename to samples/client/petstore/swift-alt/.swiftpm/xcode/xcuserdata/a.davydov.xcuserdatad/xcschemes/xcschememanagement.plist index 18d981003d68..9156ea3bf098 100644 --- a/samples/client/petstore/swift/alt/OpenAPIClient.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ b/samples/client/petstore/swift-alt/.swiftpm/xcode/xcuserdata/a.davydov.xcuserdatad/xcschemes/xcschememanagement.plist @@ -2,7 +2,13 @@ - IDEDidComputeMac32BitWarning - + SchemeUserState + + OpenAPIClient.xcscheme_^#shared#^_ + + orderHint + 0 + + diff --git a/samples/client/petstore/swift-alt/Package.swift b/samples/client/petstore/swift-alt/Package.swift new file mode 100644 index 000000000000..7c13bd37717e --- /dev/null +++ b/samples/client/petstore/swift-alt/Package.swift @@ -0,0 +1,24 @@ +// swift-tools-version:5.1 + +import PackageDescription + +let package = Package( + name: "OpenAPIClient", + platforms: [ + .iOS(.v13) + ], + products: [ + .library( + name: "OpenAPIClient", + targets: ["OpenAPIClient"] + ), + ], + dependencies: [], + targets: [ + .target( + name: "OpenAPIClient", + dependencies: [], + path: "Sources" + ), + ] +) diff --git a/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/APIs/PetAPI.swift b/samples/client/petstore/swift-alt/Sources/APIs/PetAPI.swift similarity index 52% rename from samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/APIs/PetAPI.swift rename to samples/client/petstore/swift-alt/Sources/APIs/PetAPI.swift index 8511a33d2a36..bcd73cc532aa 100644 --- a/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/APIs/PetAPI.swift +++ b/samples/client/petstore/swift-alt/Sources/APIs/PetAPI.swift @@ -11,13 +11,13 @@ import Combine open class PetAPI { - private let encoder: JSONEncoder = { + private static let encoder: JSONEncoder = { let encoder = JSONEncoder() encoder.dateEncodingStrategy = .formatted(OpenISO8601DateFormatter()) encoder.outputFormatting = .prettyPrinted return encoder }() - private let decoder: JSONDecoder = { + private static let decoder: JSONDecoder = { let decoder = JSONDecoder() decoder.dateDecodingStrategy = .formatted(OpenISO8601DateFormatter()) return decoder @@ -35,9 +35,9 @@ open class PetAPI { - type: oauth2 - name: petstore_auth - parameter pet: (body) Pet object that needs to be added to the store - - returns: AnyPublisher, Never> + - returns: AnyPublisher */ - open func addPet(pet: Pet) -> AnyPublisher, Never> { + open func addPet(pet: Pet) -> AnyPublisher { // Creating final URL with query items and path var components = URLComponents() components.path = "/pet" @@ -50,20 +50,16 @@ open class PetAPI { request.httpMethod = "POST" // Setting body parameters - request.httpBody = try? encoder.encode(pet) + request.httpBody = try? PetAPI.encoder.encode(pet) + if request.value(forHTTPHeaderField: "Content-Type") == nil { + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + } + // Getting auth type - let securityScheme: SecurityScheme = .none - return transport.send(request: request, securityScheme: securityScheme) - .map { response -> Result in - if response.response?.statusCode == 200 { - if let data = response.data { - return Result { try self.decoder.decode(Pet.self, from: data) } - } else { - return .failure(TransportError.unknown) - } - } else { - return .failure(response.error ?? TransportError.unknown) - } + let securitySchemes: [SecurityScheme] = [] + return transport.send(request: request, securitySchemes: securitySchemes) + .tryMap { response in + try PetAPI.decoder.decode(Pet.self, from: response.data) } .eraseToAnyPublisher() } @@ -76,9 +72,9 @@ open class PetAPI { - name: petstore_auth - parameter petId: (path) Pet id to delete - parameter apiKey: (header) (optional) - - returns: AnyPublisher, Never> + - returns: AnyPublisher */ - open func deletePet(petId: Int64, apiKey: String? = nil) -> AnyPublisher, Never> { + open func deletePet(petId: Int64, apiKey: String? = nil) -> AnyPublisher { // Creating final URL with query items and path var components = URLComponents() components.path = "/pet/{petId}" @@ -96,14 +92,10 @@ open class PetAPI { ].compactMapValues { $0 } // Getting auth type - let securityScheme: SecurityScheme = .none - return transport.send(request: request, securityScheme: securityScheme) - .map { response -> Result in - if response.response?.statusCode == 200 { - return .success(()) - } else { - return .failure(response.error ?? TransportError.unknown) - } + let securitySchemes: [SecurityScheme] = [] + return transport.send(request: request, securitySchemes: securitySchemes) + .tryMap { response in + return () } .eraseToAnyPublisher() } @@ -116,9 +108,9 @@ open class PetAPI { - type: oauth2 - name: petstore_auth - parameter status: (query) Status values that need to be considered for filter - - returns: AnyPublisher, Never> + - returns: AnyPublisher<[Pet], Error> */ - open func findPetsByStatus(status: [String]) -> AnyPublisher, Never> { + open func findPetsByStatus(status: [String]) -> AnyPublisher<[Pet], Error> { // Creating final URL with query items and path var components = URLComponents() components.path = "/pet/findByStatus" @@ -134,18 +126,10 @@ open class PetAPI { // Getting auth type - let securityScheme: SecurityScheme = .none - return transport.send(request: request, securityScheme: securityScheme) - .map { response -> Result<[Pet], Error> in - if response.response?.statusCode == 200 { - if let data = response.data { - return Result { try self.decoder.decode([Pet].self, from: data) } - } else { - return .failure(TransportError.unknown) - } - } else { - return .failure(response.error ?? TransportError.unknown) - } + let securitySchemes: [SecurityScheme] = [] + return transport.send(request: request, securitySchemes: securitySchemes) + .tryMap { response in + try PetAPI.decoder.decode([Pet].self, from: response.data) } .eraseToAnyPublisher() } @@ -158,9 +142,9 @@ open class PetAPI { - type: oauth2 - name: petstore_auth - parameter tags: (query) Tags to filter by - - returns: AnyPublisher, Never> + - returns: AnyPublisher<[Pet], Error> */ - open func findPetsByTags(tags: [String]) -> AnyPublisher, Never> { + open func findPetsByTags(tags: [String]) -> AnyPublisher<[Pet], Error> { // Creating final URL with query items and path var components = URLComponents() components.path = "/pet/findByTags" @@ -176,18 +160,10 @@ open class PetAPI { // Getting auth type - let securityScheme: SecurityScheme = .none - return transport.send(request: request, securityScheme: securityScheme) - .map { response -> Result<[Pet], Error> in - if response.response?.statusCode == 200 { - if let data = response.data { - return Result { try self.decoder.decode([Pet].self, from: data) } - } else { - return .failure(TransportError.unknown) - } - } else { - return .failure(response.error ?? TransportError.unknown) - } + let securitySchemes: [SecurityScheme] = [] + return transport.send(request: request, securitySchemes: securitySchemes) + .tryMap { response in + try PetAPI.decoder.decode([Pet].self, from: response.data) } .eraseToAnyPublisher() } @@ -200,9 +176,9 @@ open class PetAPI { - type: apiKey api_key - name: api_key - parameter petId: (path) ID of pet to return - - returns: AnyPublisher, Never> + - returns: AnyPublisher */ - open func getPetById(petId: Int64) -> AnyPublisher, Never> { + open func getPetById(petId: Int64) -> AnyPublisher { // Creating final URL with query items and path var components = URLComponents() components.path = "/pet/{petId}" @@ -217,18 +193,10 @@ open class PetAPI { // Getting auth type - let securityScheme: SecurityScheme = .none - return transport.send(request: request, securityScheme: securityScheme) - .map { response -> Result in - if response.response?.statusCode == 200 { - if let data = response.data { - return Result { try self.decoder.decode(Pet.self, from: data) } - } else { - return .failure(TransportError.unknown) - } - } else { - return .failure(response.error ?? TransportError.unknown) - } + let securitySchemes: [SecurityScheme] = [] + return transport.send(request: request, securitySchemes: securitySchemes) + .tryMap { response in + try PetAPI.decoder.decode(Pet.self, from: response.data) } .eraseToAnyPublisher() } @@ -240,9 +208,9 @@ open class PetAPI { - type: oauth2 - name: petstore_auth - parameter pet: (body) Pet object that needs to be added to the store - - returns: AnyPublisher, Never> + - returns: AnyPublisher */ - open func updatePet(pet: Pet) -> AnyPublisher, Never> { + open func updatePet(pet: Pet) -> AnyPublisher { // Creating final URL with query items and path var components = URLComponents() components.path = "/pet" @@ -255,20 +223,16 @@ open class PetAPI { request.httpMethod = "PUT" // Setting body parameters - request.httpBody = try? encoder.encode(pet) + request.httpBody = try? PetAPI.encoder.encode(pet) + if request.value(forHTTPHeaderField: "Content-Type") == nil { + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + } + // Getting auth type - let securityScheme: SecurityScheme = .none - return transport.send(request: request, securityScheme: securityScheme) - .map { response -> Result in - if response.response?.statusCode == 200 { - if let data = response.data { - return Result { try self.decoder.decode(Pet.self, from: data) } - } else { - return .failure(TransportError.unknown) - } - } else { - return .failure(response.error ?? TransportError.unknown) - } + let securitySchemes: [SecurityScheme] = [] + return transport.send(request: request, securitySchemes: securitySchemes) + .tryMap { response in + try PetAPI.decoder.decode(Pet.self, from: response.data) } .eraseToAnyPublisher() } @@ -282,9 +246,9 @@ open class PetAPI { - parameter petId: (path) ID of pet that needs to be updated - parameter name: (form) Updated name of the pet (optional) - parameter status: (form) Updated status of the pet (optional) - - returns: AnyPublisher, Never> + - returns: AnyPublisher */ - open func updatePetWithForm(petId: Int64, name: String? = nil, status: String? = nil) -> AnyPublisher, Never> { + open func updatePetWithForm(petId: Int64, name: String? = nil, status: String? = nil) -> AnyPublisher { // Creating final URL with query items and path var components = URLComponents() components.path = "/pet/{petId}" @@ -299,14 +263,10 @@ open class PetAPI { // Getting auth type - let securityScheme: SecurityScheme = .none - return transport.send(request: request, securityScheme: securityScheme) - .map { response -> Result in - if response.response?.statusCode == 200 { - return .success(()) - } else { - return .failure(response.error ?? TransportError.unknown) - } + let securitySchemes: [SecurityScheme] = [] + return transport.send(request: request, securitySchemes: securitySchemes) + .tryMap { response in + return () } .eraseToAnyPublisher() } @@ -320,9 +280,9 @@ open class PetAPI { - parameter petId: (path) ID of pet to update - parameter additionalMetadata: (form) Additional data to pass to server (optional) - parameter file: (form) file to upload (optional) - - returns: AnyPublisher, Never> + - returns: AnyPublisher */ - open func uploadFile(petId: Int64, additionalMetadata: String? = nil, file: Data? = nil) -> AnyPublisher, Never> { + open func uploadFile(petId: Int64, additionalMetadata: String? = nil, file: Data? = nil) -> AnyPublisher { // Creating final URL with query items and path var components = URLComponents() components.path = "/pet/{petId}/uploadImage" @@ -337,55 +297,11 @@ open class PetAPI { // Getting auth type - let securityScheme: SecurityScheme = .none - return transport.send(request: request, securityScheme: securityScheme) - .map { response -> Result in - if response.response?.statusCode == 200 { - if let data = response.data { - return Result { try self.decoder.decode(ApiResponse.self, from: data) } - } else { - return .failure(TransportError.unknown) - } - } else { - return .failure(response.error ?? TransportError.unknown) - } + let securitySchemes: [SecurityScheme] = [] + return transport.send(request: request, securitySchemes: securitySchemes) + .tryMap { response in + try PetAPI.decoder.decode(ApiResponse.self, from: response.data) } .eraseToAnyPublisher() } } - - -private class OpenISO8601DateFormatter: DateFormatter { - static let withoutSeconds: DateFormatter = { - let formatter = DateFormatter() - formatter.calendar = Calendar(identifier: .iso8601) - formatter.locale = Locale(identifier: "en_US_POSIX") - formatter.timeZone = TimeZone(secondsFromGMT: 0) - formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ" - return formatter - }() - - private func setup() { - calendar = Calendar(identifier: .iso8601) - locale = Locale(identifier: "en_US_POSIX") - timeZone = TimeZone(secondsFromGMT: 0) - dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ" - } - - override init() { - super.init() - setup() - } - - required init?(coder aDecoder: NSCoder) { - super.init(coder: aDecoder) - setup() - } - - override func date(from string: String) -> Date? { - if let result = super.date(from: string) { - return result - } - return OpenISO8601DateFormatter.withoutSeconds.date(from: string) - } -} \ No newline at end of file diff --git a/samples/client/petstore/swift-alt/Sources/APIs/StoreAPI.swift b/samples/client/petstore/swift-alt/Sources/APIs/StoreAPI.swift new file mode 100644 index 000000000000..cb52b7622703 --- /dev/null +++ b/samples/client/petstore/swift-alt/Sources/APIs/StoreAPI.swift @@ -0,0 +1,154 @@ +// +// StoreAPI.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// Run in root folder to build example mvn clean package -DskipTests; ./bin/generate-samples.sh bin/configs/swift-alt-petstore-new.yaml + +import Foundation +import Combine +// import Runtime + + +open class StoreAPI { + private static let encoder: JSONEncoder = { + let encoder = JSONEncoder() + encoder.dateEncodingStrategy = .formatted(OpenISO8601DateFormatter()) + encoder.outputFormatting = .prettyPrinted + return encoder + }() + private static let decoder: JSONDecoder = { + let decoder = JSONDecoder() + decoder.dateDecodingStrategy = .formatted(OpenISO8601DateFormatter()) + return decoder + }() + private let transport: Transport + + public init(_ transport: Transport) { + self.transport = transport + } + + /** + Delete purchase order by ID + - DELETE /store/order/{orderId} + - For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors + - parameter orderId: (path) ID of the order that needs to be deleted + - returns: AnyPublisher + */ + open func deleteOrder(orderId: String) -> AnyPublisher { + // Creating final URL with query items and path + var components = URLComponents() + components.path = "/store/order/{orderId}" + .replacingOccurrences(of: "{orderId}", with: "\(orderId)") + + guard let url = components.url(relativeTo: transport.baseURL) else { + fatalError("URL is nil") + } + + var request = URLRequest(url: url) + request.httpMethod = "DELETE" + + + // Getting auth type + let securitySchemes: [SecurityScheme] = [] + return transport.send(request: request, securitySchemes: securitySchemes) + .tryMap { response in + return () + } + .eraseToAnyPublisher() + } + + /** + Returns pet inventories by status + - GET /store/inventory + - Returns a map of status codes to quantities + - API Key: + - type: apiKey api_key + - name: api_key + - returns: AnyPublisher<[String: Int], Error> + */ + open func getInventory() -> AnyPublisher<[String: Int], Error> { + // Creating final URL with query items and path + var components = URLComponents() + components.path = "/store/inventory" + + guard let url = components.url(relativeTo: transport.baseURL) else { + fatalError("URL is nil") + } + + var request = URLRequest(url: url) + request.httpMethod = "GET" + + + // Getting auth type + let securitySchemes: [SecurityScheme] = [] + return transport.send(request: request, securitySchemes: securitySchemes) + .tryMap { response in + try StoreAPI.decoder.decode([String: Int].self, from: response.data) + } + .eraseToAnyPublisher() + } + + /** + Find purchase order by ID + - GET /store/order/{orderId} + - For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions + - parameter orderId: (path) ID of pet that needs to be fetched + - returns: AnyPublisher + */ + open func getOrderById(orderId: Int64) -> AnyPublisher { + // Creating final URL with query items and path + var components = URLComponents() + components.path = "/store/order/{orderId}" + .replacingOccurrences(of: "{orderId}", with: "\(orderId)") + + guard let url = components.url(relativeTo: transport.baseURL) else { + fatalError("URL is nil") + } + + var request = URLRequest(url: url) + request.httpMethod = "GET" + + + // Getting auth type + let securitySchemes: [SecurityScheme] = [] + return transport.send(request: request, securitySchemes: securitySchemes) + .tryMap { response in + try StoreAPI.decoder.decode(Order.self, from: response.data) + } + .eraseToAnyPublisher() + } + + /** + Place an order for a pet + - POST /store/order + - parameter order: (body) order placed for purchasing the pet + - returns: AnyPublisher + */ + open func placeOrder(order: Order) -> AnyPublisher { + // Creating final URL with query items and path + var components = URLComponents() + components.path = "/store/order" + + guard let url = components.url(relativeTo: transport.baseURL) else { + fatalError("URL is nil") + } + + var request = URLRequest(url: url) + request.httpMethod = "POST" + + // Setting body parameters + request.httpBody = try? StoreAPI.encoder.encode(order) + if request.value(forHTTPHeaderField: "Content-Type") == nil { + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + } + + // Getting auth type + let securitySchemes: [SecurityScheme] = [] + return transport.send(request: request, securitySchemes: securitySchemes) + .tryMap { response in + try StoreAPI.decoder.decode(Order.self, from: response.data) + } + .eraseToAnyPublisher() + } +} diff --git a/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/APIs/UserAPI.swift b/samples/client/petstore/swift-alt/Sources/APIs/UserAPI.swift similarity index 54% rename from samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/APIs/UserAPI.swift rename to samples/client/petstore/swift-alt/Sources/APIs/UserAPI.swift index b533bd3f360d..91f075612c28 100644 --- a/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/APIs/UserAPI.swift +++ b/samples/client/petstore/swift-alt/Sources/APIs/UserAPI.swift @@ -11,13 +11,13 @@ import Combine open class UserAPI { - private let encoder: JSONEncoder = { + private static let encoder: JSONEncoder = { let encoder = JSONEncoder() encoder.dateEncodingStrategy = .formatted(OpenISO8601DateFormatter()) encoder.outputFormatting = .prettyPrinted return encoder }() - private let decoder: JSONDecoder = { + private static let decoder: JSONDecoder = { let decoder = JSONDecoder() decoder.dateDecodingStrategy = .formatted(OpenISO8601DateFormatter()) return decoder @@ -36,9 +36,9 @@ open class UserAPI { - type: apiKey api_key - name: api_key - parameter user: (body) Created user object - - returns: AnyPublisher, Never> + - returns: AnyPublisher */ - open func createUser(user: User) -> AnyPublisher, Never> { + open func createUser(user: User) -> AnyPublisher { // Creating final URL with query items and path var components = URLComponents() components.path = "/user" @@ -51,16 +51,16 @@ open class UserAPI { request.httpMethod = "POST" // Setting body parameters - request.httpBody = try? encoder.encode(user) + request.httpBody = try? UserAPI.encoder.encode(user) + if request.value(forHTTPHeaderField: "Content-Type") == nil { + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + } + // Getting auth type - let securityScheme: SecurityScheme = .none - return transport.send(request: request, securityScheme: securityScheme) - .map { response -> Result in - if response.response?.statusCode == 200 { - return .success(()) - } else { - return .failure(response.error ?? TransportError.unknown) - } + let securitySchemes: [SecurityScheme] = [] + return transport.send(request: request, securitySchemes: securitySchemes) + .tryMap { response in + return () } .eraseToAnyPublisher() } @@ -72,9 +72,9 @@ open class UserAPI { - type: apiKey api_key - name: api_key - parameter user: (body) List of user object - - returns: AnyPublisher, Never> + - returns: AnyPublisher */ - open func createUsersWithArrayInput(user: [User]) -> AnyPublisher, Never> { + open func createUsersWithArrayInput(user: [User]) -> AnyPublisher { // Creating final URL with query items and path var components = URLComponents() components.path = "/user/createWithArray" @@ -87,16 +87,16 @@ open class UserAPI { request.httpMethod = "POST" // Setting body parameters - request.httpBody = try? encoder.encode(user) + request.httpBody = try? UserAPI.encoder.encode(user) + if request.value(forHTTPHeaderField: "Content-Type") == nil { + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + } + // Getting auth type - let securityScheme: SecurityScheme = .none - return transport.send(request: request, securityScheme: securityScheme) - .map { response -> Result in - if response.response?.statusCode == 200 { - return .success(()) - } else { - return .failure(response.error ?? TransportError.unknown) - } + let securitySchemes: [SecurityScheme] = [] + return transport.send(request: request, securitySchemes: securitySchemes) + .tryMap { response in + return () } .eraseToAnyPublisher() } @@ -108,9 +108,9 @@ open class UserAPI { - type: apiKey api_key - name: api_key - parameter user: (body) List of user object - - returns: AnyPublisher, Never> + - returns: AnyPublisher */ - open func createUsersWithListInput(user: [User]) -> AnyPublisher, Never> { + open func createUsersWithListInput(user: [User]) -> AnyPublisher { // Creating final URL with query items and path var components = URLComponents() components.path = "/user/createWithList" @@ -123,16 +123,16 @@ open class UserAPI { request.httpMethod = "POST" // Setting body parameters - request.httpBody = try? encoder.encode(user) + request.httpBody = try? UserAPI.encoder.encode(user) + if request.value(forHTTPHeaderField: "Content-Type") == nil { + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + } + // Getting auth type - let securityScheme: SecurityScheme = .none - return transport.send(request: request, securityScheme: securityScheme) - .map { response -> Result in - if response.response?.statusCode == 200 { - return .success(()) - } else { - return .failure(response.error ?? TransportError.unknown) - } + let securitySchemes: [SecurityScheme] = [] + return transport.send(request: request, securitySchemes: securitySchemes) + .tryMap { response in + return () } .eraseToAnyPublisher() } @@ -145,9 +145,9 @@ open class UserAPI { - type: apiKey api_key - name: api_key - parameter username: (path) The name that needs to be deleted - - returns: AnyPublisher, Never> + - returns: AnyPublisher */ - open func deleteUser(username: String) -> AnyPublisher, Never> { + open func deleteUser(username: String) -> AnyPublisher { // Creating final URL with query items and path var components = URLComponents() components.path = "/user/{username}" @@ -162,14 +162,10 @@ open class UserAPI { // Getting auth type - let securityScheme: SecurityScheme = .none - return transport.send(request: request, securityScheme: securityScheme) - .map { response -> Result in - if response.response?.statusCode == 200 { - return .success(()) - } else { - return .failure(response.error ?? TransportError.unknown) - } + let securitySchemes: [SecurityScheme] = [] + return transport.send(request: request, securitySchemes: securitySchemes) + .tryMap { response in + return () } .eraseToAnyPublisher() } @@ -178,9 +174,9 @@ open class UserAPI { Get user by user name - GET /user/{username} - parameter username: (path) The name that needs to be fetched. Use user1 for testing. - - returns: AnyPublisher, Never> + - returns: AnyPublisher */ - open func getUserByName(username: String) -> AnyPublisher, Never> { + open func getUserByName(username: String) -> AnyPublisher { // Creating final URL with query items and path var components = URLComponents() components.path = "/user/{username}" @@ -195,18 +191,10 @@ open class UserAPI { // Getting auth type - let securityScheme: SecurityScheme = .none - return transport.send(request: request, securityScheme: securityScheme) - .map { response -> Result in - if response.response?.statusCode == 200 { - if let data = response.data { - return Result { try self.decoder.decode(User.self, from: data) } - } else { - return .failure(TransportError.unknown) - } - } else { - return .failure(response.error ?? TransportError.unknown) - } + let securitySchemes: [SecurityScheme] = [] + return transport.send(request: request, securitySchemes: securitySchemes) + .tryMap { response in + try UserAPI.decoder.decode(User.self, from: response.data) } .eraseToAnyPublisher() } @@ -217,9 +205,9 @@ open class UserAPI { - responseHeaders: [Set-Cookie(String), X-Rate-Limit(Int), X-Expires-After(Date)] - parameter username: (query) The user name for login - parameter password: (query) The password for login in clear text - - returns: AnyPublisher, Never> + - returns: AnyPublisher */ - open func loginUser(username: String, password: String) -> AnyPublisher, Never> { + open func loginUser(username: String, password: String) -> AnyPublisher { // Creating final URL with query items and path var components = URLComponents() components.path = "/user/login" @@ -236,18 +224,10 @@ open class UserAPI { // Getting auth type - let securityScheme: SecurityScheme = .none - return transport.send(request: request, securityScheme: securityScheme) - .map { response -> Result in - if response.response?.statusCode == 200 { - if let data = response.data { - return Result { try self.decoder.decode(String.self, from: data) } - } else { - return .failure(TransportError.unknown) - } - } else { - return .failure(response.error ?? TransportError.unknown) - } + let securitySchemes: [SecurityScheme] = [] + return transport.send(request: request, securitySchemes: securitySchemes) + .tryMap { response in + try UserAPI.decoder.decode(String.self, from: response.data) } .eraseToAnyPublisher() } @@ -258,9 +238,9 @@ open class UserAPI { - API Key: - type: apiKey api_key - name: api_key - - returns: AnyPublisher, Never> + - returns: AnyPublisher */ - open func logoutUser() -> AnyPublisher, Never> { + open func logoutUser() -> AnyPublisher { // Creating final URL with query items and path var components = URLComponents() components.path = "/user/logout" @@ -274,14 +254,10 @@ open class UserAPI { // Getting auth type - let securityScheme: SecurityScheme = .none - return transport.send(request: request, securityScheme: securityScheme) - .map { response -> Result in - if response.response?.statusCode == 200 { - return .success(()) - } else { - return .failure(response.error ?? TransportError.unknown) - } + let securitySchemes: [SecurityScheme] = [] + return transport.send(request: request, securitySchemes: securitySchemes) + .tryMap { response in + return () } .eraseToAnyPublisher() } @@ -295,9 +271,9 @@ open class UserAPI { - name: api_key - parameter username: (path) name that need to be deleted - parameter user: (body) Updated user object - - returns: AnyPublisher, Never> + - returns: AnyPublisher */ - open func updateUser(username: String, user: User) -> AnyPublisher, Never> { + open func updateUser(username: String, user: User) -> AnyPublisher { // Creating final URL with query items and path var components = URLComponents() components.path = "/user/{username}" @@ -311,53 +287,17 @@ open class UserAPI { request.httpMethod = "PUT" // Setting body parameters - request.httpBody = try? encoder.encode(user) + request.httpBody = try? UserAPI.encoder.encode(user) + if request.value(forHTTPHeaderField: "Content-Type") == nil { + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + } + // Getting auth type - let securityScheme: SecurityScheme = .none - return transport.send(request: request, securityScheme: securityScheme) - .map { response -> Result in - if response.response?.statusCode == 200 { - return .success(()) - } else { - return .failure(response.error ?? TransportError.unknown) - } + let securitySchemes: [SecurityScheme] = [] + return transport.send(request: request, securitySchemes: securitySchemes) + .tryMap { response in + return () } .eraseToAnyPublisher() } } - - -private class OpenISO8601DateFormatter: DateFormatter { - static let withoutSeconds: DateFormatter = { - let formatter = DateFormatter() - formatter.calendar = Calendar(identifier: .iso8601) - formatter.locale = Locale(identifier: "en_US_POSIX") - formatter.timeZone = TimeZone(secondsFromGMT: 0) - formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ" - return formatter - }() - - private func setup() { - calendar = Calendar(identifier: .iso8601) - locale = Locale(identifier: "en_US_POSIX") - timeZone = TimeZone(secondsFromGMT: 0) - dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ" - } - - override init() { - super.init() - setup() - } - - required init?(coder aDecoder: NSCoder) { - super.init(coder: aDecoder) - setup() - } - - override func date(from string: String) -> Date? { - if let result = super.date(from: string) { - return result - } - return OpenISO8601DateFormatter.withoutSeconds.date(from: string) - } -} \ No newline at end of file diff --git a/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/Models/ApiResponse.swift b/samples/client/petstore/swift-alt/Sources/Models/ApiResponse.swift similarity index 94% rename from samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/Models/ApiResponse.swift rename to samples/client/petstore/swift-alt/Sources/Models/ApiResponse.swift index 71946091f80a..b6098eb34a0e 100644 --- a/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/Models/ApiResponse.swift +++ b/samples/client/petstore/swift-alt/Sources/Models/ApiResponse.swift @@ -6,9 +6,6 @@ // import Foundation -#if canImport(AnyCodable) -import AnyCodable -#endif /** Describes the result of uploading an image resource */ diff --git a/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/Models/Category.swift b/samples/client/petstore/swift-alt/Sources/Models/Category.swift similarity index 93% rename from samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/Models/Category.swift rename to samples/client/petstore/swift-alt/Sources/Models/Category.swift index c826c6caf9b3..bbb2a6e804d8 100644 --- a/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/Models/Category.swift +++ b/samples/client/petstore/swift-alt/Sources/Models/Category.swift @@ -6,9 +6,6 @@ // import Foundation -#if canImport(AnyCodable) -import AnyCodable -#endif /** A category for a pet */ diff --git a/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/Models/Order.swift b/samples/client/petstore/swift-alt/Sources/Models/Order.swift similarity index 97% rename from samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/Models/Order.swift rename to samples/client/petstore/swift-alt/Sources/Models/Order.swift index e0744049ca9b..a6ace8325248 100644 --- a/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/Models/Order.swift +++ b/samples/client/petstore/swift-alt/Sources/Models/Order.swift @@ -6,9 +6,6 @@ // import Foundation -#if canImport(AnyCodable) -import AnyCodable -#endif /** An order for a pets from the pet store */ diff --git a/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/Models/Pet.swift b/samples/client/petstore/swift-alt/Sources/Models/Pet.swift similarity index 96% rename from samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/Models/Pet.swift rename to samples/client/petstore/swift-alt/Sources/Models/Pet.swift index c86438b0112c..0e8d2982cede 100644 --- a/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/Models/Pet.swift +++ b/samples/client/petstore/swift-alt/Sources/Models/Pet.swift @@ -6,9 +6,6 @@ // import Foundation -#if canImport(AnyCodable) -import AnyCodable -#endif /** A pet for sale in the pet store */ diff --git a/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/Models/Tag.swift b/samples/client/petstore/swift-alt/Sources/Models/Tag.swift similarity index 93% rename from samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/Models/Tag.swift rename to samples/client/petstore/swift-alt/Sources/Models/Tag.swift index 4724926e4a45..978e87f83195 100644 --- a/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/Models/Tag.swift +++ b/samples/client/petstore/swift-alt/Sources/Models/Tag.swift @@ -6,9 +6,6 @@ // import Foundation -#if canImport(AnyCodable) -import AnyCodable -#endif /** A tag for a pet */ diff --git a/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/Models/User.swift b/samples/client/petstore/swift-alt/Sources/Models/User.swift similarity index 97% rename from samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/Models/User.swift rename to samples/client/petstore/swift-alt/Sources/Models/User.swift index 2004d9296628..81b2ac916b2e 100644 --- a/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/Models/User.swift +++ b/samples/client/petstore/swift-alt/Sources/Models/User.swift @@ -6,9 +6,6 @@ // import Foundation -#if canImport(AnyCodable) -import AnyCodable -#endif /** A User who is purchasing from the pet store */ diff --git a/samples/client/petstore/swift-alt/Sources/Private/OpenISO8601DateFormatter.swift b/samples/client/petstore/swift-alt/Sources/Private/OpenISO8601DateFormatter.swift new file mode 100644 index 000000000000..aeb29f3767db --- /dev/null +++ b/samples/client/petstore/swift-alt/Sources/Private/OpenISO8601DateFormatter.swift @@ -0,0 +1,44 @@ +// +// OpenISO8601DateFormatter.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + +// https://stackoverflow.com/a/50281094/976628 +class OpenISO8601DateFormatter: DateFormatter { + static let withoutSeconds: DateFormatter = { + let formatter = DateFormatter() + formatter.calendar = Calendar(identifier: .iso8601) + formatter.locale = Locale(identifier: "en_US_POSIX") + formatter.timeZone = TimeZone(secondsFromGMT: 0) + formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ" + return formatter + }() + + private func setup() { + calendar = Calendar(identifier: .iso8601) + locale = Locale(identifier: "en_US_POSIX") + timeZone = TimeZone(secondsFromGMT: 0) + dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ" + } + + override init() { + super.init() + setup() + } + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + setup() + } + + override func date(from string: String) -> Date? { + if let result = super.date(from: string) { + return result + } + return OpenISO8601DateFormatter.withoutSeconds.date(from: string) + } +} diff --git a/samples/client/petstore/swift-alt/Sources/Runtime.swift b/samples/client/petstore/swift-alt/Sources/Runtime.swift new file mode 100644 index 000000000000..ca2874018cbc --- /dev/null +++ b/samples/client/petstore/swift-alt/Sources/Runtime.swift @@ -0,0 +1,135 @@ +// .swift +// +// Generated by openapi-generator +// https://openapi-generator.tech + +import Foundation +import Combine + +// MARK: - Open API Scheme + +public enum SecurityScheme { + case bearer + // Other schemes not supported yet https://swagger.io/docs/specification/authentication/ +} + +// MARK: - Authenticator + +public protocol Authenticator { + func authenticate(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher + func refresh() -> AnyPublisher +} + +/// Authenticator which does not authenticate requests and does not refresh it +open class EmptyAuthenticator: Authenticator { + public func authenticate(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher { + Just(request) + .setFailureType(to: Error.self) + .eraseToAnyPublisher() + } + + public func refresh() -> AnyPublisher { + Just(()) + .setFailureType(to: Error.self) + .eraseToAnyPublisher() + } + + public init() { + } +} + +// MARK: - Transport + +public protocol Transport { + var baseURL: URL { get } + func send(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher +} + +public struct TransportResponse { + public let data: Data + public let statusCode: Int +} + +public struct TransportError: Error { + public let data: Data + public let statusCode: Int + public let nestedError: Error? +} + +public extension TransportError { + // Impossible to add authentication headers to request + static let incorrectAuthenticationCode = 601 + // Error while refreshing authentication + static let failedAuthenticationRefreshCode = 602 + // There is no HTTP URL response + static let noResponseCode = 603 +} + +public protocol URLSessionTransportDelegate: AnyObject { + func willStart(request: URLRequest) + func didFinish(request: URLRequest, response: HTTPURLResponse?) +} + +open class URLSessionTransport: Transport { + private var cancellable = Set() + let session: URLSession + let authenticator: Authenticator + // Amount of time application will refresh authentication and try performing network call again + let authenticationRetryLimit = 1 + public let baseURL: URL + public weak var delegate: URLSessionTransportDelegate? + + public init(baseURL: URL, session: URLSession = .shared, authenticator: Authenticator = EmptyAuthenticator()) { + self.baseURL = baseURL + self.session = session + self.authenticator = authenticator + } + + open func send(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher { + send(request: request, securitySchemes: securitySchemes, triesLeft: authenticationRetryLimit) + } + + func send(request: URLRequest, securitySchemes: [SecurityScheme], triesLeft: Int) -> AnyPublisher { + authenticator + // Add authentication headers if needed before request + .authenticate(request: request, securitySchemes: securitySchemes) + .mapError { + TransportError(data: Data(), statusCode: TransportError.incorrectAuthenticationCode, nestedError: $0) + } + .flatMap { request -> AnyPublisher in + self.delegate?.willStart(request: request) + // Perform network call + return URLSession.shared.dataTaskPublisher(for: request) + .mapError { TransportError(data: Data(), statusCode: $0.code.rawValue, nestedError: nil) } + .flatMap { output -> AnyPublisher in + let response = output.response as? HTTPURLResponse + self.delegate?.didFinish(request: request, response: response) + switch response?.statusCode { + case .some(200): + let transportResponse = TransportResponse(data: output.data, statusCode: 200) + return Result.success(transportResponse).publisher.eraseToAnyPublisher() + case .some(401) where triesLeft > 0: + // Refresh authentication if possible + return self.authenticator + .refresh() + .mapError { + TransportError(data: Data(), statusCode: TransportError.failedAuthenticationRefreshCode, nestedError: $0) + } + .flatMap { + // Try performing network call again + self.send(request: request, securitySchemes: securitySchemes, triesLeft: triesLeft - 1) + } + .eraseToAnyPublisher() + case let .some(status): + let error = TransportError(data: output.data, statusCode: status, nestedError: nil) + return Fail(error: error).eraseToAnyPublisher() + default: + let error = TransportError(data: output.data, statusCode: TransportError.noResponseCode, nestedError: nil) + return Fail(error: error).eraseToAnyPublisher() + } + } + .eraseToAnyPublisher() + } + .eraseToAnyPublisher() + } +} diff --git a/samples/client/petstore/swift/alt/.openapi-generator/FILES b/samples/client/petstore/swift/alt/.openapi-generator/FILES deleted file mode 100644 index b1f9bb2cd593..000000000000 --- a/samples/client/petstore/swift/alt/.openapi-generator/FILES +++ /dev/null @@ -1,11 +0,0 @@ -OpenAPIClient/Classes/OpenAPIs/APIs/PetAPI.swift -OpenAPIClient/Classes/OpenAPIs/APIs/StoreAPI.swift -OpenAPIClient/Classes/OpenAPIs/APIs/UserAPI.swift -OpenAPIClient/Classes/OpenAPIs/Models/ApiResponse.swift -OpenAPIClient/Classes/OpenAPIs/Models/Category.swift -OpenAPIClient/Classes/OpenAPIs/Models/Order.swift -OpenAPIClient/Classes/OpenAPIs/Models/Pet.swift -OpenAPIClient/Classes/OpenAPIs/Models/Tag.swift -OpenAPIClient/Classes/OpenAPIs/Models/User.swift -Package.swift -project.yml diff --git a/samples/client/petstore/swift/alt/Info.plist b/samples/client/petstore/swift/alt/Info.plist deleted file mode 100644 index 323e5ecfc420..000000000000 --- a/samples/client/petstore/swift/alt/Info.plist +++ /dev/null @@ -1,22 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - FMWK - CFBundleShortVersionString - 1.0 - CFBundleVersion - 1 - - diff --git a/samples/client/petstore/swift/alt/OpenAPIClient.xcodeproj/project.pbxproj b/samples/client/petstore/swift/alt/OpenAPIClient.xcodeproj/project.pbxproj deleted file mode 100644 index 1f721253a4b6..000000000000 --- a/samples/client/petstore/swift/alt/OpenAPIClient.xcodeproj/project.pbxproj +++ /dev/null @@ -1,403 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 51; - objects = { - -/* Begin PBXBuildFile section */ - 07AD66F44F142A25134285D2 /* Tag.swift in Sources */ = {isa = PBXBuildFile; fileRef = 004F49F830DBCE73EE547625 /* Tag.swift */; }; - 2BD3B8D727271A1300E16037 /* Runtime.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2BD3B8D627271A1300E16037 /* Runtime.swift */; }; - 2BD3B8DA27271C7F00E16037 /* StoreAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2BD3B8D527270A5E00E16037 /* StoreAPI.swift */; }; - 2BD3B8DB27271C7F00E16037 /* UserAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2BD3B8D427270A5E00E16037 /* UserAPI.swift */; }; - 2BD3B8DC27271C7F00E16037 /* PetAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2BD3B8D327270A5E00E16037 /* PetAPI.swift */; }; - 5FDB83D7EF01DBFD3E8B6AD6 /* ApiResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F0D02E61CF4C58B24BC1581 /* ApiResponse.swift */; }; - 615F8910ABA037FBFA0BC09F /* User.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA84FDE7CC165FCEDC532CE0 /* User.swift */; }; - 8BB28EBA3F247E1FC0AEB946 /* Pet.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6443F80E261022596B8ABA4 /* Pet.swift */; }; - B3B33292169982AB380577B9 /* Category.swift in Sources */ = {isa = PBXBuildFile; fileRef = E99367F9F7013FFD55123670 /* Category.swift */; }; - D2051AFBDBA23137A85FCA3B /* Order.swift in Sources */ = {isa = PBXBuildFile; fileRef = 557E9F1F7D8EE8697FFC77CA /* Order.swift */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 004F49F830DBCE73EE547625 /* Tag.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tag.swift; sourceTree = ""; }; - 2BD3B8D327270A5E00E16037 /* PetAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PetAPI.swift; sourceTree = ""; }; - 2BD3B8D427270A5E00E16037 /* UserAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAPI.swift; sourceTree = ""; }; - 2BD3B8D527270A5E00E16037 /* StoreAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoreAPI.swift; sourceTree = ""; }; - 2BD3B8D627271A1300E16037 /* Runtime.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Runtime.swift; path = "../../../../../../../../modules/openapi-generator/src/main/resources/swift-alt/Runtime.swift"; sourceTree = ""; }; - 2BD3B8D827271B0300E16037 /* Old.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Old.swift; path = "../../../../../../../../modules/openapi-generator/src/main/resources/swift-alt/Old.swift"; sourceTree = ""; }; - 557E9F1F7D8EE8697FFC77CA /* Order.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Order.swift; sourceTree = ""; }; - 5A68201A010940B069E402C4 /* OpenAPIClient.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = OpenAPIClient.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 7F0D02E61CF4C58B24BC1581 /* ApiResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApiResponse.swift; sourceTree = ""; }; - 804F7195C2469F7D77EEA124 /* AnyCodable.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = AnyCodable.framework; sourceTree = ""; }; - D6443F80E261022596B8ABA4 /* Pet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Pet.swift; sourceTree = ""; }; - DA84FDE7CC165FCEDC532CE0 /* User.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = User.swift; sourceTree = ""; }; - E99367F9F7013FFD55123670 /* Category.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Category.swift; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 15E6C78D0C713DC56DE5E647 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 2BD3B8D227270A5E00E16037 /* APIs */ = { - isa = PBXGroup; - children = ( - 2BD3B8D327270A5E00E16037 /* PetAPI.swift */, - 2BD3B8D427270A5E00E16037 /* UserAPI.swift */, - 2BD3B8D527270A5E00E16037 /* StoreAPI.swift */, - ); - path = APIs; - sourceTree = ""; - }; - 531C2FA0FDC4145945B665DB /* Frameworks */ = { - isa = PBXGroup; - children = ( - 6DC4C6468A5F92971BE0F705 /* Carthage */, - ); - name = Frameworks; - sourceTree = ""; - }; - 58C164DF5107AE40B4ED3435 /* OpenAPIs */ = { - isa = PBXGroup; - children = ( - 2BD3B8D827271B0300E16037 /* Old.swift */, - 2BD3B8D627271A1300E16037 /* Runtime.swift */, - 2BD3B8D227270A5E00E16037 /* APIs */, - D3393B2ECC9C8AA58D9CC6B5 /* Models */, - ); - path = OpenAPIs; - sourceTree = ""; - }; - 6DC4C6468A5F92971BE0F705 /* Carthage */ = { - isa = PBXGroup; - children = ( - DC6DFE2BA49A9138D046C5C0 /* iOS */, - ); - name = Carthage; - path = Carthage/Build; - sourceTree = ""; - }; - 924C9AB67DF7BB7E7B243C8E = { - isa = PBXGroup; - children = ( - E1C55E9B3278648005177880 /* OpenAPIClient */, - 531C2FA0FDC4145945B665DB /* Frameworks */, - C93545A0873D7B9F1535DF32 /* Products */, - ); - sourceTree = ""; - }; - C93545A0873D7B9F1535DF32 /* Products */ = { - isa = PBXGroup; - children = ( - 5A68201A010940B069E402C4 /* OpenAPIClient.framework */, - ); - name = Products; - sourceTree = ""; - }; - D3393B2ECC9C8AA58D9CC6B5 /* Models */ = { - isa = PBXGroup; - children = ( - 7F0D02E61CF4C58B24BC1581 /* ApiResponse.swift */, - E99367F9F7013FFD55123670 /* Category.swift */, - 557E9F1F7D8EE8697FFC77CA /* Order.swift */, - D6443F80E261022596B8ABA4 /* Pet.swift */, - 004F49F830DBCE73EE547625 /* Tag.swift */, - DA84FDE7CC165FCEDC532CE0 /* User.swift */, - ); - path = Models; - sourceTree = ""; - }; - D88204A3BFDDC0BFD4278A5C /* Classes */ = { - isa = PBXGroup; - children = ( - 58C164DF5107AE40B4ED3435 /* OpenAPIs */, - ); - path = Classes; - sourceTree = ""; - }; - DC6DFE2BA49A9138D046C5C0 /* iOS */ = { - isa = PBXGroup; - children = ( - 804F7195C2469F7D77EEA124 /* AnyCodable.framework */, - ); - path = iOS; - sourceTree = ""; - }; - E1C55E9B3278648005177880 /* OpenAPIClient */ = { - isa = PBXGroup; - children = ( - D88204A3BFDDC0BFD4278A5C /* Classes */, - ); - path = OpenAPIClient; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 5D9D2D004FCC44CC7017F1A4 /* OpenAPIClient */ = { - isa = PBXNativeTarget; - buildConfigurationList = CF386033EEF5925F9C2E4094 /* Build configuration list for PBXNativeTarget "OpenAPIClient" */; - buildPhases = ( - 640E75056E1784D861D4EED4 /* Sources */, - 15E6C78D0C713DC56DE5E647 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = OpenAPIClient; - productName = OpenAPIClient; - productReference = 5A68201A010940B069E402C4 /* OpenAPIClient.framework */; - productType = "com.apple.product-type.framework"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - E9DEC8DB659CA753BD8ABDEC /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 1200; - }; - buildConfigurationList = 2579284DF1820817301E6542 /* Build configuration list for PBXProject "OpenAPIClient" */; - compatibilityVersion = "Xcode 10.0"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - Base, - en, - ); - mainGroup = 924C9AB67DF7BB7E7B243C8E; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 5D9D2D004FCC44CC7017F1A4 /* OpenAPIClient */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXSourcesBuildPhase section */ - 640E75056E1784D861D4EED4 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 2BD3B8DA27271C7F00E16037 /* StoreAPI.swift in Sources */, - 5FDB83D7EF01DBFD3E8B6AD6 /* ApiResponse.swift in Sources */, - B3B33292169982AB380577B9 /* Category.swift in Sources */, - D2051AFBDBA23137A85FCA3B /* Order.swift in Sources */, - 2BD3B8D727271A1300E16037 /* Runtime.swift in Sources */, - 8BB28EBA3F247E1FC0AEB946 /* Pet.swift in Sources */, - 07AD66F44F142A25134285D2 /* Tag.swift in Sources */, - 615F8910ABA037FBFA0BC09F /* User.swift in Sources */, - 2BD3B8DC27271C7F00E16037 /* PetAPI.swift in Sources */, - 2BD3B8DB27271C7F00E16037 /* UserAPI.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - 36800091FD978FBD6D1175B7 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - APPLICATION_EXTENSION_API_ONLY = YES; - CODE_SIGN_IDENTITY = ""; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/iOS", - ); - INFOPLIST_FILE = Info.plist; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 14.1; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Release; - }; - 59749DDA0BC81FD9808AC0E2 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "$(inherited)", - "DEBUG=1", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - ONLY_ACTIVE_ARCH = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = iphoneos; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - }; - name = Debug; - }; - C56D67BF2B255376EE156215 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MTL_ENABLE_DEBUG_INFO = NO; - MTL_FAST_MATH = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = iphoneos; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - SWIFT_VERSION = 5.0; - }; - name = Release; - }; - E341761E3A15E306F1C55FE0 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - APPLICATION_EXTENSION_API_ONLY = YES; - CODE_SIGN_IDENTITY = ""; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/iOS", - ); - INFOPLIST_FILE = Info.plist; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 14.1; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Debug; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 2579284DF1820817301E6542 /* Build configuration list for PBXProject "OpenAPIClient" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 59749DDA0BC81FD9808AC0E2 /* Debug */, - C56D67BF2B255376EE156215 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Debug; - }; - CF386033EEF5925F9C2E4094 /* Build configuration list for PBXNativeTarget "OpenAPIClient" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - E341761E3A15E306F1C55FE0 /* Debug */, - 36800091FD978FBD6D1175B7 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Debug; - }; -/* End XCConfigurationList section */ - }; - rootObject = E9DEC8DB659CA753BD8ABDEC /* Project object */; -} diff --git a/samples/client/petstore/swift/alt/OpenAPIClient.xcodeproj/project.xcworkspace/xcuserdata/a.davydov.xcuserdatad/UserInterfaceState.xcuserstate b/samples/client/petstore/swift/alt/OpenAPIClient.xcodeproj/project.xcworkspace/xcuserdata/a.davydov.xcuserdatad/UserInterfaceState.xcuserstate deleted file mode 100644 index 5984e04175053c6a950dc04580c3d2397d367cf5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 36691 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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/APIs/StoreAPI.swift b/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/APIs/StoreAPI.swift deleted file mode 100644 index d39da57c15eb..000000000000 --- a/samples/client/petstore/swift/alt/OpenAPIClient/Classes/OpenAPIs/APIs/StoreAPI.swift +++ /dev/null @@ -1,214 +0,0 @@ -// -// StoreAPI.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech -// Run in root folder to build example mvn clean package -DskipTests; ./bin/generate-samples.sh bin/configs/swift-alt-petstore-new.yaml - -import Foundation -import Combine -// import Runtime - - -open class StoreAPI { - private let encoder: JSONEncoder = { - let encoder = JSONEncoder() - encoder.dateEncodingStrategy = .formatted(OpenISO8601DateFormatter()) - encoder.outputFormatting = .prettyPrinted - return encoder - }() - private let decoder: JSONDecoder = { - let decoder = JSONDecoder() - decoder.dateDecodingStrategy = .formatted(OpenISO8601DateFormatter()) - return decoder - }() - private let transport: Transport - - public init(_ transport: Transport) { - self.transport = transport - } - - /** - Delete purchase order by ID - - DELETE /store/order/{orderId} - - For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors - - parameter orderId: (path) ID of the order that needs to be deleted - - returns: AnyPublisher, Never> - */ - open func deleteOrder(orderId: String) -> AnyPublisher, Never> { - // Creating final URL with query items and path - var components = URLComponents() - components.path = "/store/order/{orderId}" - .replacingOccurrences(of: "{orderId}", with: "\(orderId)") - - guard let url = components.url(relativeTo: transport.baseURL) else { - fatalError("URL is nil") - } - - var request = URLRequest(url: url) - request.httpMethod = "DELETE" - - - // Getting auth type - let securityScheme: SecurityScheme = .none - return transport.send(request: request, securityScheme: securityScheme) - .map { response -> Result in - if response.response?.statusCode == 200 { - return .success(()) - } else { - return .failure(response.error ?? TransportError.unknown) - } - } - .eraseToAnyPublisher() - } - - /** - Returns pet inventories by status - - GET /store/inventory - - Returns a map of status codes to quantities - - API Key: - - type: apiKey api_key - - name: api_key - - returns: AnyPublisher, Never> - */ - open func getInventory() -> AnyPublisher, Never> { - // Creating final URL with query items and path - var components = URLComponents() - components.path = "/store/inventory" - - guard let url = components.url(relativeTo: transport.baseURL) else { - fatalError("URL is nil") - } - - var request = URLRequest(url: url) - request.httpMethod = "GET" - - - // Getting auth type - let securityScheme: SecurityScheme = .none - return transport.send(request: request, securityScheme: securityScheme) - .map { response -> Result<[String: Int], Error> in - if response.response?.statusCode == 200 { - if let data = response.data { - return Result { try self.decoder.decode([String: Int].self, from: data) } - } else { - return .failure(TransportError.unknown) - } - } else { - return .failure(response.error ?? TransportError.unknown) - } - } - .eraseToAnyPublisher() - } - - /** - Find purchase order by ID - - GET /store/order/{orderId} - - For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions - - parameter orderId: (path) ID of pet that needs to be fetched - - returns: AnyPublisher, Never> - */ - open func getOrderById(orderId: Int64) -> AnyPublisher, Never> { - // Creating final URL with query items and path - var components = URLComponents() - components.path = "/store/order/{orderId}" - .replacingOccurrences(of: "{orderId}", with: "\(orderId)") - - guard let url = components.url(relativeTo: transport.baseURL) else { - fatalError("URL is nil") - } - - var request = URLRequest(url: url) - request.httpMethod = "GET" - - - // Getting auth type - let securityScheme: SecurityScheme = .none - return transport.send(request: request, securityScheme: securityScheme) - .map { response -> Result in - if response.response?.statusCode == 200 { - if let data = response.data { - return Result { try self.decoder.decode(Order.self, from: data) } - } else { - return .failure(TransportError.unknown) - } - } else { - return .failure(response.error ?? TransportError.unknown) - } - } - .eraseToAnyPublisher() - } - - /** - Place an order for a pet - - POST /store/order - - parameter order: (body) order placed for purchasing the pet - - returns: AnyPublisher, Never> - */ - open func placeOrder(order: Order) -> AnyPublisher, Never> { - // Creating final URL with query items and path - var components = URLComponents() - components.path = "/store/order" - - guard let url = components.url(relativeTo: transport.baseURL) else { - fatalError("URL is nil") - } - - var request = URLRequest(url: url) - request.httpMethod = "POST" - - // Setting body parameters - request.httpBody = try? encoder.encode(order) - // Getting auth type - let securityScheme: SecurityScheme = .none - return transport.send(request: request, securityScheme: securityScheme) - .map { response -> Result in - if response.response?.statusCode == 200 { - if let data = response.data { - return Result { try self.decoder.decode(Order.self, from: data) } - } else { - return .failure(TransportError.unknown) - } - } else { - return .failure(response.error ?? TransportError.unknown) - } - } - .eraseToAnyPublisher() - } -} - - -private class OpenISO8601DateFormatter: DateFormatter { - static let withoutSeconds: DateFormatter = { - let formatter = DateFormatter() - formatter.calendar = Calendar(identifier: .iso8601) - formatter.locale = Locale(identifier: "en_US_POSIX") - formatter.timeZone = TimeZone(secondsFromGMT: 0) - formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ" - return formatter - }() - - private func setup() { - calendar = Calendar(identifier: .iso8601) - locale = Locale(identifier: "en_US_POSIX") - timeZone = TimeZone(secondsFromGMT: 0) - dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ" - } - - override init() { - super.init() - setup() - } - - required init?(coder aDecoder: NSCoder) { - super.init(coder: aDecoder) - setup() - } - - override func date(from string: String) -> Date? { - if let result = super.date(from: string) { - return result - } - return OpenISO8601DateFormatter.withoutSeconds.date(from: string) - } -} \ No newline at end of file diff --git a/samples/client/petstore/swift/alt/Package.swift b/samples/client/petstore/swift/alt/Package.swift deleted file mode 100644 index d0919390cf6f..000000000000 --- a/samples/client/petstore/swift/alt/Package.swift +++ /dev/null @@ -1,33 +0,0 @@ -// swift-tools-version:5.1 - -import PackageDescription - -let package = Package( - name: "OpenAPIClient", - platforms: [ - .iOS(.v9), - .macOS(.v10_11), - .tvOS(.v9), - .watchOS(.v3), - ], - products: [ - // Products define the executables and libraries produced by a package, and make them visible to other packages. - .library( - name: "OpenAPIClient", - targets: ["OpenAPIClient"] - ), - ], - dependencies: [ - // Dependencies declare other packages that this package depends on. - .package(url: "https://github.com/Flight-School/AnyCodable", from: "0.6.1"), - ], - targets: [ - // Targets are the basic building blocks of a package. A target can define a module or a test suite. - // Targets can depend on other targets in this package, and on products in packages which this package depends on. - .target( - name: "OpenAPIClient", - dependencies: ["AnyCodable", ], - path: "OpenAPIClient/Classes" - ), - ] -) diff --git a/samples/client/petstore/swift/alt/README.md b/samples/client/petstore/swift/alt/README.md deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/samples/client/petstore/swift/alt/project.yml b/samples/client/petstore/swift/alt/project.yml deleted file mode 100644 index f9639e1cd247..000000000000 --- a/samples/client/petstore/swift/alt/project.yml +++ /dev/null @@ -1,15 +0,0 @@ -name: OpenAPIClient -targets: - OpenAPIClient: - type: framework - platform: iOS - deploymentTarget: "9.0" - sources: [OpenAPIClient] - info: - path: ./Info.plist - version: 1.0.0 - settings: - APPLICATION_EXTENSION_API_ONLY: true - scheme: {} - dependencies: - - carthage: AnyCodable From 446fa48660becd0eaf1151521c514dbdadccec46 Mon Sep 17 00:00:00 2001 From: Anton Davydov Date: Tue, 16 Nov 2021 12:05:08 +0300 Subject: [PATCH 05/33] swift-alt added example --- bin/configs/swift-alt-petstore-new.yaml | 3 +- .../languages/SwiftAltClientCodegen.java | 27 ++- .../swift-alt/OpenAPITransport.mustache | 229 ++++++++++++++++++ .../OpenAPITransportPackage.mustache | 25 ++ .../main/resources/swift-alt/Package.mustache | 7 +- .../main/resources/swift-alt/Runtime.mustache | 135 ----------- .../main/resources/swift-alt/Runtime.swift | 130 ---------- .../src/main/resources/swift-alt/api.mustache | 28 ++- samples/client/petstore/swift-alt/.gitignore | 64 +++++ .../swift-alt/.openapi-generator/FILES | 12 - .../contents.xcworkspacedata | 7 - .../UserInterfaceState.xcuserstate | Bin 16927 -> 0 bytes .../xcschemes/xcschememanagement.plist | 14 -- .../petstore/swift-alt/Sources/Runtime.swift | 135 ----------- .../{ => client}/.openapi-generator-ignore | 0 .../swift-alt/client/.openapi-generator/FILES | 13 + .../{ => client}/.openapi-generator/VERSION | 0 .../OpenAPITransport}/Package.swift | 11 +- .../Sources/OpenAPITransport.swift | 229 ++++++++++++++++++ .../client/PetstoreOpenAPI/Package.swift | 25 ++ .../Sources/APIs/PetAPI.swift | 148 +++++++---- .../Sources/APIs/StoreAPI.swift | 76 ++++-- .../Sources/APIs/UserAPI.swift | 146 +++++++---- .../Sources/Models/ApiResponse.swift | 0 .../Sources/Models/Category.swift | 0 .../Sources/Models/Order.swift | 0 .../PetstoreOpenAPI}/Sources/Models/Pet.swift | 0 .../PetstoreOpenAPI}/Sources/Models/Tag.swift | 0 .../Sources/Models/User.swift | 0 .../Private/OpenISO8601DateFormatter.swift | 0 .../petstore/swift-alt/tests/Package.swift | 19 ++ .../Sources/TestClientTests/PetAPITests.swift | 117 +++++++++ 32 files changed, 1021 insertions(+), 579 deletions(-) create mode 100644 modules/openapi-generator/src/main/resources/swift-alt/OpenAPITransport.mustache create mode 100644 modules/openapi-generator/src/main/resources/swift-alt/OpenAPITransportPackage.mustache delete mode 100644 modules/openapi-generator/src/main/resources/swift-alt/Runtime.mustache delete mode 100644 modules/openapi-generator/src/main/resources/swift-alt/Runtime.swift create mode 100644 samples/client/petstore/swift-alt/.gitignore delete mode 100644 samples/client/petstore/swift-alt/.openapi-generator/FILES delete mode 100644 samples/client/petstore/swift-alt/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata delete mode 100644 samples/client/petstore/swift-alt/.swiftpm/xcode/package.xcworkspace/xcuserdata/a.davydov.xcuserdatad/UserInterfaceState.xcuserstate delete mode 100644 samples/client/petstore/swift-alt/.swiftpm/xcode/xcuserdata/a.davydov.xcuserdatad/xcschemes/xcschememanagement.plist delete mode 100644 samples/client/petstore/swift-alt/Sources/Runtime.swift rename samples/client/petstore/swift-alt/{ => client}/.openapi-generator-ignore (100%) create mode 100644 samples/client/petstore/swift-alt/client/.openapi-generator/FILES rename samples/client/petstore/swift-alt/{ => client}/.openapi-generator/VERSION (100%) rename samples/client/petstore/swift-alt/{ => client/OpenAPITransport}/Package.swift (59%) create mode 100644 samples/client/petstore/swift-alt/client/OpenAPITransport/Sources/OpenAPITransport.swift create mode 100644 samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Package.swift rename samples/client/petstore/swift-alt/{ => client/PetstoreOpenAPI}/Sources/APIs/PetAPI.swift (64%) rename samples/client/petstore/swift-alt/{ => client/PetstoreOpenAPI}/Sources/APIs/StoreAPI.swift (63%) rename samples/client/petstore/swift-alt/{ => client/PetstoreOpenAPI}/Sources/APIs/UserAPI.swift (63%) rename samples/client/petstore/swift-alt/{ => client/PetstoreOpenAPI}/Sources/Models/ApiResponse.swift (100%) rename samples/client/petstore/swift-alt/{ => client/PetstoreOpenAPI}/Sources/Models/Category.swift (100%) rename samples/client/petstore/swift-alt/{ => client/PetstoreOpenAPI}/Sources/Models/Order.swift (100%) rename samples/client/petstore/swift-alt/{ => client/PetstoreOpenAPI}/Sources/Models/Pet.swift (100%) rename samples/client/petstore/swift-alt/{ => client/PetstoreOpenAPI}/Sources/Models/Tag.swift (100%) rename samples/client/petstore/swift-alt/{ => client/PetstoreOpenAPI}/Sources/Models/User.swift (100%) rename samples/client/petstore/swift-alt/{ => client/PetstoreOpenAPI}/Sources/Private/OpenISO8601DateFormatter.swift (100%) create mode 100644 samples/client/petstore/swift-alt/tests/Package.swift create mode 100644 samples/client/petstore/swift-alt/tests/Sources/TestClientTests/PetAPITests.swift diff --git a/bin/configs/swift-alt-petstore-new.yaml b/bin/configs/swift-alt-petstore-new.yaml index 97e9a9c027dc..d8d88889e1a7 100644 --- a/bin/configs/swift-alt-petstore-new.yaml +++ b/bin/configs/swift-alt-petstore-new.yaml @@ -1,6 +1,7 @@ generatorName: swift-alt -outputDir: samples/client/petstore/swift-alt +outputDir: samples/client/petstore/swift-alt/client inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml templateDir: modules/openapi-generator/src/main/resources/swift-alt additionalProperties: hideGenerationTimestamp: "true" + projectName: "PetstoreOpenAPI" diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java index cac4d0690f93..fa3a6760d7fa 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java @@ -49,6 +49,7 @@ public class SwiftAltClientCodegen extends DefaultCodegen implements CodegenConf protected String projectName = "OpenAPIClient"; protected String privateFolder = "Sources/Private"; protected String sourceFolder = "Sources"; + protected String transportFolder = "OpenAPITransport"; /** * Constructor for the swift alt language codegen module. @@ -64,15 +65,6 @@ public SwiftAltClientCodegen() { outputFolder = "generated-code" + File.separator + "swift"; modelTemplateFiles.put("model.mustache", ".swift"); apiTemplateFiles.put("api.mustache", ".swift"); - supportingFiles.add(new SupportingFile("Package.mustache", - "", - "Package.swift")); - supportingFiles.add(new SupportingFile("Runtime.mustache", - sourceFolder, - "Runtime.swift")); - supportingFiles.add(new SupportingFile("OpenISO8601DateFormatter.mustache", - privateFolder, - "OpenISO8601DateFormatter.swift")); embeddedTemplateDir = templateDir = "swift-alt"; apiPackage = File.separator + "APIs"; modelPackage = File.separator + "Models"; @@ -284,6 +276,19 @@ public void processOpts() { } else { additionalProperties.put(PROJECT_NAME, projectName); } + + supportingFiles.add(new SupportingFile("Package.mustache", + projectName, + "Package.swift")); + supportingFiles.add(new SupportingFile("OpenAPITransportPackage.mustache", + transportFolder, + "Package.swift")); + supportingFiles.add(new SupportingFile("OpenAPITransport.mustache", + transportFolder + File.separator + sourceFolder, + "OpenAPITransport.swift")); + supportingFiles.add(new SupportingFile("OpenISO8601DateFormatter.mustache", + projectName + File.separator + privateFolder, + "OpenISO8601DateFormatter.swift")); } @Override @@ -293,13 +298,13 @@ protected boolean isReservedWord(String word) { @Override public String modelFileFolder() { - return outputFolder + File.separator + sourceFolder + return outputFolder + File.separator + projectName + File.separator + sourceFolder + modelPackage().replace('.', File.separatorChar); } @Override public String apiFileFolder() { - return outputFolder + File.separator + sourceFolder + return outputFolder + File.separator + projectName + File.separator + sourceFolder + apiPackage().replace('.', File.separatorChar); } diff --git a/modules/openapi-generator/src/main/resources/swift-alt/OpenAPITransport.mustache b/modules/openapi-generator/src/main/resources/swift-alt/OpenAPITransport.mustache new file mode 100644 index 000000000000..7524071a95aa --- /dev/null +++ b/modules/openapi-generator/src/main/resources/swift-alt/OpenAPITransport.mustache @@ -0,0 +1,229 @@ +// OpenAPITransport.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech + +import Foundation +import Combine + +// MARK: - Open API Scheme + +public enum SecurityScheme { + case bearer + // Other schemes not supported yet https://swagger.io/docs/specification/authentication/ +} + +// MARK: - Authenticator + +public protocol Authenticator { + func authenticate(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher + func refresh(securitySchemes: [SecurityScheme]) -> AnyPublisher +} + +/// Authenticator which does not authenticate requests and does not refresh it +open class EmptyAuthenticator: Authenticator { + public func authenticate(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher { + Just(request) + .setFailureType(to: Error.self) + .eraseToAnyPublisher() + } + + public func refresh(securitySchemes: [SecurityScheme]) -> AnyPublisher { + Just(()) + .setFailureType(to: Error.self) + .eraseToAnyPublisher() + } + + public init() { + } +} + +// MARK: - OpenAPITransport + +public protocol OpenAPITransport { + var baseURL: URL? { get } + + func send( + request: URLRequest, + securitySchemes: [SecurityScheme] + ) -> AnyPublisher + + func cancelAll() +} + +public struct OpenAPITransportResponse { + public let data: Data + public let statusCode: Int + + public init(data: Data, statusCode: Int) { + self.data = data + self.statusCode = statusCode + } +} + +public struct OpenAPITransportError: Error, CustomStringConvertible, LocalizedError { + public let statusCode: Int + public let description: String + public let errorDescription: String? + // It might be source network error + public let nestedError: Error? + // Data may contain additional reason info (like json payload) + public let data: Data + + public init( + statusCode: Int, + description: String? = nil, + errorDescription: String? = nil, + nestedError: Error? = nil, + data: Data = Data() + ) { + self.statusCode = statusCode + self.errorDescription = errorDescription + self.nestedError = nestedError + self.data = data + if let description = description { + self.description = description + } else { + var summary = "OpenAPITransportError with status \(statusCode)" + if let nestedError = nestedError { + summary.append(contentsOf: ", \(nestedError.localizedDescription)") + } + self.description = summary + } + } +} + +// Custom transport errors. It begins with 6.. not to conflict with HTTP codes (it begins with 5..) +public extension OpenAPITransportError { + static let incorrectAuthenticationCode = 600 + static func incorrectAuthenticationError(_ nestedError: Error? = nil) -> OpenAPITransportError { + OpenAPITransportError( + statusCode: OpenAPITransportError.incorrectAuthenticationCode, + description: "Impossible to add authentication headers to request", + errorDescription: NSLocalizedString( + "Impossible to add authentication headers to request", + comment: "Incorrect authentication" + ), + nestedError: nestedError + ) + } + + static let failedAuthenticationRefreshCode = 601 + static func failedAuthenticationRefreshError(_ nestedError: Error? = nil) -> OpenAPITransportError { + OpenAPITransportError( + statusCode: OpenAPITransportError.failedAuthenticationRefreshCode, + description: "Error while refreshing authentication", + errorDescription: NSLocalizedString( + "Error while refreshing authentication", + comment: "Failed authentication refresh" + ), + nestedError: nestedError + ) + } + + static let noResponseCode = 603 + static func noResponseError(_ nestedError: Error? = nil) -> OpenAPITransportError { + OpenAPITransportError( + statusCode: OpenAPITransportError.noResponseCode, + description: "There is no HTTP URL response", + errorDescription: NSLocalizedString( + "There is no HTTP URL response", + comment: "No response" + ), + nestedError: nestedError + ) + } + + static let badURLCode = 604 + static func badURLError(_ nestedError: Error? = nil) -> OpenAPITransportError { + OpenAPITransportError( + statusCode: OpenAPITransportError.badURLCode, + description: "Request URL cannot be created with given parameters", + errorDescription: NSLocalizedString( + "Request URL cannot be created with given parameters", + comment: "Bad URL" + ), + nestedError: nestedError + ) + } +} + +public protocol URLSessionOpenAPITransportDelegate: AnyObject { + func willStart(request: URLRequest) + func didFinish(request: URLRequest, response: HTTPURLResponse?) +} + +open class URLSessionOpenAPITransport: OpenAPITransport { + private var cancellable = Set() + let session: URLSession + let authenticator: Authenticator + // Amount of time application will refresh authentication and try performing network call again + let authenticationRetryLimit = 1 + public let baseURL: URL? + public weak var delegate: URLSessionOpenAPITransportDelegate? + + public init(baseURL: URL? = nil, session: URLSession = .shared, authenticator: Authenticator = EmptyAuthenticator()) { + self.baseURL = baseURL + self.session = session + self.authenticator = authenticator + } + + open func send( + request: URLRequest, + securitySchemes: [SecurityScheme] + ) -> AnyPublisher { + send(request: request, securitySchemes: securitySchemes, triesLeft: authenticationRetryLimit) + } + + open func cancelAll() { + cancellable.removeAll() + } + + func send( + request: URLRequest, + securitySchemes: [SecurityScheme], + triesLeft: Int + ) -> AnyPublisher { + authenticator + // Add authentication headers if needed before request + .authenticate(request: request, securitySchemes: securitySchemes) + .mapError { + OpenAPITransportError.incorrectAuthenticationError($0) + } + .flatMap { request -> AnyPublisher in + self.delegate?.willStart(request: request) + // Perform network call + return URLSession.shared.dataTaskPublisher(for: request) + .mapError { OpenAPITransportError(statusCode: $0.code.rawValue, description: "Network call finished fails") } + .flatMap { output -> AnyPublisher in + let response = output.response as? HTTPURLResponse + self.delegate?.didFinish(request: request, response: response) + switch response?.statusCode { + case .some(200): + let OpenAPITransportResponse = OpenAPITransportResponse(data: output.data, statusCode: 200) + return Result.success(OpenAPITransportResponse).publisher.eraseToAnyPublisher() + case .some(401) where triesLeft > 0: + // Refresh authentication if possible + return self.authenticator + .refresh(securitySchemes: securitySchemes) + .mapError { + OpenAPITransportError.failedAuthenticationRefreshError($0) + } + .flatMap { + // Try performing network call again + self.send(request: request, securitySchemes: securitySchemes, triesLeft: triesLeft - 1) + } + .eraseToAnyPublisher() + case let .some(status): + let error = OpenAPITransportError(statusCode: status, data: output.data) + return Fail(error: error).eraseToAnyPublisher() + default: + let error = OpenAPITransportError(statusCode: OpenAPITransportError.noResponseCode, data: output.data) + return Fail(error: error).eraseToAnyPublisher() + } + } + .eraseToAnyPublisher() + } + .eraseToAnyPublisher() + } +} diff --git a/modules/openapi-generator/src/main/resources/swift-alt/OpenAPITransportPackage.mustache b/modules/openapi-generator/src/main/resources/swift-alt/OpenAPITransportPackage.mustache new file mode 100644 index 000000000000..916f6dfd64d0 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/swift-alt/OpenAPITransportPackage.mustache @@ -0,0 +1,25 @@ +// swift-tools-version:5.1 + +import PackageDescription + +let package = Package( + name: "OpenAPITransport", + platforms: [ + .iOS(.v13), + .macOS(.v10_15) + ], + products: [ + .library( + name: "OpenAPITransport", + targets: ["OpenAPITransport"] + ), + ], + dependencies: [], + targets: [ + .target( + name: "OpenAPITransport", + dependencies: [], + path: "Sources" + ), + ] +) diff --git a/modules/openapi-generator/src/main/resources/swift-alt/Package.mustache b/modules/openapi-generator/src/main/resources/swift-alt/Package.mustache index 17d896260a3c..c1cc2a5f3a77 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/Package.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/Package.mustache @@ -5,7 +5,8 @@ import PackageDescription let package = Package( name: "{{projectName}}", platforms: [ - .iOS(.v13) + .iOS(.v13), + .macOS(.v10_15) ], products: [ .library( @@ -13,11 +14,11 @@ let package = Package( targets: ["{{projectName}}"] ), ], - dependencies: [], + dependencies: [.package(path: "../OpenAPITransport")], targets: [ .target( name: "{{projectName}}", - dependencies: [], + dependencies: [.byName(name: "OpenAPITransport")], path: "Sources" ), ] diff --git a/modules/openapi-generator/src/main/resources/swift-alt/Runtime.mustache b/modules/openapi-generator/src/main/resources/swift-alt/Runtime.mustache deleted file mode 100644 index 0be8580bdf85..000000000000 --- a/modules/openapi-generator/src/main/resources/swift-alt/Runtime.mustache +++ /dev/null @@ -1,135 +0,0 @@ -// {{classname}}.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech - -import Foundation -import Combine - -// MARK: - Open API Scheme - -public enum SecurityScheme { - case bearer - // Other schemes not supported yet https://swagger.io/docs/specification/authentication/ -} - -// MARK: - Authenticator - -public protocol Authenticator { - func authenticate(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher - func refresh() -> AnyPublisher -} - -/// Authenticator which does not authenticate requests and does not refresh it -open class EmptyAuthenticator: Authenticator { - public func authenticate(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher { - Just(request) - .setFailureType(to: Error.self) - .eraseToAnyPublisher() - } - - public func refresh() -> AnyPublisher { - Just(()) - .setFailureType(to: Error.self) - .eraseToAnyPublisher() - } - - public init() { - } -} - -// MARK: - Transport - -public protocol Transport { - var baseURL: URL { get } - func send(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher -} - -public struct TransportResponse { - public let data: Data - public let statusCode: Int -} - -public struct TransportError: Error { - public let data: Data - public let statusCode: Int - public let nestedError: Error? -} - -public extension TransportError { - // Impossible to add authentication headers to request - static let incorrectAuthenticationCode = 601 - // Error while refreshing authentication - static let failedAuthenticationRefreshCode = 602 - // There is no HTTP URL response - static let noResponseCode = 603 -} - -public protocol URLSessionTransportDelegate: AnyObject { - func willStart(request: URLRequest) - func didFinish(request: URLRequest, response: HTTPURLResponse?) -} - -open class URLSessionTransport: Transport { - private var cancellable = Set() - let session: URLSession - let authenticator: Authenticator - // Amount of time application will refresh authentication and try performing network call again - let authenticationRetryLimit = 1 - public let baseURL: URL - public weak var delegate: URLSessionTransportDelegate? - - public init(baseURL: URL, session: URLSession = .shared, authenticator: Authenticator = EmptyAuthenticator()) { - self.baseURL = baseURL - self.session = session - self.authenticator = authenticator - } - - open func send(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher { - send(request: request, securitySchemes: securitySchemes, triesLeft: authenticationRetryLimit) - } - - func send(request: URLRequest, securitySchemes: [SecurityScheme], triesLeft: Int) -> AnyPublisher { - authenticator - // Add authentication headers if needed before request - .authenticate(request: request, securitySchemes: securitySchemes) - .mapError { - TransportError(data: Data(), statusCode: TransportError.incorrectAuthenticationCode, nestedError: $0) - } - .flatMap { request -> AnyPublisher in - self.delegate?.willStart(request: request) - // Perform network call - return URLSession.shared.dataTaskPublisher(for: request) - .mapError { TransportError(data: Data(), statusCode: $0.code.rawValue, nestedError: nil) } - .flatMap { output -> AnyPublisher in - let response = output.response as? HTTPURLResponse - self.delegate?.didFinish(request: request, response: response) - switch response?.statusCode { - case .some(200): - let transportResponse = TransportResponse(data: output.data, statusCode: 200) - return Result.success(transportResponse).publisher.eraseToAnyPublisher() - case .some(401) where triesLeft > 0: - // Refresh authentication if possible - return self.authenticator - .refresh() - .mapError { - TransportError(data: Data(), statusCode: TransportError.failedAuthenticationRefreshCode, nestedError: $0) - } - .flatMap { - // Try performing network call again - self.send(request: request, securitySchemes: securitySchemes, triesLeft: triesLeft - 1) - } - .eraseToAnyPublisher() - case let .some(status): - let error = TransportError(data: output.data, statusCode: status, nestedError: nil) - return Fail(error: error).eraseToAnyPublisher() - default: - let error = TransportError(data: output.data, statusCode: TransportError.noResponseCode, nestedError: nil) - return Fail(error: error).eraseToAnyPublisher() - } - } - .eraseToAnyPublisher() - } - .eraseToAnyPublisher() - } -} diff --git a/modules/openapi-generator/src/main/resources/swift-alt/Runtime.swift b/modules/openapi-generator/src/main/resources/swift-alt/Runtime.swift deleted file mode 100644 index fde484e4c94f..000000000000 --- a/modules/openapi-generator/src/main/resources/swift-alt/Runtime.swift +++ /dev/null @@ -1,130 +0,0 @@ -import Foundation -import Combine - -// MARK: - Open API Scheme - -public enum SecurityScheme { - case bearer - // Other schemes not supported yet https://swagger.io/docs/specification/authentication/ -} - -// MARK: - Authenticator - -public protocol Authenticator { - func authenticate(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher - func refresh() -> AnyPublisher -} - -/// Authenticator which does not authenticate requests and does not refresh it -open class EmptyAuthenticator: Authenticator { - public func authenticate(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher { - Just(request) - .setFailureType(to: Error.self) - .eraseToAnyPublisher() - } - - public func refresh() -> AnyPublisher { - Just(()) - .setFailureType(to: Error.self) - .eraseToAnyPublisher() - } - - public init() { - } -} - -// MARK: - Transport - -public protocol Transport { - var baseURL: URL { get } - func send(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher -} - -public struct TransportResponse { - public let data: Data - public let statusCode: Int -} - -public struct TransportError: Error { - public let data: Data - public let statusCode: Int - public let nestedError: Error? -} - -public extension TransportError { - // Impossible to add authentication headers to request - static let incorrectAuthenticationCode = 601 - // Error while refreshing authentication - static let failedAuthenticationRefreshCode = 602 - // There is no HTTP URL response - static let noResponseCode = 603 -} - -public protocol URLSessionTransportDelegate: AnyObject { - func willStart(request: URLRequest) - func didFinish(request: URLRequest, response: HTTPURLResponse?) -} - -open class URLSessionTransport: Transport { - private var cancellable = Set() - let session: URLSession - let authenticator: Authenticator - // Amount of time application will refresh authentication and try performing network call again - let authenticationRetryLimit = 1 - public let baseURL: URL - public weak var delegate: URLSessionTransportDelegate? - - public init(baseURL: URL, session: URLSession = .shared, authenticator: Authenticator = EmptyAuthenticator()) { - self.baseURL = baseURL - self.session = session - self.authenticator = authenticator - } - - open func send(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher { - send(request: request, securitySchemes: securitySchemes, triesLeft: authenticationRetryLimit) - } - - func send(request: URLRequest, securitySchemes: [SecurityScheme], triesLeft: Int) -> AnyPublisher { - authenticator - // Add authentication headers if needed before request - .authenticate(request: request, securitySchemes: securitySchemes) - .mapError { - TransportError(data: Data(), statusCode: TransportError.incorrectAuthenticationCode, nestedError: $0) - } - .flatMap { request -> AnyPublisher in - self.delegate?.willStart(request: request) - // Perform network call - return URLSession.shared.dataTaskPublisher(for: request) - .mapError { TransportError(data: Data(), statusCode: $0.code.rawValue, nestedError: nil) } - .flatMap { output -> AnyPublisher in - let response = output.response as? HTTPURLResponse - self.delegate?.didFinish(request: request, response: response) - switch response?.statusCode { - case .some(200): - let transportResponse = TransportResponse(data: output.data, statusCode: 200) - return Result.success(transportResponse).publisher.eraseToAnyPublisher() - case .some(401) where triesLeft > 0: - // Refresh authentication if possible - return self.authenticator - .refresh() - .mapError { - TransportError(data: Data(), statusCode: TransportError.failedAuthenticationRefreshCode, nestedError: $0) - } - .flatMap { - // Try performing network call again - self.send(request: request, securitySchemes: securitySchemes, triesLeft: triesLeft - 1) - } - .eraseToAnyPublisher() - case let .some(status): - let error = TransportError(data: output.data, statusCode: status, nestedError: nil) - return Fail(error: error).eraseToAnyPublisher() - default: - let error = TransportError(data: output.data, statusCode: TransportError.noResponseCode, nestedError: nil) - return Fail(error: error).eraseToAnyPublisher() - } - } - .eraseToAnyPublisher() - } - .eraseToAnyPublisher() - } -} diff --git a/modules/openapi-generator/src/main/resources/swift-alt/api.mustache b/modules/openapi-generator/src/main/resources/swift-alt/api.mustache index d0b29519e378..b33e966a4df0 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/api.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/api.mustache @@ -3,11 +3,10 @@ // // Generated by openapi-generator // https://openapi-generator.tech -// Run in root folder to build example mvn clean package -DskipTests; ./bin/generate-samples.sh bin/configs/swift-alt-petstore-new.yaml import Foundation import Combine -// import Runtime +import OpenAPITransport {{#description}} /** {{{.}}} */{{/description}} @@ -23,9 +22,10 @@ open class {{classname}} { decoder.dateDecodingStrategy = .formatted(OpenISO8601DateFormatter()) return decoder }() - private let transport: Transport + private let transport: OpenAPITransport + public let baseURL = URL(string: "{{{basePath}}}") - public init(_ transport: Transport) { + public init(_ transport: OpenAPITransport) { self.transport = transport } {{#operation}} @@ -56,24 +56,30 @@ open class {{classname}} { */ open func {{operationId}}({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}) -> AnyPublisher<{{{returnType}}}{{^returnType}}Void{{/returnType}}, Error> { // Creating final URL with query items and path - var components = URLComponents() - components.path = "{{path}}" + guard let baseURL = transport.baseURL ?? self.baseURL else { + return Fail(error: OpenAPITransportError.badURLError()) + .eraseToAnyPublisher() + } + + let path = "{{path}}" {{#pathParams}} {{! TODO: Convert param name to string if needed (can be nil, can be container) }} .replacingOccurrences(of: "{{=<% %>=}}{<%baseName%>}<%={{ }}=%>", with: "\({{paramName}})") {{/pathParams}} - {{#hasQueryParams}}components.queryItems = [ + let url = baseURL.appendingPathComponent(path) + {{#hasQueryParams}}var{{/hasQueryParams}}{{^hasQueryParams}}let{{/hasQueryParams}} components = URLComponents(url: url, resolvingAgainstBaseURL: false) + {{#hasQueryParams}}components?.queryItems = [ {{#queryParams}} {{! TODO: Convert value to string if needed (can be nil, can be container) }} URLQueryItem(name: "{{paramName}}", value: {{#isArray}}{{paramName}}{{^required}}?{{/required}}.joined(separator: ", "){{/isArray}}{{^isArray}}{{paramName}}{{/isArray}}){{^-last}}, {{/-last}} {{/queryParams}} ]{{/hasQueryParams}} - guard let url = components.url(relativeTo: transport.baseURL) else { - {{! TODO: Process error correctly }} - fatalError("URL is nil") + guard let requestURL = components?.url else { + return Fail(error: OpenAPITransportError.badURLError()) + .eraseToAnyPublisher() } - var request = URLRequest(url: url) + var request = URLRequest(url: requestURL) request.httpMethod = "{{httpMethod}}" {{#hasHeaderParams}}// Setting headers request.allHTTPHeaderFields = [{{^headerParams}}{{^hasFormParams}} diff --git a/samples/client/petstore/swift-alt/.gitignore b/samples/client/petstore/swift-alt/.gitignore new file mode 100644 index 000000000000..4ea5f5d525b3 --- /dev/null +++ b/samples/client/petstore/swift-alt/.gitignore @@ -0,0 +1,64 @@ +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## Build generated +build/ +DerivedData + +## Various settings +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata + +## Other +*.xccheckout +*.moved-aside +*.xcuserstate +*.xcscmblueprint + +## Obj-C/Swift specific +*.hmap +*.ipa + +## Playgrounds +timeline.xctimeline +playground.xcworkspace + +# Swift Package Manager +# +# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. +# Packages/ +.build/ +.swiftpm + +# CocoaPods +# +# We recommend against adding the Pods directory to your .gitignore. However +# you should judge for yourself, the pros and cons are mentioned at: +# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control +# +# Pods/ + +# Carthage +# +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts + +Carthage/Build + +# fastlane +# +# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the +# screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://github.com/fastlane/fastlane/blob/master/docs/Gitignore.md + +fastlane/report.xml +fastlane/screenshots diff --git a/samples/client/petstore/swift-alt/.openapi-generator/FILES b/samples/client/petstore/swift-alt/.openapi-generator/FILES deleted file mode 100644 index 180d938c5951..000000000000 --- a/samples/client/petstore/swift-alt/.openapi-generator/FILES +++ /dev/null @@ -1,12 +0,0 @@ -Package.swift -Sources/APIs/PetAPI.swift -Sources/APIs/StoreAPI.swift -Sources/APIs/UserAPI.swift -Sources/Models/ApiResponse.swift -Sources/Models/Category.swift -Sources/Models/Order.swift -Sources/Models/Pet.swift -Sources/Models/Tag.swift -Sources/Models/User.swift -Sources/Private/OpenISO8601DateFormatter.swift -Sources/Runtime.swift diff --git a/samples/client/petstore/swift-alt/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata b/samples/client/petstore/swift-alt/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 919434a6254f..000000000000 --- a/samples/client/petstore/swift-alt/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/samples/client/petstore/swift-alt/.swiftpm/xcode/package.xcworkspace/xcuserdata/a.davydov.xcuserdatad/UserInterfaceState.xcuserstate b/samples/client/petstore/swift-alt/.swiftpm/xcode/package.xcworkspace/xcuserdata/a.davydov.xcuserdatad/UserInterfaceState.xcuserstate deleted file mode 100644 index 9f357587ec122dd44bbe03c1ba3d2fd20bfb63d4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16927 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 diff --git a/samples/client/petstore/swift-alt/.swiftpm/xcode/xcuserdata/a.davydov.xcuserdatad/xcschemes/xcschememanagement.plist b/samples/client/petstore/swift-alt/.swiftpm/xcode/xcuserdata/a.davydov.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index 9156ea3bf098..000000000000 --- a/samples/client/petstore/swift-alt/.swiftpm/xcode/xcuserdata/a.davydov.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SchemeUserState - - OpenAPIClient.xcscheme_^#shared#^_ - - orderHint - 0 - - - - diff --git a/samples/client/petstore/swift-alt/Sources/Runtime.swift b/samples/client/petstore/swift-alt/Sources/Runtime.swift deleted file mode 100644 index ca2874018cbc..000000000000 --- a/samples/client/petstore/swift-alt/Sources/Runtime.swift +++ /dev/null @@ -1,135 +0,0 @@ -// .swift -// -// Generated by openapi-generator -// https://openapi-generator.tech - -import Foundation -import Combine - -// MARK: - Open API Scheme - -public enum SecurityScheme { - case bearer - // Other schemes not supported yet https://swagger.io/docs/specification/authentication/ -} - -// MARK: - Authenticator - -public protocol Authenticator { - func authenticate(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher - func refresh() -> AnyPublisher -} - -/// Authenticator which does not authenticate requests and does not refresh it -open class EmptyAuthenticator: Authenticator { - public func authenticate(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher { - Just(request) - .setFailureType(to: Error.self) - .eraseToAnyPublisher() - } - - public func refresh() -> AnyPublisher { - Just(()) - .setFailureType(to: Error.self) - .eraseToAnyPublisher() - } - - public init() { - } -} - -// MARK: - Transport - -public protocol Transport { - var baseURL: URL { get } - func send(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher -} - -public struct TransportResponse { - public let data: Data - public let statusCode: Int -} - -public struct TransportError: Error { - public let data: Data - public let statusCode: Int - public let nestedError: Error? -} - -public extension TransportError { - // Impossible to add authentication headers to request - static let incorrectAuthenticationCode = 601 - // Error while refreshing authentication - static let failedAuthenticationRefreshCode = 602 - // There is no HTTP URL response - static let noResponseCode = 603 -} - -public protocol URLSessionTransportDelegate: AnyObject { - func willStart(request: URLRequest) - func didFinish(request: URLRequest, response: HTTPURLResponse?) -} - -open class URLSessionTransport: Transport { - private var cancellable = Set() - let session: URLSession - let authenticator: Authenticator - // Amount of time application will refresh authentication and try performing network call again - let authenticationRetryLimit = 1 - public let baseURL: URL - public weak var delegate: URLSessionTransportDelegate? - - public init(baseURL: URL, session: URLSession = .shared, authenticator: Authenticator = EmptyAuthenticator()) { - self.baseURL = baseURL - self.session = session - self.authenticator = authenticator - } - - open func send(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher { - send(request: request, securitySchemes: securitySchemes, triesLeft: authenticationRetryLimit) - } - - func send(request: URLRequest, securitySchemes: [SecurityScheme], triesLeft: Int) -> AnyPublisher { - authenticator - // Add authentication headers if needed before request - .authenticate(request: request, securitySchemes: securitySchemes) - .mapError { - TransportError(data: Data(), statusCode: TransportError.incorrectAuthenticationCode, nestedError: $0) - } - .flatMap { request -> AnyPublisher in - self.delegate?.willStart(request: request) - // Perform network call - return URLSession.shared.dataTaskPublisher(for: request) - .mapError { TransportError(data: Data(), statusCode: $0.code.rawValue, nestedError: nil) } - .flatMap { output -> AnyPublisher in - let response = output.response as? HTTPURLResponse - self.delegate?.didFinish(request: request, response: response) - switch response?.statusCode { - case .some(200): - let transportResponse = TransportResponse(data: output.data, statusCode: 200) - return Result.success(transportResponse).publisher.eraseToAnyPublisher() - case .some(401) where triesLeft > 0: - // Refresh authentication if possible - return self.authenticator - .refresh() - .mapError { - TransportError(data: Data(), statusCode: TransportError.failedAuthenticationRefreshCode, nestedError: $0) - } - .flatMap { - // Try performing network call again - self.send(request: request, securitySchemes: securitySchemes, triesLeft: triesLeft - 1) - } - .eraseToAnyPublisher() - case let .some(status): - let error = TransportError(data: output.data, statusCode: status, nestedError: nil) - return Fail(error: error).eraseToAnyPublisher() - default: - let error = TransportError(data: output.data, statusCode: TransportError.noResponseCode, nestedError: nil) - return Fail(error: error).eraseToAnyPublisher() - } - } - .eraseToAnyPublisher() - } - .eraseToAnyPublisher() - } -} diff --git a/samples/client/petstore/swift-alt/.openapi-generator-ignore b/samples/client/petstore/swift-alt/client/.openapi-generator-ignore similarity index 100% rename from samples/client/petstore/swift-alt/.openapi-generator-ignore rename to samples/client/petstore/swift-alt/client/.openapi-generator-ignore diff --git a/samples/client/petstore/swift-alt/client/.openapi-generator/FILES b/samples/client/petstore/swift-alt/client/.openapi-generator/FILES new file mode 100644 index 000000000000..05dded974662 --- /dev/null +++ b/samples/client/petstore/swift-alt/client/.openapi-generator/FILES @@ -0,0 +1,13 @@ +OpenAPITransport/Package.swift +OpenAPITransport/Sources/OpenAPITransport.swift +PetstoreOpenAPI/Package.swift +PetstoreOpenAPI/Sources/APIs/PetAPI.swift +PetstoreOpenAPI/Sources/APIs/StoreAPI.swift +PetstoreOpenAPI/Sources/APIs/UserAPI.swift +PetstoreOpenAPI/Sources/Models/ApiResponse.swift +PetstoreOpenAPI/Sources/Models/Category.swift +PetstoreOpenAPI/Sources/Models/Order.swift +PetstoreOpenAPI/Sources/Models/Pet.swift +PetstoreOpenAPI/Sources/Models/Tag.swift +PetstoreOpenAPI/Sources/Models/User.swift +PetstoreOpenAPI/Sources/Private/OpenISO8601DateFormatter.swift diff --git a/samples/client/petstore/swift-alt/.openapi-generator/VERSION b/samples/client/petstore/swift-alt/client/.openapi-generator/VERSION similarity index 100% rename from samples/client/petstore/swift-alt/.openapi-generator/VERSION rename to samples/client/petstore/swift-alt/client/.openapi-generator/VERSION diff --git a/samples/client/petstore/swift-alt/Package.swift b/samples/client/petstore/swift-alt/client/OpenAPITransport/Package.swift similarity index 59% rename from samples/client/petstore/swift-alt/Package.swift rename to samples/client/petstore/swift-alt/client/OpenAPITransport/Package.swift index 7c13bd37717e..916f6dfd64d0 100644 --- a/samples/client/petstore/swift-alt/Package.swift +++ b/samples/client/petstore/swift-alt/client/OpenAPITransport/Package.swift @@ -3,20 +3,21 @@ import PackageDescription let package = Package( - name: "OpenAPIClient", + name: "OpenAPITransport", platforms: [ - .iOS(.v13) + .iOS(.v13), + .macOS(.v10_15) ], products: [ .library( - name: "OpenAPIClient", - targets: ["OpenAPIClient"] + name: "OpenAPITransport", + targets: ["OpenAPITransport"] ), ], dependencies: [], targets: [ .target( - name: "OpenAPIClient", + name: "OpenAPITransport", dependencies: [], path: "Sources" ), diff --git a/samples/client/petstore/swift-alt/client/OpenAPITransport/Sources/OpenAPITransport.swift b/samples/client/petstore/swift-alt/client/OpenAPITransport/Sources/OpenAPITransport.swift new file mode 100644 index 000000000000..7524071a95aa --- /dev/null +++ b/samples/client/petstore/swift-alt/client/OpenAPITransport/Sources/OpenAPITransport.swift @@ -0,0 +1,229 @@ +// OpenAPITransport.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech + +import Foundation +import Combine + +// MARK: - Open API Scheme + +public enum SecurityScheme { + case bearer + // Other schemes not supported yet https://swagger.io/docs/specification/authentication/ +} + +// MARK: - Authenticator + +public protocol Authenticator { + func authenticate(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher + func refresh(securitySchemes: [SecurityScheme]) -> AnyPublisher +} + +/// Authenticator which does not authenticate requests and does not refresh it +open class EmptyAuthenticator: Authenticator { + public func authenticate(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher { + Just(request) + .setFailureType(to: Error.self) + .eraseToAnyPublisher() + } + + public func refresh(securitySchemes: [SecurityScheme]) -> AnyPublisher { + Just(()) + .setFailureType(to: Error.self) + .eraseToAnyPublisher() + } + + public init() { + } +} + +// MARK: - OpenAPITransport + +public protocol OpenAPITransport { + var baseURL: URL? { get } + + func send( + request: URLRequest, + securitySchemes: [SecurityScheme] + ) -> AnyPublisher + + func cancelAll() +} + +public struct OpenAPITransportResponse { + public let data: Data + public let statusCode: Int + + public init(data: Data, statusCode: Int) { + self.data = data + self.statusCode = statusCode + } +} + +public struct OpenAPITransportError: Error, CustomStringConvertible, LocalizedError { + public let statusCode: Int + public let description: String + public let errorDescription: String? + // It might be source network error + public let nestedError: Error? + // Data may contain additional reason info (like json payload) + public let data: Data + + public init( + statusCode: Int, + description: String? = nil, + errorDescription: String? = nil, + nestedError: Error? = nil, + data: Data = Data() + ) { + self.statusCode = statusCode + self.errorDescription = errorDescription + self.nestedError = nestedError + self.data = data + if let description = description { + self.description = description + } else { + var summary = "OpenAPITransportError with status \(statusCode)" + if let nestedError = nestedError { + summary.append(contentsOf: ", \(nestedError.localizedDescription)") + } + self.description = summary + } + } +} + +// Custom transport errors. It begins with 6.. not to conflict with HTTP codes (it begins with 5..) +public extension OpenAPITransportError { + static let incorrectAuthenticationCode = 600 + static func incorrectAuthenticationError(_ nestedError: Error? = nil) -> OpenAPITransportError { + OpenAPITransportError( + statusCode: OpenAPITransportError.incorrectAuthenticationCode, + description: "Impossible to add authentication headers to request", + errorDescription: NSLocalizedString( + "Impossible to add authentication headers to request", + comment: "Incorrect authentication" + ), + nestedError: nestedError + ) + } + + static let failedAuthenticationRefreshCode = 601 + static func failedAuthenticationRefreshError(_ nestedError: Error? = nil) -> OpenAPITransportError { + OpenAPITransportError( + statusCode: OpenAPITransportError.failedAuthenticationRefreshCode, + description: "Error while refreshing authentication", + errorDescription: NSLocalizedString( + "Error while refreshing authentication", + comment: "Failed authentication refresh" + ), + nestedError: nestedError + ) + } + + static let noResponseCode = 603 + static func noResponseError(_ nestedError: Error? = nil) -> OpenAPITransportError { + OpenAPITransportError( + statusCode: OpenAPITransportError.noResponseCode, + description: "There is no HTTP URL response", + errorDescription: NSLocalizedString( + "There is no HTTP URL response", + comment: "No response" + ), + nestedError: nestedError + ) + } + + static let badURLCode = 604 + static func badURLError(_ nestedError: Error? = nil) -> OpenAPITransportError { + OpenAPITransportError( + statusCode: OpenAPITransportError.badURLCode, + description: "Request URL cannot be created with given parameters", + errorDescription: NSLocalizedString( + "Request URL cannot be created with given parameters", + comment: "Bad URL" + ), + nestedError: nestedError + ) + } +} + +public protocol URLSessionOpenAPITransportDelegate: AnyObject { + func willStart(request: URLRequest) + func didFinish(request: URLRequest, response: HTTPURLResponse?) +} + +open class URLSessionOpenAPITransport: OpenAPITransport { + private var cancellable = Set() + let session: URLSession + let authenticator: Authenticator + // Amount of time application will refresh authentication and try performing network call again + let authenticationRetryLimit = 1 + public let baseURL: URL? + public weak var delegate: URLSessionOpenAPITransportDelegate? + + public init(baseURL: URL? = nil, session: URLSession = .shared, authenticator: Authenticator = EmptyAuthenticator()) { + self.baseURL = baseURL + self.session = session + self.authenticator = authenticator + } + + open func send( + request: URLRequest, + securitySchemes: [SecurityScheme] + ) -> AnyPublisher { + send(request: request, securitySchemes: securitySchemes, triesLeft: authenticationRetryLimit) + } + + open func cancelAll() { + cancellable.removeAll() + } + + func send( + request: URLRequest, + securitySchemes: [SecurityScheme], + triesLeft: Int + ) -> AnyPublisher { + authenticator + // Add authentication headers if needed before request + .authenticate(request: request, securitySchemes: securitySchemes) + .mapError { + OpenAPITransportError.incorrectAuthenticationError($0) + } + .flatMap { request -> AnyPublisher in + self.delegate?.willStart(request: request) + // Perform network call + return URLSession.shared.dataTaskPublisher(for: request) + .mapError { OpenAPITransportError(statusCode: $0.code.rawValue, description: "Network call finished fails") } + .flatMap { output -> AnyPublisher in + let response = output.response as? HTTPURLResponse + self.delegate?.didFinish(request: request, response: response) + switch response?.statusCode { + case .some(200): + let OpenAPITransportResponse = OpenAPITransportResponse(data: output.data, statusCode: 200) + return Result.success(OpenAPITransportResponse).publisher.eraseToAnyPublisher() + case .some(401) where triesLeft > 0: + // Refresh authentication if possible + return self.authenticator + .refresh(securitySchemes: securitySchemes) + .mapError { + OpenAPITransportError.failedAuthenticationRefreshError($0) + } + .flatMap { + // Try performing network call again + self.send(request: request, securitySchemes: securitySchemes, triesLeft: triesLeft - 1) + } + .eraseToAnyPublisher() + case let .some(status): + let error = OpenAPITransportError(statusCode: status, data: output.data) + return Fail(error: error).eraseToAnyPublisher() + default: + let error = OpenAPITransportError(statusCode: OpenAPITransportError.noResponseCode, data: output.data) + return Fail(error: error).eraseToAnyPublisher() + } + } + .eraseToAnyPublisher() + } + .eraseToAnyPublisher() + } +} diff --git a/samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Package.swift b/samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Package.swift new file mode 100644 index 000000000000..65c060130e0e --- /dev/null +++ b/samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Package.swift @@ -0,0 +1,25 @@ +// swift-tools-version:5.1 + +import PackageDescription + +let package = Package( + name: "PetstoreOpenAPI", + platforms: [ + .iOS(.v13), + .macOS(.v10_15) + ], + products: [ + .library( + name: "PetstoreOpenAPI", + targets: ["PetstoreOpenAPI"] + ), + ], + dependencies: [.package(path: "../OpenAPITransport")], + targets: [ + .target( + name: "PetstoreOpenAPI", + dependencies: [.byName(name: "OpenAPITransport")], + path: "Sources" + ), + ] +) diff --git a/samples/client/petstore/swift-alt/Sources/APIs/PetAPI.swift b/samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/APIs/PetAPI.swift similarity index 64% rename from samples/client/petstore/swift-alt/Sources/APIs/PetAPI.swift rename to samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/APIs/PetAPI.swift index bcd73cc532aa..9fb858ac90e3 100644 --- a/samples/client/petstore/swift-alt/Sources/APIs/PetAPI.swift +++ b/samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/APIs/PetAPI.swift @@ -3,11 +3,10 @@ // // Generated by openapi-generator // https://openapi-generator.tech -// Run in root folder to build example mvn clean package -DskipTests; ./bin/generate-samples.sh bin/configs/swift-alt-petstore-new.yaml import Foundation import Combine -// import Runtime +import OpenAPITransport open class PetAPI { @@ -22,9 +21,10 @@ open class PetAPI { decoder.dateDecodingStrategy = .formatted(OpenISO8601DateFormatter()) return decoder }() - private let transport: Transport + private let transport: OpenAPITransport + public let baseURL = URL(string: "http://petstore.swagger.io/v2") - public init(_ transport: Transport) { + public init(_ transport: OpenAPITransport) { self.transport = transport } @@ -39,14 +39,21 @@ open class PetAPI { */ open func addPet(pet: Pet) -> AnyPublisher { // Creating final URL with query items and path - var components = URLComponents() - components.path = "/pet" + guard let baseURL = transport.baseURL ?? self.baseURL else { + return Fail(error: OpenAPITransportError.badURLError()) + .eraseToAnyPublisher() + } + + let path = "/pet" + let url = baseURL.appendingPathComponent(path) + let components = URLComponents(url: url, resolvingAgainstBaseURL: false) - guard let url = components.url(relativeTo: transport.baseURL) else { - fatalError("URL is nil") + guard let requestURL = components?.url else { + return Fail(error: OpenAPITransportError.badURLError()) + .eraseToAnyPublisher() } - var request = URLRequest(url: url) + var request = URLRequest(url: requestURL) request.httpMethod = "POST" // Setting body parameters @@ -76,15 +83,22 @@ open class PetAPI { */ open func deletePet(petId: Int64, apiKey: String? = nil) -> AnyPublisher { // Creating final URL with query items and path - var components = URLComponents() - components.path = "/pet/{petId}" + guard let baseURL = transport.baseURL ?? self.baseURL else { + return Fail(error: OpenAPITransportError.badURLError()) + .eraseToAnyPublisher() + } + + let path = "/pet/{petId}" .replacingOccurrences(of: "{petId}", with: "\(petId)") + let url = baseURL.appendingPathComponent(path) + let components = URLComponents(url: url, resolvingAgainstBaseURL: false) - guard let url = components.url(relativeTo: transport.baseURL) else { - fatalError("URL is nil") + guard let requestURL = components?.url else { + return Fail(error: OpenAPITransportError.badURLError()) + .eraseToAnyPublisher() } - var request = URLRequest(url: url) + var request = URLRequest(url: requestURL) request.httpMethod = "DELETE" // Setting headers request.allHTTPHeaderFields = [ @@ -112,16 +126,23 @@ open class PetAPI { */ open func findPetsByStatus(status: [String]) -> AnyPublisher<[Pet], Error> { // Creating final URL with query items and path - var components = URLComponents() - components.path = "/pet/findByStatus" - components.queryItems = [ + guard let baseURL = transport.baseURL ?? self.baseURL else { + return Fail(error: OpenAPITransportError.badURLError()) + .eraseToAnyPublisher() + } + + let path = "/pet/findByStatus" + let url = baseURL.appendingPathComponent(path) + var components = URLComponents(url: url, resolvingAgainstBaseURL: false) + components?.queryItems = [ URLQueryItem(name: "status", value: status.joined(separator: ", ")) ] - guard let url = components.url(relativeTo: transport.baseURL) else { - fatalError("URL is nil") + guard let requestURL = components?.url else { + return Fail(error: OpenAPITransportError.badURLError()) + .eraseToAnyPublisher() } - var request = URLRequest(url: url) + var request = URLRequest(url: requestURL) request.httpMethod = "GET" @@ -146,16 +167,23 @@ open class PetAPI { */ open func findPetsByTags(tags: [String]) -> AnyPublisher<[Pet], Error> { // Creating final URL with query items and path - var components = URLComponents() - components.path = "/pet/findByTags" - components.queryItems = [ + guard let baseURL = transport.baseURL ?? self.baseURL else { + return Fail(error: OpenAPITransportError.badURLError()) + .eraseToAnyPublisher() + } + + let path = "/pet/findByTags" + let url = baseURL.appendingPathComponent(path) + var components = URLComponents(url: url, resolvingAgainstBaseURL: false) + components?.queryItems = [ URLQueryItem(name: "tags", value: tags.joined(separator: ", ")) ] - guard let url = components.url(relativeTo: transport.baseURL) else { - fatalError("URL is nil") + guard let requestURL = components?.url else { + return Fail(error: OpenAPITransportError.badURLError()) + .eraseToAnyPublisher() } - var request = URLRequest(url: url) + var request = URLRequest(url: requestURL) request.httpMethod = "GET" @@ -180,15 +208,22 @@ open class PetAPI { */ open func getPetById(petId: Int64) -> AnyPublisher { // Creating final URL with query items and path - var components = URLComponents() - components.path = "/pet/{petId}" + guard let baseURL = transport.baseURL ?? self.baseURL else { + return Fail(error: OpenAPITransportError.badURLError()) + .eraseToAnyPublisher() + } + + let path = "/pet/{petId}" .replacingOccurrences(of: "{petId}", with: "\(petId)") + let url = baseURL.appendingPathComponent(path) + let components = URLComponents(url: url, resolvingAgainstBaseURL: false) - guard let url = components.url(relativeTo: transport.baseURL) else { - fatalError("URL is nil") + guard let requestURL = components?.url else { + return Fail(error: OpenAPITransportError.badURLError()) + .eraseToAnyPublisher() } - var request = URLRequest(url: url) + var request = URLRequest(url: requestURL) request.httpMethod = "GET" @@ -212,14 +247,21 @@ open class PetAPI { */ open func updatePet(pet: Pet) -> AnyPublisher { // Creating final URL with query items and path - var components = URLComponents() - components.path = "/pet" + guard let baseURL = transport.baseURL ?? self.baseURL else { + return Fail(error: OpenAPITransportError.badURLError()) + .eraseToAnyPublisher() + } + + let path = "/pet" + let url = baseURL.appendingPathComponent(path) + let components = URLComponents(url: url, resolvingAgainstBaseURL: false) - guard let url = components.url(relativeTo: transport.baseURL) else { - fatalError("URL is nil") + guard let requestURL = components?.url else { + return Fail(error: OpenAPITransportError.badURLError()) + .eraseToAnyPublisher() } - var request = URLRequest(url: url) + var request = URLRequest(url: requestURL) request.httpMethod = "PUT" // Setting body parameters @@ -250,15 +292,22 @@ open class PetAPI { */ open func updatePetWithForm(petId: Int64, name: String? = nil, status: String? = nil) -> AnyPublisher { // Creating final URL with query items and path - var components = URLComponents() - components.path = "/pet/{petId}" + guard let baseURL = transport.baseURL ?? self.baseURL else { + return Fail(error: OpenAPITransportError.badURLError()) + .eraseToAnyPublisher() + } + + let path = "/pet/{petId}" .replacingOccurrences(of: "{petId}", with: "\(petId)") + let url = baseURL.appendingPathComponent(path) + let components = URLComponents(url: url, resolvingAgainstBaseURL: false) - guard let url = components.url(relativeTo: transport.baseURL) else { - fatalError("URL is nil") + guard let requestURL = components?.url else { + return Fail(error: OpenAPITransportError.badURLError()) + .eraseToAnyPublisher() } - var request = URLRequest(url: url) + var request = URLRequest(url: requestURL) request.httpMethod = "POST" @@ -284,15 +333,22 @@ open class PetAPI { */ open func uploadFile(petId: Int64, additionalMetadata: String? = nil, file: Data? = nil) -> AnyPublisher { // Creating final URL with query items and path - var components = URLComponents() - components.path = "/pet/{petId}/uploadImage" + guard let baseURL = transport.baseURL ?? self.baseURL else { + return Fail(error: OpenAPITransportError.badURLError()) + .eraseToAnyPublisher() + } + + let path = "/pet/{petId}/uploadImage" .replacingOccurrences(of: "{petId}", with: "\(petId)") + let url = baseURL.appendingPathComponent(path) + let components = URLComponents(url: url, resolvingAgainstBaseURL: false) - guard let url = components.url(relativeTo: transport.baseURL) else { - fatalError("URL is nil") + guard let requestURL = components?.url else { + return Fail(error: OpenAPITransportError.badURLError()) + .eraseToAnyPublisher() } - var request = URLRequest(url: url) + var request = URLRequest(url: requestURL) request.httpMethod = "POST" diff --git a/samples/client/petstore/swift-alt/Sources/APIs/StoreAPI.swift b/samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/APIs/StoreAPI.swift similarity index 63% rename from samples/client/petstore/swift-alt/Sources/APIs/StoreAPI.swift rename to samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/APIs/StoreAPI.swift index cb52b7622703..ba96d8dfdc37 100644 --- a/samples/client/petstore/swift-alt/Sources/APIs/StoreAPI.swift +++ b/samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/APIs/StoreAPI.swift @@ -3,11 +3,10 @@ // // Generated by openapi-generator // https://openapi-generator.tech -// Run in root folder to build example mvn clean package -DskipTests; ./bin/generate-samples.sh bin/configs/swift-alt-petstore-new.yaml import Foundation import Combine -// import Runtime +import OpenAPITransport open class StoreAPI { @@ -22,9 +21,10 @@ open class StoreAPI { decoder.dateDecodingStrategy = .formatted(OpenISO8601DateFormatter()) return decoder }() - private let transport: Transport + private let transport: OpenAPITransport + public let baseURL = URL(string: "http://petstore.swagger.io/v2") - public init(_ transport: Transport) { + public init(_ transport: OpenAPITransport) { self.transport = transport } @@ -37,15 +37,22 @@ open class StoreAPI { */ open func deleteOrder(orderId: String) -> AnyPublisher { // Creating final URL with query items and path - var components = URLComponents() - components.path = "/store/order/{orderId}" + guard let baseURL = transport.baseURL ?? self.baseURL else { + return Fail(error: OpenAPITransportError.badURLError()) + .eraseToAnyPublisher() + } + + let path = "/store/order/{orderId}" .replacingOccurrences(of: "{orderId}", with: "\(orderId)") + let url = baseURL.appendingPathComponent(path) + let components = URLComponents(url: url, resolvingAgainstBaseURL: false) - guard let url = components.url(relativeTo: transport.baseURL) else { - fatalError("URL is nil") + guard let requestURL = components?.url else { + return Fail(error: OpenAPITransportError.badURLError()) + .eraseToAnyPublisher() } - var request = URLRequest(url: url) + var request = URLRequest(url: requestURL) request.httpMethod = "DELETE" @@ -69,14 +76,21 @@ open class StoreAPI { */ open func getInventory() -> AnyPublisher<[String: Int], Error> { // Creating final URL with query items and path - var components = URLComponents() - components.path = "/store/inventory" + guard let baseURL = transport.baseURL ?? self.baseURL else { + return Fail(error: OpenAPITransportError.badURLError()) + .eraseToAnyPublisher() + } + + let path = "/store/inventory" + let url = baseURL.appendingPathComponent(path) + let components = URLComponents(url: url, resolvingAgainstBaseURL: false) - guard let url = components.url(relativeTo: transport.baseURL) else { - fatalError("URL is nil") + guard let requestURL = components?.url else { + return Fail(error: OpenAPITransportError.badURLError()) + .eraseToAnyPublisher() } - var request = URLRequest(url: url) + var request = URLRequest(url: requestURL) request.httpMethod = "GET" @@ -98,15 +112,22 @@ open class StoreAPI { */ open func getOrderById(orderId: Int64) -> AnyPublisher { // Creating final URL with query items and path - var components = URLComponents() - components.path = "/store/order/{orderId}" + guard let baseURL = transport.baseURL ?? self.baseURL else { + return Fail(error: OpenAPITransportError.badURLError()) + .eraseToAnyPublisher() + } + + let path = "/store/order/{orderId}" .replacingOccurrences(of: "{orderId}", with: "\(orderId)") + let url = baseURL.appendingPathComponent(path) + let components = URLComponents(url: url, resolvingAgainstBaseURL: false) - guard let url = components.url(relativeTo: transport.baseURL) else { - fatalError("URL is nil") + guard let requestURL = components?.url else { + return Fail(error: OpenAPITransportError.badURLError()) + .eraseToAnyPublisher() } - var request = URLRequest(url: url) + var request = URLRequest(url: requestURL) request.httpMethod = "GET" @@ -127,14 +148,21 @@ open class StoreAPI { */ open func placeOrder(order: Order) -> AnyPublisher { // Creating final URL with query items and path - var components = URLComponents() - components.path = "/store/order" + guard let baseURL = transport.baseURL ?? self.baseURL else { + return Fail(error: OpenAPITransportError.badURLError()) + .eraseToAnyPublisher() + } + + let path = "/store/order" + let url = baseURL.appendingPathComponent(path) + let components = URLComponents(url: url, resolvingAgainstBaseURL: false) - guard let url = components.url(relativeTo: transport.baseURL) else { - fatalError("URL is nil") + guard let requestURL = components?.url else { + return Fail(error: OpenAPITransportError.badURLError()) + .eraseToAnyPublisher() } - var request = URLRequest(url: url) + var request = URLRequest(url: requestURL) request.httpMethod = "POST" // Setting body parameters diff --git a/samples/client/petstore/swift-alt/Sources/APIs/UserAPI.swift b/samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/APIs/UserAPI.swift similarity index 63% rename from samples/client/petstore/swift-alt/Sources/APIs/UserAPI.swift rename to samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/APIs/UserAPI.swift index 91f075612c28..cc189c962ee4 100644 --- a/samples/client/petstore/swift-alt/Sources/APIs/UserAPI.swift +++ b/samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/APIs/UserAPI.swift @@ -3,11 +3,10 @@ // // Generated by openapi-generator // https://openapi-generator.tech -// Run in root folder to build example mvn clean package -DskipTests; ./bin/generate-samples.sh bin/configs/swift-alt-petstore-new.yaml import Foundation import Combine -// import Runtime +import OpenAPITransport open class UserAPI { @@ -22,9 +21,10 @@ open class UserAPI { decoder.dateDecodingStrategy = .formatted(OpenISO8601DateFormatter()) return decoder }() - private let transport: Transport + private let transport: OpenAPITransport + public let baseURL = URL(string: "http://petstore.swagger.io/v2") - public init(_ transport: Transport) { + public init(_ transport: OpenAPITransport) { self.transport = transport } @@ -40,14 +40,21 @@ open class UserAPI { */ open func createUser(user: User) -> AnyPublisher { // Creating final URL with query items and path - var components = URLComponents() - components.path = "/user" + guard let baseURL = transport.baseURL ?? self.baseURL else { + return Fail(error: OpenAPITransportError.badURLError()) + .eraseToAnyPublisher() + } + + let path = "/user" + let url = baseURL.appendingPathComponent(path) + let components = URLComponents(url: url, resolvingAgainstBaseURL: false) - guard let url = components.url(relativeTo: transport.baseURL) else { - fatalError("URL is nil") + guard let requestURL = components?.url else { + return Fail(error: OpenAPITransportError.badURLError()) + .eraseToAnyPublisher() } - var request = URLRequest(url: url) + var request = URLRequest(url: requestURL) request.httpMethod = "POST" // Setting body parameters @@ -76,14 +83,21 @@ open class UserAPI { */ open func createUsersWithArrayInput(user: [User]) -> AnyPublisher { // Creating final URL with query items and path - var components = URLComponents() - components.path = "/user/createWithArray" + guard let baseURL = transport.baseURL ?? self.baseURL else { + return Fail(error: OpenAPITransportError.badURLError()) + .eraseToAnyPublisher() + } + + let path = "/user/createWithArray" + let url = baseURL.appendingPathComponent(path) + let components = URLComponents(url: url, resolvingAgainstBaseURL: false) - guard let url = components.url(relativeTo: transport.baseURL) else { - fatalError("URL is nil") + guard let requestURL = components?.url else { + return Fail(error: OpenAPITransportError.badURLError()) + .eraseToAnyPublisher() } - var request = URLRequest(url: url) + var request = URLRequest(url: requestURL) request.httpMethod = "POST" // Setting body parameters @@ -112,14 +126,21 @@ open class UserAPI { */ open func createUsersWithListInput(user: [User]) -> AnyPublisher { // Creating final URL with query items and path - var components = URLComponents() - components.path = "/user/createWithList" + guard let baseURL = transport.baseURL ?? self.baseURL else { + return Fail(error: OpenAPITransportError.badURLError()) + .eraseToAnyPublisher() + } + + let path = "/user/createWithList" + let url = baseURL.appendingPathComponent(path) + let components = URLComponents(url: url, resolvingAgainstBaseURL: false) - guard let url = components.url(relativeTo: transport.baseURL) else { - fatalError("URL is nil") + guard let requestURL = components?.url else { + return Fail(error: OpenAPITransportError.badURLError()) + .eraseToAnyPublisher() } - var request = URLRequest(url: url) + var request = URLRequest(url: requestURL) request.httpMethod = "POST" // Setting body parameters @@ -149,15 +170,22 @@ open class UserAPI { */ open func deleteUser(username: String) -> AnyPublisher { // Creating final URL with query items and path - var components = URLComponents() - components.path = "/user/{username}" + guard let baseURL = transport.baseURL ?? self.baseURL else { + return Fail(error: OpenAPITransportError.badURLError()) + .eraseToAnyPublisher() + } + + let path = "/user/{username}" .replacingOccurrences(of: "{username}", with: "\(username)") + let url = baseURL.appendingPathComponent(path) + let components = URLComponents(url: url, resolvingAgainstBaseURL: false) - guard let url = components.url(relativeTo: transport.baseURL) else { - fatalError("URL is nil") + guard let requestURL = components?.url else { + return Fail(error: OpenAPITransportError.badURLError()) + .eraseToAnyPublisher() } - var request = URLRequest(url: url) + var request = URLRequest(url: requestURL) request.httpMethod = "DELETE" @@ -178,15 +206,22 @@ open class UserAPI { */ open func getUserByName(username: String) -> AnyPublisher { // Creating final URL with query items and path - var components = URLComponents() - components.path = "/user/{username}" + guard let baseURL = transport.baseURL ?? self.baseURL else { + return Fail(error: OpenAPITransportError.badURLError()) + .eraseToAnyPublisher() + } + + let path = "/user/{username}" .replacingOccurrences(of: "{username}", with: "\(username)") + let url = baseURL.appendingPathComponent(path) + let components = URLComponents(url: url, resolvingAgainstBaseURL: false) - guard let url = components.url(relativeTo: transport.baseURL) else { - fatalError("URL is nil") + guard let requestURL = components?.url else { + return Fail(error: OpenAPITransportError.badURLError()) + .eraseToAnyPublisher() } - var request = URLRequest(url: url) + var request = URLRequest(url: requestURL) request.httpMethod = "GET" @@ -209,17 +244,24 @@ open class UserAPI { */ open func loginUser(username: String, password: String) -> AnyPublisher { // Creating final URL with query items and path - var components = URLComponents() - components.path = "/user/login" - components.queryItems = [ + guard let baseURL = transport.baseURL ?? self.baseURL else { + return Fail(error: OpenAPITransportError.badURLError()) + .eraseToAnyPublisher() + } + + let path = "/user/login" + let url = baseURL.appendingPathComponent(path) + var components = URLComponents(url: url, resolvingAgainstBaseURL: false) + components?.queryItems = [ URLQueryItem(name: "username", value: username), URLQueryItem(name: "password", value: password) ] - guard let url = components.url(relativeTo: transport.baseURL) else { - fatalError("URL is nil") + guard let requestURL = components?.url else { + return Fail(error: OpenAPITransportError.badURLError()) + .eraseToAnyPublisher() } - var request = URLRequest(url: url) + var request = URLRequest(url: requestURL) request.httpMethod = "GET" @@ -242,14 +284,21 @@ open class UserAPI { */ open func logoutUser() -> AnyPublisher { // Creating final URL with query items and path - var components = URLComponents() - components.path = "/user/logout" + guard let baseURL = transport.baseURL ?? self.baseURL else { + return Fail(error: OpenAPITransportError.badURLError()) + .eraseToAnyPublisher() + } + + let path = "/user/logout" + let url = baseURL.appendingPathComponent(path) + let components = URLComponents(url: url, resolvingAgainstBaseURL: false) - guard let url = components.url(relativeTo: transport.baseURL) else { - fatalError("URL is nil") + guard let requestURL = components?.url else { + return Fail(error: OpenAPITransportError.badURLError()) + .eraseToAnyPublisher() } - var request = URLRequest(url: url) + var request = URLRequest(url: requestURL) request.httpMethod = "GET" @@ -275,15 +324,22 @@ open class UserAPI { */ open func updateUser(username: String, user: User) -> AnyPublisher { // Creating final URL with query items and path - var components = URLComponents() - components.path = "/user/{username}" + guard let baseURL = transport.baseURL ?? self.baseURL else { + return Fail(error: OpenAPITransportError.badURLError()) + .eraseToAnyPublisher() + } + + let path = "/user/{username}" .replacingOccurrences(of: "{username}", with: "\(username)") + let url = baseURL.appendingPathComponent(path) + let components = URLComponents(url: url, resolvingAgainstBaseURL: false) - guard let url = components.url(relativeTo: transport.baseURL) else { - fatalError("URL is nil") + guard let requestURL = components?.url else { + return Fail(error: OpenAPITransportError.badURLError()) + .eraseToAnyPublisher() } - var request = URLRequest(url: url) + var request = URLRequest(url: requestURL) request.httpMethod = "PUT" // Setting body parameters diff --git a/samples/client/petstore/swift-alt/Sources/Models/ApiResponse.swift b/samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/Models/ApiResponse.swift similarity index 100% rename from samples/client/petstore/swift-alt/Sources/Models/ApiResponse.swift rename to samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/Models/ApiResponse.swift diff --git a/samples/client/petstore/swift-alt/Sources/Models/Category.swift b/samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/Models/Category.swift similarity index 100% rename from samples/client/petstore/swift-alt/Sources/Models/Category.swift rename to samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/Models/Category.swift diff --git a/samples/client/petstore/swift-alt/Sources/Models/Order.swift b/samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/Models/Order.swift similarity index 100% rename from samples/client/petstore/swift-alt/Sources/Models/Order.swift rename to samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/Models/Order.swift diff --git a/samples/client/petstore/swift-alt/Sources/Models/Pet.swift b/samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/Models/Pet.swift similarity index 100% rename from samples/client/petstore/swift-alt/Sources/Models/Pet.swift rename to samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/Models/Pet.swift diff --git a/samples/client/petstore/swift-alt/Sources/Models/Tag.swift b/samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/Models/Tag.swift similarity index 100% rename from samples/client/petstore/swift-alt/Sources/Models/Tag.swift rename to samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/Models/Tag.swift diff --git a/samples/client/petstore/swift-alt/Sources/Models/User.swift b/samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/Models/User.swift similarity index 100% rename from samples/client/petstore/swift-alt/Sources/Models/User.swift rename to samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/Models/User.swift diff --git a/samples/client/petstore/swift-alt/Sources/Private/OpenISO8601DateFormatter.swift b/samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/Private/OpenISO8601DateFormatter.swift similarity index 100% rename from samples/client/petstore/swift-alt/Sources/Private/OpenISO8601DateFormatter.swift rename to samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/Private/OpenISO8601DateFormatter.swift diff --git a/samples/client/petstore/swift-alt/tests/Package.swift b/samples/client/petstore/swift-alt/tests/Package.swift new file mode 100644 index 000000000000..9dbe7b4e42fc --- /dev/null +++ b/samples/client/petstore/swift-alt/tests/Package.swift @@ -0,0 +1,19 @@ +// swift-tools-version:5.1 + +import PackageDescription + +let package = Package( + name: "TestClientTests", + platforms: [ + .iOS(.v13), + .macOS(.v10_15) + ], + products: [], + dependencies: [.package(path: "../client/PetstoreOpenAPI")], + targets: [ + .testTarget( + name: "TestClientTests", + dependencies: [.byName(name: "PetstoreOpenAPI")] + ), + ] +) diff --git a/samples/client/petstore/swift-alt/tests/Sources/TestClientTests/PetAPITests.swift b/samples/client/petstore/swift-alt/tests/Sources/TestClientTests/PetAPITests.swift new file mode 100644 index 000000000000..535fe1906696 --- /dev/null +++ b/samples/client/petstore/swift-alt/tests/Sources/TestClientTests/PetAPITests.swift @@ -0,0 +1,117 @@ +// +// PetAPITests.swift +// +// +// Created by Anton Davydov on 16.11.2021. +// + +import XCTest +import Combine +import PetstoreOpenAPI +import OpenAPITransport + +class PetAPITests: XCTestCase { + var cancellable = Set() + let timeout: TimeInterval = 10 + let baseURL = URL(string: "https://petstore.swagger.io/v2")! + + override func tearDown() { + cancellable.removeAll() + } + + func testAddPet() { + // Given + let transport = URLSessionOpenAPITransport(baseURL: baseURL) + let api = PetAPI(transport) + let category = Category(id: 1, name: "CategoryName") + let photoUrls = ["https://petstore.com/sample/photo1.jpg", "https://petstore.com/sample/photo2.jpg"] + let tags = [Tag(id: 10, name: "Tag1"), Tag(id: 11, name: "Tag2")] + let pet = Pet( + id: 100, + category: category, + name: "PetName100", + photoUrls: photoUrls, + tags: tags, + status: .available + ) + + // When + let expectation = expectation(description: "addPetTestExpectation") + api.addPet(pet: pet) + .sink(receiveCompletion: { completion in + // Then + switch completion { + case .finished: + expectation.fulfill() + case let .failure(error): + XCTFail("Adding pet operation finished with error: \(error)") + expectation.fulfill() + } + }, receiveValue: { addedPet in + // Then + XCTAssertTrue(pet == addedPet, "Added pet should be the same as given value") + }) + .store(in: &cancellable) + wait(for: [expectation], timeout: timeout) + } + + func testGetPetById() { + // Given + let transport = URLSessionOpenAPITransport(baseURL: baseURL) + let api = PetAPI(transport) + let petId: Int64 = 101 + let pet = Pet(id: petId, category: nil, name: "PetName101", photoUrls: [], tags: nil, status: .available) + + // When + let expectation = expectation(description: "testGetPetByIdExpectation") + api.addPet(pet: pet) + // Delay to prevent too early access data + .delay(for: 3.0, scheduler: DispatchQueue.global()) + .flatMap { _ in + api.getPetById(petId: petId) + } + .sink { completion in + switch completion { + case .finished: + expectation.fulfill() + case let .failure(error): + XCTFail("Finding pet operation finished with error: \(error)") + expectation.fulfill() + } + } receiveValue: { pet in + XCTAssertTrue(pet.id == petId, "Found pet should have given pet id") + } + .store(in: &cancellable) + + wait(for: [expectation], timeout: timeout) + } + + func testDeletePet() { + // Given + let transport = URLSessionOpenAPITransport(baseURL: baseURL) + let api = PetAPI(transport) + let petId: Int64 = 102 + let pet = Pet(id: petId, category: nil, name: "PetName102", photoUrls: [], tags: nil, status: .available) + + // When + let expectation = expectation(description: "testDeletePetExpectation") + api.addPet(pet: pet) + // Delay to prevent too early access data + .delay(for: 3.0, scheduler: DispatchQueue.global()) + .flatMap { _ in + api.deletePet(petId: petId, apiKey: "special-key") + } + .sink { completion in + // Then + switch completion { + case .finished: + expectation.fulfill() + case let .failure(error): + XCTFail("Deleting pet operation finished with error: \(error)") + expectation.fulfill() + } + } receiveValue: {} + .store(in: &cancellable) + wait(for: [expectation], timeout: timeout) + } +} From 18749c8781c6a37ee281f8a8fe0267a213a67aae Mon Sep 17 00:00:00 2001 From: Anton Davydov Date: Wed, 17 Nov 2021 16:47:21 +0300 Subject: [PATCH 06/33] swift-alt v0.1.0 --- .../languages/SwiftAltClientCodegen.java | 13 +- .../swift-alt/OpenAPITransport.mustache | 171 ++++++++++++------ .../src/main/resources/swift-alt/api.mustache | 9 + .../Sources/OpenAPITransport.swift | 171 ++++++++++++------ .../Sources/TestClientTests/PetAPITests.swift | 41 ++--- 5 files changed, 269 insertions(+), 136 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java index fa3a6760d7fa..ff98c577be00 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java @@ -50,6 +50,7 @@ public class SwiftAltClientCodegen extends DefaultCodegen implements CodegenConf protected String privateFolder = "Sources/Private"; protected String sourceFolder = "Sources"; protected String transportFolder = "OpenAPITransport"; + protected List notCodableTypes = Arrays.asList("Any", "AnyObject", "[String: Any]"); /** * Constructor for the swift alt language codegen module. @@ -86,6 +87,7 @@ public SwiftAltClientCodegen() { "URL", "AnyObject", "Any", + "[String: Any]", "Decimal") ); defaultIncludes = new HashSet<>( @@ -100,7 +102,6 @@ public SwiftAltClientCodegen() { "Any", "Empty", "AnyObject", - "Any", "Decimal") ); @@ -176,8 +177,8 @@ public SwiftAltClientCodegen() { typeMapping.put("UUID", "UUID"); typeMapping.put("URI", "String"); typeMapping.put("decimal", "Decimal"); - typeMapping.put("object", "AnyCodable"); - typeMapping.put("AnyType", "AnyCodable"); + typeMapping.put("object", "[String: Any]"); + typeMapping.put("AnyType", "Any"); typeMapping.put("file", "Data"); typeMapping.put("binary", "Data"); @@ -766,6 +767,9 @@ public Map postProcessOperationsWithModels(Map o for (CodegenParameter cp : operation.allParams) { cp.vendorExtensions.put("x-swift-example", constructExampleCode(cp, modelMaps, new HashSet())); } + if (notCodableTypes.contains(operation.returnType)) { + operation.vendorExtensions.put("x-swift-isNotCodable", true); + } } return objs; } @@ -880,7 +884,8 @@ public String constructExampleCode(CodegenModel codegenModel, HashMap AnyPublisher - func refresh(securitySchemes: [SecurityScheme]) -> AnyPublisher + func authenticate(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher + func refresh(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher } -/// Authenticator which does not authenticate requests and does not refresh it -open class EmptyAuthenticator: Authenticator { - public func authenticate(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher { +final class DefaultAuthenticator: Authenticator { + func authenticate(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher { Just(request) - .setFailureType(to: Error.self) + .setFailureType(to: OpenAPITransportError.self) .eraseToAnyPublisher() } - public func refresh(securitySchemes: [SecurityScheme]) -> AnyPublisher { - Just(()) - .setFailureType(to: Error.self) + func refresh(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher { + Fail(outputType: Void.self, failure: OpenAPITransportError.failedAuthenticationRefreshError()) .eraseToAnyPublisher() } - public init() { + init() { + } +} + +// MARK: - Policy + +/// Policy to define whether response is successful or requires authentication +public protocol URLResponsePolicy { + func defineState(for response: URLResponse) -> URLResponseState +} + +public enum URLResponseState { + case success + case failure + case requiresAuthentication +} + +final class DefaultURLResponsePolicy: URLResponsePolicy { + func defineState(for response: URLResponse) -> URLResponseState { + switch (response as? HTTPURLResponse)?.statusCode { + case .some(200): + return .success + case .some(401): + return .requiresAuthentication + default: + return .failure + } + } +} + +/// Define how to customize URL request before network call +public protocol URLRequestProcessor { + /// Customize request before performing. Add headers or encrypt body for example. + func enrich(request: URLRequest) -> AnyPublisher + /// Customize response before handling. Decrypt body for example. + func decode(output: URLSession.DataTaskPublisher.Output) -> AnyPublisher +} + +final class DefaultURLRequestProcessor: URLRequestProcessor { + func enrich(request: URLRequest) -> AnyPublisher { + Just(request) + .setFailureType(to: OpenAPITransportError.self) + .eraseToAnyPublisher() + } + + func decode(output: URLSession.DataTaskPublisher.Output) -> AnyPublisher { + Just(output) + .setFailureType(to: OpenAPITransportError.self) + .eraseToAnyPublisher() } } @@ -146,6 +192,19 @@ public extension OpenAPITransportError { nestedError: nestedError ) } + + static let invalidResponseMappingCode = 605 + static func invalidResponseMappingError(data: Data) -> OpenAPITransportError { + OpenAPITransportError( + statusCode: OpenAPITransportError.invalidResponseMappingCode, + description: "Response data cannot be expected object scheme", + errorDescription: NSLocalizedString( + "Response data cannot be expected object scheme", + comment: "Invalid response mapping" + ), + data: data + ) + } } public protocol URLSessionOpenAPITransportDelegate: AnyObject { @@ -155,70 +214,55 @@ public protocol URLSessionOpenAPITransportDelegate: AnyObject { open class URLSessionOpenAPITransport: OpenAPITransport { private var cancellable = Set() - let session: URLSession - let authenticator: Authenticator - // Amount of time application will refresh authentication and try performing network call again - let authenticationRetryLimit = 1 - public let baseURL: URL? - public weak var delegate: URLSessionOpenAPITransportDelegate? + private let config: Config + public var baseURL: URL? { config.baseURL } - public init(baseURL: URL? = nil, session: URLSession = .shared, authenticator: Authenticator = EmptyAuthenticator()) { - self.baseURL = baseURL - self.session = session - self.authenticator = authenticator + public init(config: Config = .init()) { + self.config = config } open func send( request: URLRequest, securitySchemes: [SecurityScheme] ) -> AnyPublisher { - send(request: request, securitySchemes: securitySchemes, triesLeft: authenticationRetryLimit) - } - - open func cancelAll() { - cancellable.removeAll() - } - - func send( - request: URLRequest, - securitySchemes: [SecurityScheme], - triesLeft: Int - ) -> AnyPublisher { - authenticator + + config.processor + // Add custom headers or if needed + .enrich(request: request) // Add authentication headers if needed before request - .authenticate(request: request, securitySchemes: securitySchemes) - .mapError { - OpenAPITransportError.incorrectAuthenticationError($0) + .flatMap { request in + self.config.authenticator + .authenticate(request: request, securitySchemes: securitySchemes) + .eraseToAnyPublisher() } .flatMap { request -> AnyPublisher in - self.delegate?.willStart(request: request) + self.config.delegate?.willStart(request: request) // Perform network call return URLSession.shared.dataTaskPublisher(for: request) .mapError { OpenAPITransportError(statusCode: $0.code.rawValue, description: "Network call finished fails") } + .flatMap { output in + self.config.processor.decode(output: output) + } .flatMap { output -> AnyPublisher in let response = output.response as? HTTPURLResponse - self.delegate?.didFinish(request: request, response: response) - switch response?.statusCode { - case .some(200): + self.config.delegate?.didFinish(request: request, response: response) + switch self.config.policy.defineState(for: output.response) { + case .success: let OpenAPITransportResponse = OpenAPITransportResponse(data: output.data, statusCode: 200) return Result.success(OpenAPITransportResponse).publisher.eraseToAnyPublisher() - case .some(401) where triesLeft > 0: + case .requiresAuthentication: // Refresh authentication if possible - return self.authenticator - .refresh(securitySchemes: securitySchemes) - .mapError { - OpenAPITransportError.failedAuthenticationRefreshError($0) - } + return self.config.authenticator + .refresh(request: request, securitySchemes: securitySchemes) .flatMap { // Try performing network call again - self.send(request: request, securitySchemes: securitySchemes, triesLeft: triesLeft - 1) + self.send(request: request, securitySchemes: securitySchemes) } .eraseToAnyPublisher() - case let .some(status): - let error = OpenAPITransportError(statusCode: status, data: output.data) - return Fail(error: error).eraseToAnyPublisher() + // TODO: Check too many attempts error default: - let error = OpenAPITransportError(statusCode: OpenAPITransportError.noResponseCode, data: output.data) + let code = response?.statusCode ?? OpenAPITransportError.noResponseCode + let error = OpenAPITransportError(statusCode: code, data: output.data) return Fail(error: error).eraseToAnyPublisher() } } @@ -226,4 +270,25 @@ open class URLSessionOpenAPITransport: OpenAPITransport { } .eraseToAnyPublisher() } + + open func cancelAll() { + cancellable.removeAll() + } +} + +public extension URLSessionOpenAPITransport { + struct Config { + public var baseURL: URL? = nil + public var session: URLSession = .shared + public var authenticator: Authenticator = DefaultAuthenticator() + public var processor: URLRequestProcessor = DefaultURLRequestProcessor() + public var policy: URLResponsePolicy = DefaultURLResponsePolicy() + public weak var delegate: URLSessionOpenAPITransportDelegate? + + public init() {} + + public init(baseURL: URL) { + self.baseURL = baseURL + } + } } diff --git a/modules/openapi-generator/src/main/resources/swift-alt/api.mustache b/modules/openapi-generator/src/main/resources/swift-alt/api.mustache index b33e966a4df0..8f66bf71392c 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/api.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/api.mustache @@ -100,7 +100,16 @@ open class {{classname}} { .tryMap { response in {{! TODO: Check responses properly }} {{#returnType}} + {{#vendorExtensions.x-swift-isNotCodable}} + if let object = try JSONSerialization.jsonObject(with: response.data, options: []) as? {{{returnType}}} { + return object + } else { + throw OpenAPITransportError.invalidResponseMappingError(data: response.data) + } + {{/vendorExtensions.x-swift-isNotCodable}} + {{^vendorExtensions.x-swift-isNotCodable}} try {{classname}}.decoder.decode({{{returnType}}}.self, from: response.data) + {{/vendorExtensions.x-swift-isNotCodable}} {{/returnType}} {{^returnType}} return () diff --git a/samples/client/petstore/swift-alt/client/OpenAPITransport/Sources/OpenAPITransport.swift b/samples/client/petstore/swift-alt/client/OpenAPITransport/Sources/OpenAPITransport.swift index 7524071a95aa..fcb10c10c592 100644 --- a/samples/client/petstore/swift-alt/client/OpenAPITransport/Sources/OpenAPITransport.swift +++ b/samples/client/petstore/swift-alt/client/OpenAPITransport/Sources/OpenAPITransport.swift @@ -9,32 +9,78 @@ import Combine // MARK: - Open API Scheme public enum SecurityScheme { - case bearer - // Other schemes not supported yet https://swagger.io/docs/specification/authentication/ + // Security schemes not supported yet https://swagger.io/docs/specification/authentication/ } // MARK: - Authenticator +// Class which is able to add authentication headers and refresh authentication public protocol Authenticator { - func authenticate(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher - func refresh(securitySchemes: [SecurityScheme]) -> AnyPublisher + func authenticate(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher + func refresh(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher } -/// Authenticator which does not authenticate requests and does not refresh it -open class EmptyAuthenticator: Authenticator { - public func authenticate(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher { +final class DefaultAuthenticator: Authenticator { + func authenticate(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher { Just(request) - .setFailureType(to: Error.self) + .setFailureType(to: OpenAPITransportError.self) .eraseToAnyPublisher() } - public func refresh(securitySchemes: [SecurityScheme]) -> AnyPublisher { - Just(()) - .setFailureType(to: Error.self) + func refresh(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher { + Fail(outputType: Void.self, failure: OpenAPITransportError.failedAuthenticationRefreshError()) .eraseToAnyPublisher() } - public init() { + init() { + } +} + +// MARK: - Policy + +/// Policy to define whether response is successful or requires authentication +public protocol URLResponsePolicy { + func defineState(for response: URLResponse) -> URLResponseState +} + +public enum URLResponseState { + case success + case failure + case requiresAuthentication +} + +final class DefaultURLResponsePolicy: URLResponsePolicy { + func defineState(for response: URLResponse) -> URLResponseState { + switch (response as? HTTPURLResponse)?.statusCode { + case .some(200): + return .success + case .some(401): + return .requiresAuthentication + default: + return .failure + } + } +} + +/// Define how to customize URL request before network call +public protocol URLRequestProcessor { + /// Customize request before performing. Add headers or encrypt body for example. + func enrich(request: URLRequest) -> AnyPublisher + /// Customize response before handling. Decrypt body for example. + func decode(output: URLSession.DataTaskPublisher.Output) -> AnyPublisher +} + +final class DefaultURLRequestProcessor: URLRequestProcessor { + func enrich(request: URLRequest) -> AnyPublisher { + Just(request) + .setFailureType(to: OpenAPITransportError.self) + .eraseToAnyPublisher() + } + + func decode(output: URLSession.DataTaskPublisher.Output) -> AnyPublisher { + Just(output) + .setFailureType(to: OpenAPITransportError.self) + .eraseToAnyPublisher() } } @@ -146,6 +192,19 @@ public extension OpenAPITransportError { nestedError: nestedError ) } + + static let invalidResponseMappingCode = 605 + static func invalidResponseMappingError(data: Data) -> OpenAPITransportError { + OpenAPITransportError( + statusCode: OpenAPITransportError.invalidResponseMappingCode, + description: "Response data cannot be expected object scheme", + errorDescription: NSLocalizedString( + "Response data cannot be expected object scheme", + comment: "Invalid response mapping" + ), + data: data + ) + } } public protocol URLSessionOpenAPITransportDelegate: AnyObject { @@ -155,70 +214,55 @@ public protocol URLSessionOpenAPITransportDelegate: AnyObject { open class URLSessionOpenAPITransport: OpenAPITransport { private var cancellable = Set() - let session: URLSession - let authenticator: Authenticator - // Amount of time application will refresh authentication and try performing network call again - let authenticationRetryLimit = 1 - public let baseURL: URL? - public weak var delegate: URLSessionOpenAPITransportDelegate? + private let config: Config + public var baseURL: URL? { config.baseURL } - public init(baseURL: URL? = nil, session: URLSession = .shared, authenticator: Authenticator = EmptyAuthenticator()) { - self.baseURL = baseURL - self.session = session - self.authenticator = authenticator + public init(config: Config = .init()) { + self.config = config } open func send( request: URLRequest, securitySchemes: [SecurityScheme] ) -> AnyPublisher { - send(request: request, securitySchemes: securitySchemes, triesLeft: authenticationRetryLimit) - } - - open func cancelAll() { - cancellable.removeAll() - } - - func send( - request: URLRequest, - securitySchemes: [SecurityScheme], - triesLeft: Int - ) -> AnyPublisher { - authenticator + + config.processor + // Add custom headers or if needed + .enrich(request: request) // Add authentication headers if needed before request - .authenticate(request: request, securitySchemes: securitySchemes) - .mapError { - OpenAPITransportError.incorrectAuthenticationError($0) + .flatMap { request in + self.config.authenticator + .authenticate(request: request, securitySchemes: securitySchemes) + .eraseToAnyPublisher() } .flatMap { request -> AnyPublisher in - self.delegate?.willStart(request: request) + self.config.delegate?.willStart(request: request) // Perform network call return URLSession.shared.dataTaskPublisher(for: request) .mapError { OpenAPITransportError(statusCode: $0.code.rawValue, description: "Network call finished fails") } + .flatMap { output in + self.config.processor.decode(output: output) + } .flatMap { output -> AnyPublisher in let response = output.response as? HTTPURLResponse - self.delegate?.didFinish(request: request, response: response) - switch response?.statusCode { - case .some(200): + self.config.delegate?.didFinish(request: request, response: response) + switch self.config.policy.defineState(for: output.response) { + case .success: let OpenAPITransportResponse = OpenAPITransportResponse(data: output.data, statusCode: 200) return Result.success(OpenAPITransportResponse).publisher.eraseToAnyPublisher() - case .some(401) where triesLeft > 0: + case .requiresAuthentication: // Refresh authentication if possible - return self.authenticator - .refresh(securitySchemes: securitySchemes) - .mapError { - OpenAPITransportError.failedAuthenticationRefreshError($0) - } + return self.config.authenticator + .refresh(request: request, securitySchemes: securitySchemes) .flatMap { // Try performing network call again - self.send(request: request, securitySchemes: securitySchemes, triesLeft: triesLeft - 1) + self.send(request: request, securitySchemes: securitySchemes) } .eraseToAnyPublisher() - case let .some(status): - let error = OpenAPITransportError(statusCode: status, data: output.data) - return Fail(error: error).eraseToAnyPublisher() + // TODO: Check too many attempts error default: - let error = OpenAPITransportError(statusCode: OpenAPITransportError.noResponseCode, data: output.data) + let code = response?.statusCode ?? OpenAPITransportError.noResponseCode + let error = OpenAPITransportError(statusCode: code, data: output.data) return Fail(error: error).eraseToAnyPublisher() } } @@ -226,4 +270,25 @@ open class URLSessionOpenAPITransport: OpenAPITransport { } .eraseToAnyPublisher() } + + open func cancelAll() { + cancellable.removeAll() + } +} + +public extension URLSessionOpenAPITransport { + struct Config { + public var baseURL: URL? = nil + public var session: URLSession = .shared + public var authenticator: Authenticator = DefaultAuthenticator() + public var processor: URLRequestProcessor = DefaultURLRequestProcessor() + public var policy: URLResponsePolicy = DefaultURLResponsePolicy() + public weak var delegate: URLSessionOpenAPITransportDelegate? + + public init() {} + + public init(baseURL: URL) { + self.baseURL = baseURL + } + } } diff --git a/samples/client/petstore/swift-alt/tests/Sources/TestClientTests/PetAPITests.swift b/samples/client/petstore/swift-alt/tests/Sources/TestClientTests/PetAPITests.swift index 535fe1906696..c7d8ead2a392 100644 --- a/samples/client/petstore/swift-alt/tests/Sources/TestClientTests/PetAPITests.swift +++ b/samples/client/petstore/swift-alt/tests/Sources/TestClientTests/PetAPITests.swift @@ -21,7 +21,7 @@ class PetAPITests: XCTestCase { func testAddPet() { // Given - let transport = URLSessionOpenAPITransport(baseURL: baseURL) + let transport = URLSessionOpenAPITransport(config: .init(baseURL: baseURL)) let api = PetAPI(transport) let category = Category(id: 1, name: "CategoryName") let photoUrls = ["https://petstore.com/sample/photo1.jpg", "https://petstore.com/sample/photo2.jpg"] @@ -55,59 +55,48 @@ class PetAPITests: XCTestCase { wait(for: [expectation], timeout: timeout) } - func testGetPetById() { + func testGetPetByUnknownId() { // Given - let transport = URLSessionOpenAPITransport(baseURL: baseURL) + let transport = URLSessionOpenAPITransport(config: .init(baseURL: baseURL)) let api = PetAPI(transport) - let petId: Int64 = 101 - let pet = Pet(id: petId, category: nil, name: "PetName101", photoUrls: [], tags: nil, status: .available) + let unknownPetId: Int64 = 1010101010 // When let expectation = expectation(description: "testGetPetByIdExpectation") - api.addPet(pet: pet) - // Delay to prevent too early access data - .delay(for: 3.0, scheduler: DispatchQueue.global()) - .flatMap { _ in - api.getPetById(petId: petId) - } + api.getPetById(petId: unknownPetId) .sink { completion in switch completion { case .finished: + XCTFail("Finding unknown pet operation should return 404 error") expectation.fulfill() case let .failure(error): - XCTFail("Finding pet operation finished with error: \(error)") + XCTAssertTrue((error as? OpenAPITransportError)?.statusCode == 404, "Finding unknown pet operation should return 404 error") expectation.fulfill() } - } receiveValue: { pet in - XCTAssertTrue(pet.id == petId, "Found pet should have given pet id") - } + } receiveValue: { _ in } .store(in: &cancellable) wait(for: [expectation], timeout: timeout) } - func testDeletePet() { + func testDeleteUnknownPet() { // Given - let transport = URLSessionOpenAPITransport(baseURL: baseURL) + let transport = URLSessionOpenAPITransport(config: .init(baseURL: baseURL)) let api = PetAPI(transport) - let petId: Int64 = 102 - let pet = Pet(id: petId, category: nil, name: "PetName102", photoUrls: [], tags: nil, status: .available) + let unknownPetId: Int64 = 1010101010 // When let expectation = expectation(description: "testDeletePetExpectation") - api.addPet(pet: pet) - // Delay to prevent too early access data - .delay(for: 3.0, scheduler: DispatchQueue.global()) - .flatMap { _ in - api.deletePet(petId: petId, apiKey: "special-key") - } + api + .deletePet(petId: unknownPetId, apiKey: "special-key") .sink { completion in // Then switch completion { case .finished: + XCTFail("Deleting unknown pet operation should return 404 error") expectation.fulfill() case let .failure(error): - XCTFail("Deleting pet operation finished with error: \(error)") + XCTAssertTrue((error as? OpenAPITransportError)?.statusCode == 404, "Deleting unknown pet operation should return 404 error") expectation.fulfill() } } receiveValue: {} From 91581db87d3408e57c2601850693029e48a5dad4 Mon Sep 17 00:00:00 2001 From: Anton Davydov Date: Tue, 14 Dec 2021 21:54:09 +0300 Subject: [PATCH 07/33] swift-alt implemented form encoded body --- .../languages/SwiftAltClientCodegen.java | 9 ++++ .../swift-alt/OpenAPITransport.mustache | 4 +- .../src/main/resources/swift-alt/api.mustache | 47 ++++++++++++++----- .../resources/swift-alt/toString.mustache | 1 + 4 files changed, 46 insertions(+), 15 deletions(-) create mode 100644 modules/openapi-generator/src/main/resources/swift-alt/toString.mustache diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java index ff98c577be00..dfcfd91891c6 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java @@ -57,6 +57,7 @@ public class SwiftAltClientCodegen extends DefaultCodegen implements CodegenConf */ public SwiftAltClientCodegen() { super(); + this.supportsAdditionalPropertiesWithComposedSchema = true; this.useOneOfInterfaces = true; generatorMetadata = GeneratorMetadata.newBuilder(generatorMetadata) @@ -297,6 +298,14 @@ protected boolean isReservedWord(String word) { return word != null && reservedWords.contains(word); //don't lowercase as super does } + @Override + public String escapeReservedWord(String name) { + if (this.reservedWordsMappings().containsKey(name)) { + return this.reservedWordsMappings().get(name); + } + return "_" + name; + } + @Override public String modelFileFolder() { return outputFolder + File.separator + projectName + File.separator + sourceFolder diff --git a/modules/openapi-generator/src/main/resources/swift-alt/OpenAPITransport.mustache b/modules/openapi-generator/src/main/resources/swift-alt/OpenAPITransport.mustache index fcb10c10c592..872552f508f2 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/OpenAPITransport.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/OpenAPITransport.mustache @@ -209,7 +209,7 @@ public extension OpenAPITransportError { public protocol URLSessionOpenAPITransportDelegate: AnyObject { func willStart(request: URLRequest) - func didFinish(request: URLRequest, response: HTTPURLResponse?) + func didFinish(request: URLRequest, response: HTTPURLResponse?, data: Data) } open class URLSessionOpenAPITransport: OpenAPITransport { @@ -245,7 +245,7 @@ open class URLSessionOpenAPITransport: OpenAPITransport { } .flatMap { output -> AnyPublisher in let response = output.response as? HTTPURLResponse - self.config.delegate?.didFinish(request: request, response: response) + self.config.delegate?.didFinish(request: request, response: response, data: output.data) switch self.config.policy.defineState(for: output.response) { case .success: let OpenAPITransportResponse = OpenAPITransportResponse(data: output.data, statusCode: 200) diff --git a/modules/openapi-generator/src/main/resources/swift-alt/api.mustache b/modules/openapi-generator/src/main/resources/swift-alt/api.mustache index 8f66bf71392c..c07a11a2c71c 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/api.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/api.mustache @@ -30,6 +30,22 @@ open class {{classname}} { } {{#operation}} + {{#allParams}} + {{#isEnum}} + /** + * enum for parameter {{paramName}} + */ + public enum {{enumName}}_{{operationId}}: {{dataType}}, Hashable, Codable, CaseIterable { + {{#allowableValues}} + {{#enumVars}} + case {{name}} = {{{value}}} + {{/enumVars}} + {{/allowableValues}} + } + + {{/isEnum}} + {{/allParams}} + /** {{#summary}} {{{.}}} @@ -67,13 +83,14 @@ open class {{classname}} { .replacingOccurrences(of: "{{=<% %>=}}{<%baseName%>}<%={{ }}=%>", with: "\({{paramName}})") {{/pathParams}} let url = baseURL.appendingPathComponent(path) - {{#hasQueryParams}}var{{/hasQueryParams}}{{^hasQueryParams}}let{{/hasQueryParams}} components = URLComponents(url: url, resolvingAgainstBaseURL: false) - {{#hasQueryParams}}components?.queryItems = [ - {{#queryParams}} - {{! TODO: Convert value to string if needed (can be nil, can be container) }} - URLQueryItem(name: "{{paramName}}", value: {{#isArray}}{{paramName}}{{^required}}?{{/required}}.joined(separator: ", "){{/isArray}}{{^isArray}}{{paramName}}{{/isArray}}){{^-last}}, {{/-last}} - {{/queryParams}} - ]{{/hasQueryParams}} + {{#hasQueryParams}} + // Adding query items + var{{/hasQueryParams}}{{^hasQueryParams}}let{{/hasQueryParams}} components = URLComponents(url: url, resolvingAgainstBaseURL: false) + {{#hasQueryParams}}var queryItems: [URLQueryItem] = [] + {{#queryParams}} + {{#required}}queryItems.append(URLQueryItem(name: "{{paramName}}", value: {{> toString}})){{/required}}{{^required}}if let {{paramName}} = {{paramName}} { queryItems.append(URLQueryItem(name: "{{paramName}}", value: {{> toString}})) } {{/required}} + {{/queryParams}} + components?.queryItems = queryItems{{/hasQueryParams}} guard let requestURL = components?.url else { return Fail(error: OpenAPITransportError.badURLError()) .eraseToAnyPublisher() @@ -81,19 +98,23 @@ open class {{classname}} { var request = URLRequest(url: requestURL) request.httpMethod = "{{httpMethod}}" - {{#hasHeaderParams}}// Setting headers + // Setting headers request.allHTTPHeaderFields = [{{^headerParams}}{{^hasFormParams}} :{{/hasFormParams}}{{/headerParams}}{{#hasFormParams}} "Content-Type": {{^consumes}}"multipart/form-data"{{/consumes}}{{#consumes.0}}"{{{mediaType}}}"{{/consumes.0}},{{/hasFormParams}}{{#headerParams}} {{! TODO: Convert value to string if needed (can be nil, can be container) }} "{{baseName}}": {{paramName}}{{^-last}}, {{/-last}}{{/headerParams}} - ].compactMapValues { $0 }{{/hasHeaderParams}} - {{#hasBodyParam}}{{#bodyParam}}// Setting body parameters {{! TODO: Convert value to data if needed (can be nil, can be Data already) }} + ].compactMapValues { $0 } + {{#hasBodyParam}}{{#bodyParam}}// Setting JSON body request.httpBody = try? {{classname}}.encoder.encode({{paramName}}) - if request.value(forHTTPHeaderField: "Content-Type") == nil { - request.setValue("application/json", forHTTPHeaderField: "Content-Type") - } {{/bodyParam}}{{/hasBodyParam}} + {{#hasFormParams}} // Setting form encoded body + var formEncodedItems: [String] = [] + {{#formParams}} + {{#required}}formEncodedItems.append("{{paramName}}=\({{> toString}})"){{/required}}{{^required}}if let {{paramName}} = {{paramName}} { formEncodedItems.append("{{paramName}}=\({{> toString}})") } {{/required}} + {{/formParams}} + request.httpBody = formEncodedItems.joined(separator: "&").data(using: .utf8) + {{/hasFormParams}} // Getting auth type {{! TODO: Set proper auth type) }} let securitySchemes: [SecurityScheme] = [{{#authMethods}}{{#isBasicBearer}}.bearer{{/isBasicBearer}}{{/authMethods}}] return transport.send(request: request, securitySchemes: securitySchemes) diff --git a/modules/openapi-generator/src/main/resources/swift-alt/toString.mustache b/modules/openapi-generator/src/main/resources/swift-alt/toString.mustache new file mode 100644 index 000000000000..4cfef59c4821 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/swift-alt/toString.mustache @@ -0,0 +1 @@ +{{#isEnum}}{{paramName}}.rawValue{{/isEnum}}{{^isEnum}}{{#isString}}{{paramName}}{{/isString}}{{#isInteger}}"\({{paramName}})"{{/isInteger}}{{#isDouble}}"\({{paramName}})"{{/isDouble}}{{#isFloat}}"\({{paramName}})"{{/isFloat}}{{#isNumber}}"\({{paramName}})"{{/isNumber}}{{#isBoolean}}{{paramName}} ? "true" : "false"{{/isBoolean}}{{#isArray}}{{paramName}}.joined(separator: ", "){{/isArray}}{{/isEnum}} \ No newline at end of file From 22a84abdb45db13683dd973017d0736dfb3d51c6 Mon Sep 17 00:00:00 2001 From: Anton Davydov Date: Tue, 14 Dec 2021 22:48:50 +0300 Subject: [PATCH 08/33] swift-alt fixed array of enums to string --- .../codegen/languages/SwiftAltClientCodegen.java | 7 +++++++ .../src/main/resources/swift-alt/toString.mustache | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java index dfcfd91891c6..22202393e14b 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java @@ -776,6 +776,13 @@ public Map postProcessOperationsWithModels(Map o for (CodegenParameter cp : operation.allParams) { cp.vendorExtensions.put("x-swift-example", constructExampleCode(cp, modelMaps, new HashSet())); } + for (CodegenParameter cp : operation.queryParams) { + if (cp.isArray && modelMaps.get(cp.baseType).isEnum) { + cp.vendorExtensions.put("x-swift-isBaseTypeEnum", true); + } else { + cp.vendorExtensions.put("x-swift-isBaseTypeEnum", false); + } + } if (notCodableTypes.contains(operation.returnType)) { operation.vendorExtensions.put("x-swift-isNotCodable", true); } diff --git a/modules/openapi-generator/src/main/resources/swift-alt/toString.mustache b/modules/openapi-generator/src/main/resources/swift-alt/toString.mustache index 4cfef59c4821..33e8621f47fc 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/toString.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/toString.mustache @@ -1 +1 @@ -{{#isEnum}}{{paramName}}.rawValue{{/isEnum}}{{^isEnum}}{{#isString}}{{paramName}}{{/isString}}{{#isInteger}}"\({{paramName}})"{{/isInteger}}{{#isDouble}}"\({{paramName}})"{{/isDouble}}{{#isFloat}}"\({{paramName}})"{{/isFloat}}{{#isNumber}}"\({{paramName}})"{{/isNumber}}{{#isBoolean}}{{paramName}} ? "true" : "false"{{/isBoolean}}{{#isArray}}{{paramName}}.joined(separator: ", "){{/isArray}}{{/isEnum}} \ No newline at end of file +{{#isEnum}}{{paramName}}.rawValue{{/isEnum}}{{^isEnum}}{{#isString}}{{paramName}}{{/isString}}{{#isInteger}}"\({{paramName}})"{{/isInteger}}{{#isDouble}}"\({{paramName}})"{{/isDouble}}{{#isFloat}}"\({{paramName}})"{{/isFloat}}{{#isNumber}}"\({{paramName}})"{{/isNumber}}{{#isBoolean}}{{paramName}} ? "true" : "false"{{/isBoolean}}{{#isArray}}{{paramName}}{{#vendorExtensions.x-swift-isBaseTypeEnum}}.map { $0.rawValue }{{/vendorExtensions.x-swift-isBaseTypeEnum}}.joined(separator: ", "){{/isArray}}{{/isEnum}} \ No newline at end of file From 040b7ed0f0625ebfec35f6fe40761bc0582695ac Mon Sep 17 00:00:00 2001 From: Anton Davydov Date: Wed, 15 Dec 2021 20:19:04 +0300 Subject: [PATCH 09/33] swift-alt v0.2.0 --- .../languages/SwiftAltClientCodegen.java | 267 +++++------------- .../swift-alt/OpenAPITransport.mustache | 62 +--- .../src/main/resources/swift-alt/api.mustache | 59 +++- .../resources/swift-alt/toString.mustache | 2 +- 4 files changed, 131 insertions(+), 259 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java index 22202393e14b..e6b89c790e7a 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java @@ -19,8 +19,8 @@ import io.swagger.v3.oas.models.media.ArraySchema; import io.swagger.v3.oas.models.media.Schema; +import io.swagger.v3.oas.models.media.StringSchema; import org.apache.commons.io.FilenameUtils; -import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.text.WordUtils; import org.openapitools.codegen.*; @@ -33,12 +33,15 @@ import java.io.File; import java.io.IOException; import java.util.*; +import java.util.function.Function; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.time.OffsetDateTime; import java.time.Instant; import java.time.temporal.ChronoField; import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; +import java.util.stream.Stream; import static org.openapitools.codegen.utils.StringUtils.camelize; @@ -50,15 +53,15 @@ public class SwiftAltClientCodegen extends DefaultCodegen implements CodegenConf protected String privateFolder = "Sources/Private"; protected String sourceFolder = "Sources"; protected String transportFolder = "OpenAPITransport"; - protected List notCodableTypes = Arrays.asList("Any", "AnyObject", "[String: Any]"); + protected List notCodableTypes = Arrays.asList("Any", "AnyObject", "[String: Any]", "[String: [String: Any]"); /** * Constructor for the swift alt language codegen module. */ public SwiftAltClientCodegen() { super(); - this.supportsAdditionalPropertiesWithComposedSchema = true; this.useOneOfInterfaces = true; + this.supportsInheritance = true; generatorMetadata = GeneratorMetadata.newBuilder(generatorMetadata) .stability(Stability.STABLE) @@ -183,6 +186,9 @@ public SwiftAltClientCodegen() { typeMapping.put("file", "Data"); typeMapping.put("binary", "Data"); + instantiationTypes.put("array", "Array"); + instantiationTypes.put("list", "Array"); + importMapping = new HashMap<>(); cliOptions.add(new CliOption(PROJECT_NAME, "Project name in Xcode")); @@ -190,45 +196,6 @@ public SwiftAltClientCodegen() { CliOption libraryOption = new CliOption(CodegenConstants.LIBRARY, "Library template (sub-template) to use"); } - private static CodegenModel reconcileProperties(CodegenModel codegenModel, - CodegenModel parentCodegenModel) { - // To support inheritance in this generator, we will analyze - // the parent and child models, look for properties that match, and remove - // them from the child models and leave them in the parent. - // Because the child models extend the parents, the properties - // will be available via the parent. - - // Get the properties for the parent and child models - final List parentModelCodegenProperties = parentCodegenModel.vars; - List codegenProperties = codegenModel.vars; - codegenModel.allVars = new ArrayList(codegenProperties); - codegenModel.parentVars = parentCodegenModel.allVars; - - // Iterate over all of the parent model properties - boolean removedChildProperty = false; - - for (CodegenProperty parentModelCodegenProperty : parentModelCodegenProperties) { - // Now that we have found a prop in the parent class, - // and search the child class for the same prop. - Iterator iterator = codegenProperties.iterator(); - while (iterator.hasNext()) { - CodegenProperty codegenProperty = iterator.next(); - if (codegenProperty.baseName.equals(parentModelCodegenProperty.baseName)) { - // We found a property in the child class that is - // a duplicate of the one in the parent, so remove it. - iterator.remove(); - removedChildProperty = true; - } - } - } - - if (removedChildProperty) { - codegenModel.vars = codegenProperties; - } - - return codegenModel; - } - @Override public CodegenType getTag() { return CodegenType.CLIENT; @@ -244,25 +211,6 @@ public String getHelp() { return "Generates a Swift 5 alternative client library."; } - @Override - protected void addAdditionPropertiesToCodeGenModel(CodegenModel codegenModel, - Schema schema) { - - final Schema additionalProperties = getAdditionalProperties(schema); - - if (additionalProperties != null) { - Schema inner = null; - if (ModelUtils.isArraySchema(schema)) { - ArraySchema ap = (ArraySchema) schema; - inner = ap.getItems(); - } else if (ModelUtils.isMapSchema(schema)) { - inner = getAdditionalProperties(schema); - } - - codegenModel.additionalPropertiesType = inner != null ? getTypeDeclaration(inner) : getSchemaType(additionalProperties); - } - } - @Override public void processOpts() { super.processOpts(); @@ -320,15 +268,23 @@ public String apiFileFolder() { @Override public String getTypeDeclaration(Schema p) { - if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); - return ModelUtils.isSet(p) ? "Set<" + getTypeDeclaration(inner) + ">" : "[" + getTypeDeclaration(inner) + "]"; - } else if (ModelUtils.isMapSchema(p)) { - Schema inner = getAdditionalProperties(p); + Schema schema = ModelUtils.unaliasSchema(this.openAPI, p, importMapping); + Schema target = ModelUtils.isGenerateAliasAsModel() ? p : schema; + if (ModelUtils.isArraySchema(target)) { + Schema items = getSchemaItems((ArraySchema) schema); + return ModelUtils.isSet(target) ? "Set<" + getTypeDeclaration(items) + ">" : "[" + getTypeDeclaration(items) + "]"; + } else if (ModelUtils.isMapSchema(target)) { + // Note: ModelUtils.isMapSchema(p) returns true when p is a composed schema that also defines + // additionalproperties: true + Schema inner = getAdditionalProperties(target); + if (inner == null) { + LOGGER.error("`{}` (map property) does not have a proper inner type defined. Default to type:string", p.getName()); + inner = new StringSchema().description("TODO default missing map inner type to string"); + p.setAdditionalProperties(inner); + } return "[String: " + getTypeDeclaration(inner) + "]"; } - return super.getTypeDeclaration(p); + return super.getTypeDeclaration(target); } @Override @@ -553,27 +509,26 @@ public String toParamName(String name) { } @Override - public CodegenModel fromModel(String name, Schema model) { - Map allDefinitions = ModelUtils.getSchemas(this.openAPI); - CodegenModel codegenModel = super.fromModel(name, model); - if (codegenModel.description != null) { - codegenModel.imports.add("ApiModel"); - } - if (allDefinitions != null) { - String parentSchema = codegenModel.parentSchema; - - // multilevel inheritance: reconcile properties of all the parents - while (parentSchema != null) { - final Schema parentModel = allDefinitions.get(parentSchema); - final CodegenModel parentCodegenModel = super.fromModel(codegenModel.parent, - parentModel); - codegenModel = SwiftAltClientCodegen.reconcileProperties(codegenModel, parentCodegenModel); - - // get the next parent - parentSchema = parentCodegenModel.parentSchema; - } - } - return codegenModel; + public CodegenModel fromModel(String name, Schema schema) { + CodegenModel m = super.fromModel(name, schema); + m.optionalVars = m.optionalVars.stream().distinct().collect(Collectors.toList()); + // Update allVars/requiredVars/optionalVars with isInherited + // Each of these lists contains elements that are similar, but they are all cloned + // via CodegenModel.removeAllDuplicatedProperty and therefore need to be updated + // separately. + // First find only the parent vars via baseName matching + Map allVarsMap = m.allVars.stream() + .collect(Collectors.toMap(CodegenProperty::getBaseName, Function.identity())); + allVarsMap.keySet() + .removeAll(m.vars.stream().map(CodegenProperty::getBaseName).collect(Collectors.toSet())); + // Update the allVars + allVarsMap.values().forEach(p -> p.isInherited = true); + // Update any other vars (requiredVars, optionalVars) + Stream.of(m.requiredVars, m.optionalVars) + .flatMap(List::stream) + .filter(p -> allVarsMap.containsKey(p.baseName)) + .forEach(p -> p.isInherited = true); + return m; } public void setProjectName(String projectName) { @@ -773,127 +728,35 @@ public Map postProcessOperationsWithModels(Map o List operations = (List) objectMap.get("operation"); for (CodegenOperation operation : operations) { - for (CodegenParameter cp : operation.allParams) { - cp.vendorExtensions.put("x-swift-example", constructExampleCode(cp, modelMaps, new HashSet())); + operation.allParams.forEach(cp -> addVendorExtensions(cp, operation, modelMaps)); + operation.queryParams.forEach(cp -> addVendorExtensions(cp, operation, modelMaps)); + operation.bodyParams.forEach(cp -> addVendorExtensions(cp, operation, modelMaps)); + operation.formParams.forEach(cp -> addVendorExtensions(cp, operation, modelMaps)); + if (notCodableTypes.contains(operation.returnType) || notCodableTypes.contains(operation.returnBaseType)) { + operation.vendorExtensions.put("x-swift-is-not-codable", true); } - for (CodegenParameter cp : operation.queryParams) { - if (cp.isArray && modelMaps.get(cp.baseType).isEnum) { - cp.vendorExtensions.put("x-swift-isBaseTypeEnum", true); - } else { - cp.vendorExtensions.put("x-swift-isBaseTypeEnum", false); + List responses = operation.responses; + for (CodegenResponse response : responses) { + if (response.is4xx || response.is5xx) { + response.vendorExtensions.put("x-swift-has-custom-error-type", true); + response.vendorExtensions.put("x-swift-custom-error-type", WordUtils.capitalize(operation.operationId) + "Error"); + operation.vendorExtensions.put("x-swift-custom-error-type", WordUtils.capitalize(operation.operationId) + "Error"); } - } - if (notCodableTypes.contains(operation.returnType)) { - operation.vendorExtensions.put("x-swift-isNotCodable", true); + response.vendorExtensions.put("x-swift-is-response-code-explicit", !response.code.contains("x")); } } return objs; } - public String constructExampleCode(CodegenParameter codegenParameter, HashMap modelMaps, Set visitedModels) { - if (codegenParameter.isArray) { // array - return "[" + constructExampleCode(codegenParameter.items, modelMaps, visitedModels) + "]"; - } else if (codegenParameter.isMap) { // TODO: map, file type - return "\"TODO\""; - } else if (languageSpecificPrimitives.contains(codegenParameter.dataType)) { // primitive type - if ("String".equals(codegenParameter.dataType) || "Character".equals(codegenParameter.dataType)) { - if (StringUtils.isEmpty(codegenParameter.example)) { - return "\"" + codegenParameter.example + "\""; - } else { - return "\"" + codegenParameter.paramName + "_example\""; - } - } else if ("Bool".equals(codegenParameter.dataType)) { // boolean - if (Boolean.parseBoolean(codegenParameter.example)) { - return "true"; - } else { - return "false"; - } - } else if ("URL".equals(codegenParameter.dataType)) { // URL - return "URL(string: \"https://example.com\")!"; - } else if ("Data".equals(codegenParameter.dataType)) { // URL - return "Data([9, 8, 7])"; - } else if ("Date".equals(codegenParameter.dataType)) { // date - return "Date()"; - } else { // numeric - if (StringUtils.isEmpty(codegenParameter.example)) { - return codegenParameter.example; - } else { - return "987"; - } - } - } else { // model - // look up the model - if (modelMaps.containsKey(codegenParameter.dataType)) { - if (visitedModels.contains(codegenParameter.dataType)) { - // recursive/self-referencing model, simply return nil to avoid stackoverflow - return "nil"; - } else { - visitedModels.add(codegenParameter.dataType); - return constructExampleCode(modelMaps.get(codegenParameter.dataType), modelMaps, visitedModels); - } - } else { - //LOGGER.error("Error in constructing examples. Failed to look up the model " + codegenParameter.dataType); - return "TODO"; - } - } - } - - public String constructExampleCode(CodegenProperty codegenProperty, HashMap modelMaps, Set visitedModels) { - if (codegenProperty.isArray) { // array - return "[" + constructExampleCode(codegenProperty.items, modelMaps, visitedModels) + "]"; - } else if (codegenProperty.isMap) { // TODO: map, file type - return "\"TODO\""; - } else if (languageSpecificPrimitives.contains(codegenProperty.dataType)) { // primitive type - if ("String".equals(codegenProperty.dataType) || "Character".equals(codegenProperty.dataType)) { - if (StringUtils.isEmpty(codegenProperty.example)) { - return "\"" + codegenProperty.example + "\""; - } else { - return "\"" + codegenProperty.name + "_example\""; - } - } else if ("Bool".equals(codegenProperty.dataType)) { // boolean - if (Boolean.parseBoolean(codegenProperty.example)) { - return "true"; - } else { - return "false"; - } - } else if ("URL".equals(codegenProperty.dataType)) { // URL - return "URL(string: \"https://example.com\")!"; - } else if ("Date".equals(codegenProperty.dataType)) { // date - return "Date()"; - } else { // numeric - if (StringUtils.isEmpty(codegenProperty.example)) { - return codegenProperty.example; - } else { - return "123"; - } - } - } else { - // look up the model - if (modelMaps.containsKey(codegenProperty.dataType)) { - if (visitedModels.contains(codegenProperty.dataType)) { - // recursive/self-referencing model, simply return nil to avoid stackoverflow - return "nil"; - } else { - visitedModels.add(codegenProperty.dataType); - return constructExampleCode(modelMaps.get(codegenProperty.dataType), modelMaps, visitedModels); - } - } else { - //LOGGER.error("Error in constructing examples. Failed to look up the model " + codegenProperty.dataType); - return "\"TODO\""; - } + protected void addVendorExtensions(CodegenParameter cp, CodegenOperation operation, HashMap modelMaps) { + cp.vendorExtensions.put("x-swift-is-base-type-enum", cp.isArray && modelMaps.get(cp.baseType).isEnum); + if (cp.isEnum) { + cp.vendorExtensions.put("x-swift-nested-enum-type", WordUtils.capitalize(operation.operationId) + WordUtils.capitalize(cp.enumName)); } - } - - public String constructExampleCode(CodegenModel codegenModel, HashMap modelMaps, Set visitedModels) { - String example; - example = codegenModel.name + "("; - List propertyExamples = new ArrayList<>(); - for (CodegenProperty codegenProperty : codegenModel.vars) { - propertyExamples.add(codegenProperty.name + ": " + constructExampleCode(codegenProperty, modelMaps, visitedModels)); + CodegenModel model = modelMaps.get(cp.dataType); + if (cp.isEnum || (model != null && model.isEnum)) { + cp.vendorExtensions.put("x-swift-is-enum-type", true); } - example += StringUtils.join(propertyExamples, ", "); - example += ")"; - return example; } @Override @@ -901,7 +764,7 @@ public void postProcess() { System.out.println("################################################################################"); System.out.println("# Thanks for using OpenAPI Generator. #"); System.out.println("# swift alternative generator is contributed by @dydus0x14 and @ptiz. #"); - System.out.println("# swift alternative generator v0.1.0 #"); + System.out.println("# swift alternative generator v0.2.0 #"); System.out.println("################################################################################"); } } diff --git a/modules/openapi-generator/src/main/resources/swift-alt/OpenAPITransport.mustache b/modules/openapi-generator/src/main/resources/swift-alt/OpenAPITransport.mustache index 872552f508f2..3b36c0f9a4cf 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/OpenAPITransport.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/OpenAPITransport.mustache @@ -12,30 +12,6 @@ public enum SecurityScheme { // Security schemes not supported yet https://swagger.io/docs/specification/authentication/ } -// MARK: - Authenticator - -// Class which is able to add authentication headers and refresh authentication -public protocol Authenticator { - func authenticate(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher - func refresh(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher -} - -final class DefaultAuthenticator: Authenticator { - func authenticate(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher { - Just(request) - .setFailureType(to: OpenAPITransportError.self) - .eraseToAnyPublisher() - } - - func refresh(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher { - Fail(outputType: Void.self, failure: OpenAPITransportError.failedAuthenticationRefreshError()) - .eraseToAnyPublisher() - } - - init() { - } -} - // MARK: - Policy /// Policy to define whether response is successful or requires authentication @@ -44,18 +20,19 @@ public protocol URLResponsePolicy { } public enum URLResponseState { + // Return success to client case success + // Return error to client case failure - case requiresAuthentication + // Repeat request + case retry } final class DefaultURLResponsePolicy: URLResponsePolicy { func defineState(for response: URLResponse) -> URLResponseState { switch (response as? HTTPURLResponse)?.statusCode { - case .some(200): + case .some(200...299): return .success - case .some(401): - return .requiresAuthentication default: return .failure } @@ -65,13 +42,13 @@ final class DefaultURLResponsePolicy: URLResponsePolicy { /// Define how to customize URL request before network call public protocol URLRequestProcessor { /// Customize request before performing. Add headers or encrypt body for example. - func enrich(request: URLRequest) -> AnyPublisher + func enrich(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher /// Customize response before handling. Decrypt body for example. func decode(output: URLSession.DataTaskPublisher.Output) -> AnyPublisher } final class DefaultURLRequestProcessor: URLRequestProcessor { - func enrich(request: URLRequest) -> AnyPublisher { + func enrich(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher { Just(request) .setFailureType(to: OpenAPITransportError.self) .eraseToAnyPublisher() @@ -227,14 +204,8 @@ open class URLSessionOpenAPITransport: OpenAPITransport { ) -> AnyPublisher { config.processor - // Add custom headers or if needed - .enrich(request: request) - // Add authentication headers if needed before request - .flatMap { request in - self.config.authenticator - .authenticate(request: request, securitySchemes: securitySchemes) - .eraseToAnyPublisher() - } + // Add custom headers or refresh token if needed + .enrich(request: request, securitySchemes: securitySchemes) .flatMap { request -> AnyPublisher in self.config.delegate?.willStart(request: request) // Perform network call @@ -250,17 +221,9 @@ open class URLSessionOpenAPITransport: OpenAPITransport { case .success: let OpenAPITransportResponse = OpenAPITransportResponse(data: output.data, statusCode: 200) return Result.success(OpenAPITransportResponse).publisher.eraseToAnyPublisher() - case .requiresAuthentication: - // Refresh authentication if possible - return self.config.authenticator - .refresh(request: request, securitySchemes: securitySchemes) - .flatMap { - // Try performing network call again - self.send(request: request, securitySchemes: securitySchemes) - } - .eraseToAnyPublisher() - // TODO: Check too many attempts error - default: + case .retry: + return self.send(request: request, securitySchemes: securitySchemes) + case .failure: let code = response?.statusCode ?? OpenAPITransportError.noResponseCode let error = OpenAPITransportError(statusCode: code, data: output.data) return Fail(error: error).eraseToAnyPublisher() @@ -280,7 +243,6 @@ public extension URLSessionOpenAPITransport { struct Config { public var baseURL: URL? = nil public var session: URLSession = .shared - public var authenticator: Authenticator = DefaultAuthenticator() public var processor: URLRequestProcessor = DefaultURLRequestProcessor() public var policy: URLResponsePolicy = DefaultURLResponsePolicy() public weak var delegate: URLSessionOpenAPITransportDelegate? diff --git a/modules/openapi-generator/src/main/resources/swift-alt/api.mustache b/modules/openapi-generator/src/main/resources/swift-alt/api.mustache index c07a11a2c71c..065a0ddcaa98 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/api.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/api.mustache @@ -35,7 +35,7 @@ open class {{classname}} { /** * enum for parameter {{paramName}} */ - public enum {{enumName}}_{{operationId}}: {{dataType}}, Hashable, Codable, CaseIterable { + public enum {{{vendorExtensions.x-swift-nested-enum-type}}}: {{dataType}}, Hashable, Codable, CaseIterable { {{#allowableValues}} {{#enumVars}} case {{name}} = {{{value}}} @@ -46,6 +46,28 @@ open class {{classname}} { {{/isEnum}} {{/allParams}} + {{#vendorExtensions.x-swift-custom-error-type}} + public enum {{{vendorExtensions.x-swift-custom-error-type}}}: Error, CustomStringConvertible { + {{#responses}} + {{#vendorExtensions.x-swift-has-custom-error-type}} + // {{{message}}} + case code{{{code}}}Error{{#dataType}}({{{dataType}}}){{/dataType}} + {{/vendorExtensions.x-swift-has-custom-error-type}} + {{/responses}} + + public var description: String { + switch self { + {{#responses}} + {{#vendorExtensions.x-swift-has-custom-error-type}} + case .code{{{code}}}Error{{#dataType}}(let object){{/dataType}}: + return "{{{vendorExtensions.x-swift-custom-error-type}}}: {{{message}}}{{#dataType}}: \(object){{/dataType}}" + {{/vendorExtensions.x-swift-has-custom-error-type}} + {{/responses}} + } + } + } + {{/vendorExtensions.x-swift-custom-error-type}} + /** {{#summary}} {{{.}}} @@ -70,7 +92,7 @@ open class {{classname}} { {{/allParams}} - returns: AnyPublisher<{{{returnType}}}{{^returnType}}Void{{/returnType}}, Error> {{description}} */ - open func {{operationId}}({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}) -> AnyPublisher<{{{returnType}}}{{^returnType}}Void{{/returnType}}, Error> { + open func {{operationId}}({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{vendorExtensions.x-swift-nested-enum-type}}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}) -> AnyPublisher<{{{returnType}}}{{^returnType}}Void{{/returnType}}, Error> { // Creating final URL with query items and path guard let baseURL = transport.baseURL ?? self.baseURL else { return Fail(error: OpenAPITransportError.badURLError()) @@ -107,6 +129,9 @@ open class {{classname}} { ].compactMapValues { $0 } {{#hasBodyParam}}{{#bodyParam}}// Setting JSON body request.httpBody = try? {{classname}}.encoder.encode({{paramName}}) + if request.value(forHTTPHeaderField: "Content-Type") == nil { + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + } {{/bodyParam}}{{/hasBodyParam}} {{#hasFormParams}} // Setting form encoded body var formEncodedItems: [String] = [] @@ -118,19 +143,41 @@ open class {{classname}} { // Getting auth type {{! TODO: Set proper auth type) }} let securitySchemes: [SecurityScheme] = [{{#authMethods}}{{#isBasicBearer}}.bearer{{/isBasicBearer}}{{/authMethods}}] return transport.send(request: request, securitySchemes: securitySchemes) + {{#vendorExtensions.x-swift-custom-error-type}} + .mapError { transportError -> Error in + {{#responses}} + {{#vendorExtensions.x-swift-has-custom-error-type}} + if transportError.statusCode == {{{code}}} { + {{#dataType}} + do { + let error = try {{classname}}.decoder.decode({{{dataType}}}.self, from: transportError.data) + return {{{vendorExtensions.x-swift-custom-error-type}}}.code{{{code}}}Error(error) + } catch { + return error + } + {{/dataType}} + {{^dataType}} + return {{{vendorExtensions.x-swift-custom-error-type}}}.code{{{code}}}Error + {{/dataType}} + } + {{/vendorExtensions.x-swift-has-custom-error-type}} + {{/responses}} + return transportError + } + {{/vendorExtensions.x-swift-custom-error-type}} .tryMap { response in {{! TODO: Check responses properly }} {{#returnType}} - {{#vendorExtensions.x-swift-isNotCodable}} + {{#vendorExtensions.x-swift-is-not-codable}} if let object = try JSONSerialization.jsonObject(with: response.data, options: []) as? {{{returnType}}} { return object } else { throw OpenAPITransportError.invalidResponseMappingError(data: response.data) } - {{/vendorExtensions.x-swift-isNotCodable}} - {{^vendorExtensions.x-swift-isNotCodable}} + {{/vendorExtensions.x-swift-is-not-codable}} + {{^vendorExtensions.x-swift-is-not-codable}} try {{classname}}.decoder.decode({{{returnType}}}.self, from: response.data) - {{/vendorExtensions.x-swift-isNotCodable}} + {{/vendorExtensions.x-swift-is-not-codable}} {{/returnType}} {{^returnType}} return () diff --git a/modules/openapi-generator/src/main/resources/swift-alt/toString.mustache b/modules/openapi-generator/src/main/resources/swift-alt/toString.mustache index 33e8621f47fc..6fe4f1e27a98 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/toString.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/toString.mustache @@ -1 +1 @@ -{{#isEnum}}{{paramName}}.rawValue{{/isEnum}}{{^isEnum}}{{#isString}}{{paramName}}{{/isString}}{{#isInteger}}"\({{paramName}})"{{/isInteger}}{{#isDouble}}"\({{paramName}})"{{/isDouble}}{{#isFloat}}"\({{paramName}})"{{/isFloat}}{{#isNumber}}"\({{paramName}})"{{/isNumber}}{{#isBoolean}}{{paramName}} ? "true" : "false"{{/isBoolean}}{{#isArray}}{{paramName}}{{#vendorExtensions.x-swift-isBaseTypeEnum}}.map { $0.rawValue }{{/vendorExtensions.x-swift-isBaseTypeEnum}}.joined(separator: ", "){{/isArray}}{{/isEnum}} \ No newline at end of file +{{#vendorExtensions.x-swift-is-enum-type}}{{paramName}}.rawValue{{/vendorExtensions.x-swift-is-enum-type}}{{^isEnum}}{{#isString}}{{paramName}}{{/isString}}{{#isInteger}}"\({{paramName}})"{{/isInteger}}{{#isDouble}}"\({{paramName}})"{{/isDouble}}{{#isFloat}}"\({{paramName}})"{{/isFloat}}{{#isNumber}}"\({{paramName}})"{{/isNumber}}{{#isBoolean}}{{paramName}} ? "true" : "false"{{/isBoolean}}{{#isArray}}{{paramName}}{{#vendorExtensions.x-swift-is-base-type-enum}}.map { $0.rawValue }{{/vendorExtensions.x-swift-is-base-type-enum}}.joined(separator: ", "){{/isArray}}{{/isEnum}} \ No newline at end of file From cf1379d3eac769a7b0230e6fde2d20dfa14dc79c Mon Sep 17 00:00:00 2001 From: Anton Davydov Date: Sun, 9 Jan 2022 00:36:56 +0300 Subject: [PATCH 10/33] swift-alt v0.3.0 --- .../languages/SwiftAltClientCodegen.java | 14 +--- .../swift-alt/OpenAPITransport.mustache | 42 +++++----- .../src/main/resources/swift-alt/api.mustache | 38 ++++----- .../main/resources/swift-alt/model.mustache | 5 +- .../resources/swift-alt/modelObject.mustache | 21 ----- .../swift-alt/modelObjectCustom.mustache | 83 +++++++++++++++++++ 6 files changed, 129 insertions(+), 74 deletions(-) create mode 100644 modules/openapi-generator/src/main/resources/swift-alt/modelObjectCustom.mustache diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java index e6b89c790e7a..cfcc7a538d30 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java @@ -664,15 +664,9 @@ public Map postProcessModels(Map objs) { @Override public void postProcessModelProperty(CodegenModel model, CodegenProperty property) { super.postProcessModelProperty(model, property); - - boolean isSwiftScalarType = property.isInteger || property.isLong || property.isFloat - || property.isDouble || property.isBoolean; - if ((!property.required || property.isNullable) && isSwiftScalarType) { - // Optional scalar types like Int?, Int64?, Float?, Double?, and Bool? - // do not translate to Objective-C. So we want to flag those - // properties in case we want to put special code in the templates - // which provide Objective-C compatibility. - property.vendorExtensions.put("x-swift-optional-scalar", true); + if (notCodableTypes.contains(property.dataType) || notCodableTypes.contains(property.baseType)) { + property.vendorExtensions.put("x-swift-is-not-codable", true); + model.vendorExtensions.put("x-swift-contains-not-codable", true); } } @@ -764,7 +758,7 @@ public void postProcess() { System.out.println("################################################################################"); System.out.println("# Thanks for using OpenAPI Generator. #"); System.out.println("# swift alternative generator is contributed by @dydus0x14 and @ptiz. #"); - System.out.println("# swift alternative generator v0.2.0 #"); + System.out.println("# swift alternative generator v0.3.0 #"); System.out.println("################################################################################"); } } diff --git a/modules/openapi-generator/src/main/resources/swift-alt/OpenAPITransport.mustache b/modules/openapi-generator/src/main/resources/swift-alt/OpenAPITransport.mustache index 3b36c0f9a4cf..10be9a517283 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/OpenAPITransport.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/OpenAPITransport.mustache @@ -16,7 +16,7 @@ public enum SecurityScheme { /// Policy to define whether response is successful or requires authentication public protocol URLResponsePolicy { - func defineState(for response: URLResponse) -> URLResponseState + func defineState(for request: URLRequest, output: URLSession.DataTaskPublisher.Output) -> AnyPublisher } public enum URLResponseState { @@ -29,13 +29,13 @@ public enum URLResponseState { } final class DefaultURLResponsePolicy: URLResponsePolicy { - func defineState(for response: URLResponse) -> URLResponseState { - switch (response as? HTTPURLResponse)?.statusCode { - case .some(200...299): - return .success - default: - return .failure + func defineState(for request: URLRequest, output: URLSession.DataTaskPublisher.Output) -> AnyPublisher { + let state: URLResponseState + switch (output.response as? HTTPURLResponse)?.statusCode { + case .some(200...299): state = .success + default: state = .failure } + return Just(state).eraseToAnyPublisher() } } @@ -191,7 +191,7 @@ public protocol URLSessionOpenAPITransportDelegate: AnyObject { open class URLSessionOpenAPITransport: OpenAPITransport { private var cancellable = Set() - private let config: Config + public var config: Config public var baseURL: URL? { config.baseURL } public init(config: Config = .init()) { @@ -217,17 +217,21 @@ open class URLSessionOpenAPITransport: OpenAPITransport { .flatMap { output -> AnyPublisher in let response = output.response as? HTTPURLResponse self.config.delegate?.didFinish(request: request, response: response, data: output.data) - switch self.config.policy.defineState(for: output.response) { - case .success: - let OpenAPITransportResponse = OpenAPITransportResponse(data: output.data, statusCode: 200) - return Result.success(OpenAPITransportResponse).publisher.eraseToAnyPublisher() - case .retry: - return self.send(request: request, securitySchemes: securitySchemes) - case .failure: - let code = response?.statusCode ?? OpenAPITransportError.noResponseCode - let error = OpenAPITransportError(statusCode: code, data: output.data) - return Fail(error: error).eraseToAnyPublisher() - } + return self.config.policy.defineState(for: request, output: output) + .setFailureType(to: OpenAPITransportError.self) + .flatMap { state -> AnyPublisher in + switch state { + case .success: + let transportResponse = OpenAPITransportResponse(data: output.data, statusCode: 200) + return Result.success(transportResponse).publisher.eraseToAnyPublisher() + case .retry: + return self.send(request: request, securitySchemes: securitySchemes) + case .failure: + let code = response?.statusCode ?? OpenAPITransportError.noResponseCode + let transportError = OpenAPITransportError(statusCode: code, data: output.data) + return Fail(error: transportError).eraseToAnyPublisher() + } + }.eraseToAnyPublisher() } .eraseToAnyPublisher() } diff --git a/modules/openapi-generator/src/main/resources/swift-alt/api.mustache b/modules/openapi-generator/src/main/resources/swift-alt/api.mustache index 065a0ddcaa98..04ee17c27df6 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/api.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/api.mustache @@ -11,19 +11,19 @@ import OpenAPITransport {{#description}} /** {{{.}}} */{{/description}} open class {{classname}} { - private static let encoder: JSONEncoder = { + private let transport: OpenAPITransport + public var encoder: JSONEncoder = { let encoder = JSONEncoder() encoder.dateEncodingStrategy = .formatted(OpenISO8601DateFormatter()) encoder.outputFormatting = .prettyPrinted return encoder }() - private static let decoder: JSONDecoder = { + public var decoder: JSONDecoder = { let decoder = JSONDecoder() decoder.dateDecodingStrategy = .formatted(OpenISO8601DateFormatter()) return decoder }() - private let transport: OpenAPITransport - public let baseURL = URL(string: "{{{basePath}}}") + public var baseURL = URL(string: "{{{basePath}}}") public init(_ transport: OpenAPITransport) { self.transport = transport @@ -93,54 +93,49 @@ open class {{classname}} { - returns: AnyPublisher<{{{returnType}}}{{^returnType}}Void{{/returnType}}, Error> {{description}} */ open func {{operationId}}({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{vendorExtensions.x-swift-nested-enum-type}}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}) -> AnyPublisher<{{{returnType}}}{{^returnType}}Void{{/returnType}}, Error> { - // Creating final URL with query items and path guard let baseURL = transport.baseURL ?? self.baseURL else { return Fail(error: OpenAPITransportError.badURLError()) .eraseToAnyPublisher() } - let path = "{{path}}" {{#pathParams}} - {{! TODO: Convert param name to string if needed (can be nil, can be container) }} .replacingOccurrences(of: "{{=<% %>=}}{<%baseName%>}<%={{ }}=%>", with: "\({{paramName}})") {{/pathParams}} let url = baseURL.appendingPathComponent(path) + {{#hasQueryParams}}var{{/hasQueryParams}}{{^hasQueryParams}}let{{/hasQueryParams}} components = URLComponents(url: url, resolvingAgainstBaseURL: false) {{#hasQueryParams}} - // Adding query items - var{{/hasQueryParams}}{{^hasQueryParams}}let{{/hasQueryParams}} components = URLComponents(url: url, resolvingAgainstBaseURL: false) - {{#hasQueryParams}}var queryItems: [URLQueryItem] = [] + var queryItems: [URLQueryItem] = [] {{#queryParams}} {{#required}}queryItems.append(URLQueryItem(name: "{{paramName}}", value: {{> toString}})){{/required}}{{^required}}if let {{paramName}} = {{paramName}} { queryItems.append(URLQueryItem(name: "{{paramName}}", value: {{> toString}})) } {{/required}} {{/queryParams}} - components?.queryItems = queryItems{{/hasQueryParams}} + components?.queryItems = queryItems + {{/hasQueryParams}} guard let requestURL = components?.url else { return Fail(error: OpenAPITransportError.badURLError()) .eraseToAnyPublisher() } - var request = URLRequest(url: requestURL) request.httpMethod = "{{httpMethod}}" - // Setting headers request.allHTTPHeaderFields = [{{^headerParams}}{{^hasFormParams}} :{{/hasFormParams}}{{/headerParams}}{{#hasFormParams}} "Content-Type": {{^consumes}}"multipart/form-data"{{/consumes}}{{#consumes.0}}"{{{mediaType}}}"{{/consumes.0}},{{/hasFormParams}}{{#headerParams}} - {{! TODO: Convert value to string if needed (can be nil, can be container) }} "{{baseName}}": {{paramName}}{{^-last}}, {{/-last}}{{/headerParams}} ].compactMapValues { $0 } - {{#hasBodyParam}}{{#bodyParam}}// Setting JSON body - request.httpBody = try? {{classname}}.encoder.encode({{paramName}}) + {{#hasBodyParam}} + {{#bodyParam}} + request.httpBody = try? encoder.encode({{paramName}}) if request.value(forHTTPHeaderField: "Content-Type") == nil { request.setValue("application/json", forHTTPHeaderField: "Content-Type") } - {{/bodyParam}}{{/hasBodyParam}} - {{#hasFormParams}} // Setting form encoded body + {{/bodyParam}} + {{/hasBodyParam}} + {{#hasFormParams}} var formEncodedItems: [String] = [] {{#formParams}} {{#required}}formEncodedItems.append("{{paramName}}=\({{> toString}})"){{/required}}{{^required}}if let {{paramName}} = {{paramName}} { formEncodedItems.append("{{paramName}}=\({{> toString}})") } {{/required}} {{/formParams}} request.httpBody = formEncodedItems.joined(separator: "&").data(using: .utf8) {{/hasFormParams}} - // Getting auth type {{! TODO: Set proper auth type) }} let securitySchemes: [SecurityScheme] = [{{#authMethods}}{{#isBasicBearer}}.bearer{{/isBasicBearer}}{{/authMethods}}] return transport.send(request: request, securitySchemes: securitySchemes) {{#vendorExtensions.x-swift-custom-error-type}} @@ -150,7 +145,7 @@ open class {{classname}} { if transportError.statusCode == {{{code}}} { {{#dataType}} do { - let error = try {{classname}}.decoder.decode({{{dataType}}}.self, from: transportError.data) + let error = try self.decoder.decode({{{dataType}}}.self, from: transportError.data) return {{{vendorExtensions.x-swift-custom-error-type}}}.code{{{code}}}Error(error) } catch { return error @@ -166,7 +161,6 @@ open class {{classname}} { } {{/vendorExtensions.x-swift-custom-error-type}} .tryMap { response in - {{! TODO: Check responses properly }} {{#returnType}} {{#vendorExtensions.x-swift-is-not-codable}} if let object = try JSONSerialization.jsonObject(with: response.data, options: []) as? {{{returnType}}} { @@ -176,7 +170,7 @@ open class {{classname}} { } {{/vendorExtensions.x-swift-is-not-codable}} {{^vendorExtensions.x-swift-is-not-codable}} - try {{classname}}.decoder.decode({{{returnType}}}.self, from: response.data) + try self.decoder.decode({{{returnType}}}.self, from: response.data) {{/vendorExtensions.x-swift-is-not-codable}} {{/returnType}} {{^returnType}} diff --git a/modules/openapi-generator/src/main/resources/swift-alt/model.mustache b/modules/openapi-generator/src/main/resources/swift-alt/model.mustache index 575acb79c0f8..095cbabf12f0 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/model.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/model.mustache @@ -11,5 +11,6 @@ import Foundation {{#vendorExtensions.x-is-one-of-interface}} {{> modelOneOf}}{{/vendorExtensions.x-is-one-of-interface}}{{^vendorExtensions.x-is-one-of-interface}}{{#isArray}} {{> modelArray}}{{/isArray}}{{^isArray}}{{#isEnum}} -{{> modelEnum}}{{/isEnum}}{{^isEnum}} -{{> modelObject}}{{/isEnum}}{{/isArray}}{{/vendorExtensions.x-is-one-of-interface}}{{/model}}{{/models}} \ No newline at end of file +{{> modelEnum}}{{/isEnum}}{{^isEnum}}{{#vendorExtensions.x-swift-contains-not-codable}} +{{> modelObjectCustom}}{{/vendorExtensions.x-swift-contains-not-codable}}{{^vendorExtensions.x-swift-contains-not-codable}} +{{> modelObject}}{{/vendorExtensions.x-swift-contains-not-codable}}{{/isEnum}}{{/isArray}}{{/vendorExtensions.x-is-one-of-interface}}{{/model}}{{/models}} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/swift-alt/modelObject.mustache b/modules/openapi-generator/src/main/resources/swift-alt/modelObject.mustache index f1909aae9208..2d37f62b8b93 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/modelObject.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/modelObject.mustache @@ -22,25 +22,4 @@ public struct {{{classname}}}: Codable, Hashable { {{/allVars}} } {{/hasVars}} - - public enum CodingKeys: {{#hasVars}}String, {{/hasVars}}CodingKey, CaseIterable { - {{#allVars}} - case {{{name}}}{{#vendorExtensions.x-codegen-escaped-property-name}} = "{{{baseName}}}"{{/vendorExtensions.x-codegen-escaped-property-name}} - {{/allVars}} - } - - // Encodable protocol methods - - public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - {{#allVars}} - try container.encode{{^required}}IfPresent{{/required}}({{{name}}}, forKey: .{{{name}}}) - {{/allVars}} - {{#generateModelAdditionalProperties}} - {{#additionalPropertiesType}} - var additionalPropertiesContainer = encoder.container(keyedBy: String.self) - try additionalPropertiesContainer.encodeMap(additionalProperties) - {{/additionalPropertiesType}} - {{/generateModelAdditionalProperties}} - } } diff --git a/modules/openapi-generator/src/main/resources/swift-alt/modelObjectCustom.mustache b/modules/openapi-generator/src/main/resources/swift-alt/modelObjectCustom.mustache new file mode 100644 index 000000000000..2a5c3065847a --- /dev/null +++ b/modules/openapi-generator/src/main/resources/swift-alt/modelObjectCustom.mustache @@ -0,0 +1,83 @@ +public struct {{{classname}}}: Codable { +{{#allVars}} +{{#isEnum}} +{{> modelInlineEnumDeclaration}} +{{/isEnum}} +{{/allVars}} +{{#allVars}} +{{#isEnum}} + {{#description}}/** {{{.}}} */ + {{/description}}public var {{{name}}}: {{{datatypeWithEnum}}}{{#required}}{{#isNullable}}?{{/isNullable}}{{/required}}{{^required}}?{{/required}}{{#defaultValue}} = {{{.}}}{{/defaultValue}} +{{/isEnum}} +{{^isEnum}} + {{#description}}/** {{{.}}} */ + {{/description}}public var {{{name}}}: {{{datatype}}}{{#required}}{{#isNullable}}?{{/isNullable}}{{/required}}{{^required}}?{{/required}}{{#defaultValue}} = {{{.}}}{{/defaultValue}} +{{/isEnum}} +{{/allVars}} +{{#hasVars}} + + public init({{#allVars}}{{{name}}}: {{{datatypeWithEnum}}}{{#required}}{{#isNullable}}?{{/isNullable}}{{/required}}{{^required}}?{{/required}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}{{^defaultValue}}{{^required}} = nil{{/required}}{{/defaultValue}}{{^-last}}, {{/-last}}{{/allVars}}) { + {{#allVars}} + self.{{{name}}} = {{{name}}} + {{/allVars}} + } +{{/hasVars}} + + public enum CodingKeys: {{#hasVars}}String, {{/hasVars}}CodingKey, CaseIterable { + {{#allVars}} + case {{{name}}}{{#vendorExtensions.x-codegen-escaped-property-name}} = "{{{baseName}}}"{{/vendorExtensions.x-codegen-escaped-property-name}} + {{/allVars}} + } + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + {{#allVars}} + {{#vendorExtensions.x-swift-is-not-codable}} + {{#required}} + if let object = try JSONSerialization.jsonObject(with: try container.decode(Data.self, forKey: .{{{name}}})) as? {{{datatypeWithEnum}}} { + {{{name}}} = object + } else { + throw DecodingError.typeMismatch({{{datatypeWithEnum}}}.self, .init(codingPath: [CodingKeys.{{{name}}}], debugDescription: "Unable to cast types while decoding {{{classname}}}")) + } + {{/required}} + {{^required}} + if container.contains(.{{{name}}}) { + if let object = try JSONSerialization.jsonObject(with: try container.decode(Data.self, forKey: .{{{name}}})) as? {{{datatypeWithEnum}}} { + {{{name}}} = object + } else { + throw DecodingError.typeMismatch({{{datatypeWithEnum}}}.self, .init(codingPath: [CodingKeys.{{{name}}}], debugDescription: "Unable to cast types while decoding {{{classname}}}")) + } + } + {{/required}} + {{/vendorExtensions.x-swift-is-not-codable}} + {{^vendorExtensions.x-swift-is-not-codable}} + {{{name}}} = try container.decode{{^required}}IfPresent{{/required}}({{{datatypeWithEnum}}}.self, forKey: .{{{name}}}) + {{/vendorExtensions.x-swift-is-not-codable}} + {{/allVars}} + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + {{#allVars}} + {{#vendorExtensions.x-swift-is-not-codable}} + {{#required}} + try container.encode(try JSONSerialization.data(withJSONObject: {{{name}}}), forKey: .{{{name}}}) + {{/required}} + {{^required}} + if let {{{name}}} = {{{name}}} { + try container.encodeIfPresent(try JSONSerialization.data(withJSONObject: {{{name}}}), forKey: .{{{name}}}) + } + {{/required}} + {{/vendorExtensions.x-swift-is-not-codable}} + {{^vendorExtensions.x-swift-is-not-codable}} + try container.encode{{^required}}IfPresent{{/required}}({{{name}}}, forKey: .{{{name}}}) + {{/vendorExtensions.x-swift-is-not-codable}} + {{/allVars}} + {{#generateModelAdditionalProperties}} + {{#additionalPropertiesType}} + var additionalPropertiesContainer = encoder.container(keyedBy: String.self) + try additionalPropertiesContainer.encodeMap(additionalProperties) + {{/additionalPropertiesType}} + {{/generateModelAdditionalProperties}} + } +} \ No newline at end of file From 8016462565ea5d3fad2e309a8edd75a25e9359ba Mon Sep 17 00:00:00 2001 From: Anton Davydov Date: Mon, 17 Jan 2022 12:06:58 +0300 Subject: [PATCH 11/33] swift-alt v0.4.0 --- .../languages/SwiftAltClientCodegen.java | 17 +++++++---------- .../main/resources/swift-alt/modelEnum.mustache | 2 +- .../modelInlineEnumDeclaration.mustache | 2 +- .../resources/swift-alt/modelObject.mustache | 2 +- .../resources/swift-alt/modelOneOf.mustache | 2 +- 5 files changed, 11 insertions(+), 14 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java index cfcc7a538d30..5b48e70b3b50 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java @@ -652,6 +652,12 @@ public Map postProcessModels(Map objs) { prop.vendorExtensions.put("x-codegen-escaped-property-name", true); modelHasPropertyWithEscapedName = true; } + if (notCodableTypes.contains(prop.dataType) || notCodableTypes.contains(prop.baseType)) { + prop.vendorExtensions.put("x-swift-is-not-codable", true); + } + if (modelHasPropertyWithEscapedName || notCodableTypes.contains(prop.dataType) || notCodableTypes.contains(prop.baseType)) { + cm.vendorExtensions.put("x-swift-contains-not-codable", true); + } } if (modelHasPropertyWithEscapedName) { cm.vendorExtensions.put("x-codegen-has-escaped-property-names", true); @@ -661,15 +667,6 @@ public Map postProcessModels(Map objs) { return postProcessedModelsEnum; } - @Override - public void postProcessModelProperty(CodegenModel model, CodegenProperty property) { - super.postProcessModelProperty(model, property); - if (notCodableTypes.contains(property.dataType) || notCodableTypes.contains(property.baseType)) { - property.vendorExtensions.put("x-swift-is-not-codable", true); - model.vendorExtensions.put("x-swift-contains-not-codable", true); - } - } - @Override public String escapeQuotationMark(String input) { // remove " to avoid code injection @@ -758,7 +755,7 @@ public void postProcess() { System.out.println("################################################################################"); System.out.println("# Thanks for using OpenAPI Generator. #"); System.out.println("# swift alternative generator is contributed by @dydus0x14 and @ptiz. #"); - System.out.println("# swift alternative generator v0.3.0 #"); + System.out.println("# swift alternative generator v0.4.0 #"); System.out.println("################################################################################"); } } diff --git a/modules/openapi-generator/src/main/resources/swift-alt/modelEnum.mustache b/modules/openapi-generator/src/main/resources/swift-alt/modelEnum.mustache index fd9a11330558..2cb07669480e 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/modelEnum.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/modelEnum.mustache @@ -1,4 +1,4 @@ -public enum {{classname}}: {{dataType}}, Hashable, Codable, CaseIterable { +public enum {{classname}}: {{dataType}}, Codable, CaseIterable { {{#allowableValues}} {{#enumVars}} case {{{name}}} = {{{value}}} diff --git a/modules/openapi-generator/src/main/resources/swift-alt/modelInlineEnumDeclaration.mustache b/modules/openapi-generator/src/main/resources/swift-alt/modelInlineEnumDeclaration.mustache index aed8f3629829..1b07a51b5984 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/modelInlineEnumDeclaration.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/modelInlineEnumDeclaration.mustache @@ -1,4 +1,4 @@ - public enum {{enumName}}: {{^isContainer}}{{dataType}}{{/isContainer}}{{#isContainer}}String{{/isContainer}}, Hashable, Codable, CaseIterable { + public enum {{enumName}}: {{^isContainer}}{{dataType}}{{/isContainer}}{{#isContainer}}String{{/isContainer}}, Codable, CaseIterable { {{#allowableValues}} {{#enumVars}} case {{{name}}} = {{{value}}} diff --git a/modules/openapi-generator/src/main/resources/swift-alt/modelObject.mustache b/modules/openapi-generator/src/main/resources/swift-alt/modelObject.mustache index 2d37f62b8b93..11c4cf5d8a55 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/modelObject.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/modelObject.mustache @@ -1,4 +1,4 @@ -public struct {{{classname}}}: Codable, Hashable { +public struct {{{classname}}}: Codable { {{#allVars}} {{#isEnum}} {{> modelInlineEnumDeclaration}} diff --git a/modules/openapi-generator/src/main/resources/swift-alt/modelOneOf.mustache b/modules/openapi-generator/src/main/resources/swift-alt/modelOneOf.mustache index 315373aace5f..8aeddcc3c123 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/modelOneOf.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/modelOneOf.mustache @@ -1,4 +1,4 @@ -public enum {{classname}}: Codable, Hashable { +public enum {{classname}}: Codable { {{#oneOf}} case type{{.}}({{.}}) {{/oneOf}} From 12831b1a1a50d12db21484d041991e7248acd5a4 Mon Sep 17 00:00:00 2001 From: Anton Davydov Date: Sat, 22 Jan 2022 18:55:23 +0300 Subject: [PATCH 12/33] swift-alt v0.5.0 --- .../openapitools/codegen/languages/SwiftAltClientCodegen.java | 2 +- .../src/main/resources/swift-alt/OpenAPITransport.mustache | 2 +- .../main/resources/swift-alt/OpenAPITransportPackage.mustache | 1 + .../src/main/resources/swift-alt/Package.mustache | 1 + 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java index 5b48e70b3b50..e2a00741662e 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java @@ -755,7 +755,7 @@ public void postProcess() { System.out.println("################################################################################"); System.out.println("# Thanks for using OpenAPI Generator. #"); System.out.println("# swift alternative generator is contributed by @dydus0x14 and @ptiz. #"); - System.out.println("# swift alternative generator v0.4.0 #"); + System.out.println("# swift alternative generator v0.5.0 #"); System.out.println("################################################################################"); } } diff --git a/modules/openapi-generator/src/main/resources/swift-alt/OpenAPITransport.mustache b/modules/openapi-generator/src/main/resources/swift-alt/OpenAPITransport.mustache index 10be9a517283..afd19cb133ee 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/OpenAPITransport.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/OpenAPITransport.mustache @@ -209,7 +209,7 @@ open class URLSessionOpenAPITransport: OpenAPITransport { .flatMap { request -> AnyPublisher in self.config.delegate?.willStart(request: request) // Perform network call - return URLSession.shared.dataTaskPublisher(for: request) + return self.config.session.dataTaskPublisher(for: request) .mapError { OpenAPITransportError(statusCode: $0.code.rawValue, description: "Network call finished fails") } .flatMap { output in self.config.processor.decode(output: output) diff --git a/modules/openapi-generator/src/main/resources/swift-alt/OpenAPITransportPackage.mustache b/modules/openapi-generator/src/main/resources/swift-alt/OpenAPITransportPackage.mustache index 916f6dfd64d0..1235c42ca84e 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/OpenAPITransportPackage.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/OpenAPITransportPackage.mustache @@ -11,6 +11,7 @@ let package = Package( products: [ .library( name: "OpenAPITransport", + type: .static, targets: ["OpenAPITransport"] ), ], diff --git a/modules/openapi-generator/src/main/resources/swift-alt/Package.mustache b/modules/openapi-generator/src/main/resources/swift-alt/Package.mustache index c1cc2a5f3a77..31e8eeda6b5c 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/Package.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/Package.mustache @@ -11,6 +11,7 @@ let package = Package( products: [ .library( name: "{{projectName}}", + type: .static, targets: ["{{projectName}}"] ), ], From 3b5529f00cee76f3d90f68abeacd4d4582f673e1 Mon Sep 17 00:00:00 2001 From: Anton Davydov Date: Tue, 25 Jan 2022 19:20:51 +0300 Subject: [PATCH 13/33] swift-alt v0.6.0 --- .../codegen/languages/SwiftAltClientCodegen.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java index e2a00741662e..9d0ca3334051 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java @@ -740,7 +740,8 @@ public Map postProcessOperationsWithModels(Map o } protected void addVendorExtensions(CodegenParameter cp, CodegenOperation operation, HashMap modelMaps) { - cp.vendorExtensions.put("x-swift-is-base-type-enum", cp.isArray && modelMaps.get(cp.baseType).isEnum); + boolean isBaseTypeEnum = cp.isArray && cp.baseType != null && modelMaps.get(cp.baseType) != null && modelMaps.get(cp.baseType).isEnum; + cp.vendorExtensions.put("x-swift-is-base-type-enum", isBaseTypeEnum); if (cp.isEnum) { cp.vendorExtensions.put("x-swift-nested-enum-type", WordUtils.capitalize(operation.operationId) + WordUtils.capitalize(cp.enumName)); } @@ -755,7 +756,7 @@ public void postProcess() { System.out.println("################################################################################"); System.out.println("# Thanks for using OpenAPI Generator. #"); System.out.println("# swift alternative generator is contributed by @dydus0x14 and @ptiz. #"); - System.out.println("# swift alternative generator v0.5.0 #"); + System.out.println("# swift alternative generator v0.6.0 #"); System.out.println("################################################################################"); } } From 0017fb0d101b18951e8e8fe6b173aac79d5f3d99 Mon Sep 17 00:00:00 2001 From: Anton Davydov Date: Tue, 8 Feb 2022 12:56:27 +0300 Subject: [PATCH 14/33] swift-alt v0.7.0 --- .../languages/SwiftAltClientCodegen.java | 23 +- .../src/main/resources/swift-alt/api.mustache | 209 +++++++++++------- .../main/resources/swift-alt/toData.mustache | 1 + .../resources/swift-alt/toString.mustache | 2 +- 4 files changed, 149 insertions(+), 86 deletions(-) create mode 100644 modules/openapi-generator/src/main/resources/swift-alt/toData.mustache diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java index 9d0ca3334051..aa8f06225b2f 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java @@ -49,11 +49,13 @@ public class SwiftAltClientCodegen extends DefaultCodegen implements CodegenConf private final Logger LOGGER = LoggerFactory.getLogger(SwiftAltClientCodegen.class); public static final String PROJECT_NAME = "projectName"; + public static final String MAP_FILE_BINARY_TO_DATA = "mapFileBinaryToData"; protected String projectName = "OpenAPIClient"; protected String privateFolder = "Sources/Private"; protected String sourceFolder = "Sources"; protected String transportFolder = "OpenAPITransport"; protected List notCodableTypes = Arrays.asList("Any", "AnyObject", "[String: Any]", "[String: [String: Any]"); + protected boolean mapFileBinaryToData = true; /** * Constructor for the swift alt language codegen module. @@ -150,7 +152,7 @@ public SwiftAltClientCodegen() { "Array", "Dictionary", "Set", "OptionSet", "CountableRange", "CountableClosedRange", // The following are commonly-used Foundation types - "URL", "Data", "Codable", "Encodable", "Decodable", + "URL", "Data", "Codable", "Encodable", "Decodable", "Result", // The following are other words we want to reserve "Void", "AnyObject", "Class", "dynamicType", "COLUMN", "FILE", "FUNCTION", "LINE" @@ -175,8 +177,6 @@ public SwiftAltClientCodegen() { typeMapping.put("float", "Float"); typeMapping.put("number", "Double"); typeMapping.put("double", "Double"); - typeMapping.put("file", "URL"); - typeMapping.put("binary", "URL"); typeMapping.put("ByteArray", "Data"); typeMapping.put("UUID", "UUID"); typeMapping.put("URI", "String"); @@ -193,7 +193,9 @@ public SwiftAltClientCodegen() { cliOptions.add(new CliOption(PROJECT_NAME, "Project name in Xcode")); cliOptions.add(new CliOption(CodegenConstants.API_NAME_PREFIX, CodegenConstants.API_NAME_PREFIX_DESC)); - CliOption libraryOption = new CliOption(CodegenConstants.LIBRARY, "Library template (sub-template) to use"); + cliOptions.add(new CliOption(MAP_FILE_BINARY_TO_DATA, + "Map File and Binary to Data (default: true)") + .defaultValue(Boolean.TRUE.toString())); } @Override @@ -239,6 +241,17 @@ public void processOpts() { supportingFiles.add(new SupportingFile("OpenISO8601DateFormatter.mustache", projectName + File.separator + privateFolder, "OpenISO8601DateFormatter.swift")); + if (additionalProperties.containsKey(MAP_FILE_BINARY_TO_DATA)) { + mapFileBinaryToData = convertPropertyToBooleanAndWriteBack(MAP_FILE_BINARY_TO_DATA); + } + additionalProperties.put(MAP_FILE_BINARY_TO_DATA, mapFileBinaryToData); + if (mapFileBinaryToData) { + typeMapping.put("file", "Data"); + typeMapping.put("binary", "Data"); + } else { + typeMapping.put("file", "URL"); + typeMapping.put("binary", "URL"); + } } @Override @@ -756,7 +769,7 @@ public void postProcess() { System.out.println("################################################################################"); System.out.println("# Thanks for using OpenAPI Generator. #"); System.out.println("# swift alternative generator is contributed by @dydus0x14 and @ptiz. #"); - System.out.println("# swift alternative generator v0.6.0 #"); + System.out.println("# swift alternative generator v0.7.0 #"); System.out.println("################################################################################"); } } diff --git a/modules/openapi-generator/src/main/resources/swift-alt/api.mustache b/modules/openapi-generator/src/main/resources/swift-alt/api.mustache index 04ee17c27df6..9afcb3030272 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/api.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/api.mustache @@ -93,91 +93,140 @@ open class {{classname}} { - returns: AnyPublisher<{{{returnType}}}{{^returnType}}Void{{/returnType}}, Error> {{description}} */ open func {{operationId}}({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{vendorExtensions.x-swift-nested-enum-type}}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}) -> AnyPublisher<{{{returnType}}}{{^returnType}}Void{{/returnType}}, Error> { - guard let baseURL = transport.baseURL ?? self.baseURL else { - return Fail(error: OpenAPITransportError.badURLError()) - .eraseToAnyPublisher() - } - let path = "{{path}}" - {{#pathParams}} - .replacingOccurrences(of: "{{=<% %>=}}{<%baseName%>}<%={{ }}=%>", with: "\({{paramName}})") - {{/pathParams}} - let url = baseURL.appendingPathComponent(path) - {{#hasQueryParams}}var{{/hasQueryParams}}{{^hasQueryParams}}let{{/hasQueryParams}} components = URLComponents(url: url, resolvingAgainstBaseURL: false) - {{#hasQueryParams}} - var queryItems: [URLQueryItem] = [] - {{#queryParams}} - {{#required}}queryItems.append(URLQueryItem(name: "{{paramName}}", value: {{> toString}})){{/required}}{{^required}}if let {{paramName}} = {{paramName}} { queryItems.append(URLQueryItem(name: "{{paramName}}", value: {{> toString}})) } {{/required}} - {{/queryParams}} - components?.queryItems = queryItems - {{/hasQueryParams}} - guard let requestURL = components?.url else { - return Fail(error: OpenAPITransportError.badURLError()) - .eraseToAnyPublisher() - } - var request = URLRequest(url: requestURL) - request.httpMethod = "{{httpMethod}}" - request.allHTTPHeaderFields = [{{^headerParams}}{{^hasFormParams}} - :{{/hasFormParams}}{{/headerParams}}{{#hasFormParams}} - "Content-Type": {{^consumes}}"multipart/form-data"{{/consumes}}{{#consumes.0}}"{{{mediaType}}}"{{/consumes.0}},{{/hasFormParams}}{{#headerParams}} - "{{baseName}}": {{paramName}}{{^-last}}, {{/-last}}{{/headerParams}} - ].compactMapValues { $0 } - {{#hasBodyParam}} - {{#bodyParam}} - request.httpBody = try? encoder.encode({{paramName}}) - if request.value(forHTTPHeaderField: "Content-Type") == nil { + return Result { + guard let baseURL = transport.baseURL ?? self.baseURL else { + throw OpenAPITransportError.badURLError() + } + let path = "{{path}}" + {{#pathParams}} + .replacingOccurrences(of: "{{=<% %>=}}{<%baseName%>}<%={{ }}=%>", with: "\({{paramName}})") + {{/pathParams}} + let url = baseURL.appendingPathComponent(path) + {{#hasQueryParams}}var{{/hasQueryParams}}{{^hasQueryParams}}let{{/hasQueryParams}} components = URLComponents(url: url, resolvingAgainstBaseURL: false) + {{#hasQueryParams}} + var queryItems: [URLQueryItem] = [] + {{#queryParams}} + {{#required}}queryItems.append(URLQueryItem(name: "{{paramName}}", value: {{> toString}})){{/required}}{{^required}}if let {{paramName}} = {{paramName}} { queryItems.append(URLQueryItem(name: "{{paramName}}", value: {{> toString}})) } {{/required}} + {{/queryParams}} + components?.queryItems = queryItems + {{/hasQueryParams}} + guard let requestURL = components?.url else { + throw OpenAPITransportError.badURLError() + } + var request = URLRequest(url: requestURL) + request.httpMethod = "{{httpMethod}}" + {{! Begin headers }} + {{#headerParams}} + {{#-last}} + request.allHTTPHeaderFields = [ + {{/-last}} + {{/headerParams}} + {{#headerParams}} + "{{baseName}}": {{paramName}}{{^-last}}, {{/-last}} + {{/headerParams}} + {{#headerParams}} + {{#-last}} + ].compactMapValues { $0 } + {{/-last}} + {{/headerParams}} + {{! Begin body }} + {{#hasBodyParam}} + {{#bodyParam}} + request.httpBody = try encoder.encode({{paramName}}) request.setValue("application/json", forHTTPHeaderField: "Content-Type") + {{/bodyParam}} + {{/hasBodyParam}} + {{! Begin multipart form }} + {{#hasFormParams}} + {{#isMultipart}} + let multipartBoundary = String(format: "Boundary+%08X%08X", arc4random(), arc4random()) + var multipartData = Data() + {{#formParams}} + let {{paramName}}Header = "--\(multipartBoundary)\r\n" + {{#isFile}} + .appending("Content-Disposition:form-data; name=\"{{paramName}}\"; filename=\"{{paramName}}\"\r\n") + {{/isFile}} + {{^isFile}} + .appending("Content-Disposition:form-data; name=\"{{paramName}}\"\r\n") + {{/isFile}} + {{#contentType}} + .appending("Content-Type: {{{contentType}}}\r\n") + {{/contentType}} + .appending("\r\n") + if let {{paramName}}HeaderData = {{paramName}}Header.data(using: .utf8) { + multipartData.append({{paramName}}HeaderData) + } + {{#required}}multipartData.append({{> toData}}){{/required}}{{^required}}if let {{paramName}} = {{paramName}} { multipartData.append({{> toData}}) }{{/required}} + {{^-last}} + if let separator = "\r\n".data(using: .utf8) { + multipartData.append(separator) + } + {{/-last}} + {{/formParams}} + if let footer = "\r\n--\(multipartBoundary)--\r\n".data(using: .utf8) { + multipartData.append(footer) + } + request.httpBody = multipartData + request.setValue("\(multipartData.count)", forHTTPHeaderField: "Content-Length") + request.setValue("multipart/form-data; boundary=\(multipartBoundary)", forHTTPHeaderField: "Content-Type") + {{/isMultipart}} + {{^isMultipart}} + {{! Begin form urlencoded }} + var formEncodedItems: [String] = [] + {{#formParams}} + {{#required}}formEncodedItems.append("{{paramName}}=\({{> toString}})"){{/required}}{{^required}}if let {{paramName}} = {{paramName}} { formEncodedItems.append("{{paramName}}=\({{> toString}})") } {{/required}} + {{/formParams}} + request.httpBody = formEncodedItems.joined(separator: "&").data(using: .utf8) + request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type") + {{/isMultipart}} + {{/hasFormParams}} + return request } - {{/bodyParam}} - {{/hasBodyParam}} - {{#hasFormParams}} - var formEncodedItems: [String] = [] - {{#formParams}} - {{#required}}formEncodedItems.append("{{paramName}}=\({{> toString}})"){{/required}}{{^required}}if let {{paramName}} = {{paramName}} { formEncodedItems.append("{{paramName}}=\({{> toString}})") } {{/required}} - {{/formParams}} - request.httpBody = formEncodedItems.joined(separator: "&").data(using: .utf8) - {{/hasFormParams}} - let securitySchemes: [SecurityScheme] = [{{#authMethods}}{{#isBasicBearer}}.bearer{{/isBasicBearer}}{{/authMethods}}] - return transport.send(request: request, securitySchemes: securitySchemes) - {{#vendorExtensions.x-swift-custom-error-type}} - .mapError { transportError -> Error in - {{#responses}} - {{#vendorExtensions.x-swift-has-custom-error-type}} - if transportError.statusCode == {{{code}}} { - {{#dataType}} - do { - let error = try self.decoder.decode({{{dataType}}}.self, from: transportError.data) - return {{{vendorExtensions.x-swift-custom-error-type}}}.code{{{code}}}Error(error) - } catch { - return error + .publisher + .flatMap { request -> AnyPublisher<{{{returnType}}}{{^returnType}}Void{{/returnType}}, Error> in + let securitySchemes: [SecurityScheme] = [{{#authMethods}}{{#isBasicBearer}}.bearer{{/isBasicBearer}}{{/authMethods}}] + return self.transport.send(request: request, securitySchemes: securitySchemes) + {{#vendorExtensions.x-swift-custom-error-type}} + .mapError { transportError -> Error in + {{#responses}} + {{#vendorExtensions.x-swift-has-custom-error-type}} + if transportError.statusCode == {{{code}}} { + {{#dataType}} + do { + let error = try self.decoder.decode({{{dataType}}}.self, from: transportError.data) + return {{{vendorExtensions.x-swift-custom-error-type}}}.code{{{code}}}Error(error) + } catch { + return error + } + {{/dataType}} + {{^dataType}} + return {{{vendorExtensions.x-swift-custom-error-type}}}.code{{{code}}}Error + {{/dataType}} } - {{/dataType}} - {{^dataType}} - return {{{vendorExtensions.x-swift-custom-error-type}}}.code{{{code}}}Error - {{/dataType}} + {{/vendorExtensions.x-swift-has-custom-error-type}} + {{/responses}} + return transportError } - {{/vendorExtensions.x-swift-has-custom-error-type}} - {{/responses}} - return transportError - } - {{/vendorExtensions.x-swift-custom-error-type}} - .tryMap { response in - {{#returnType}} - {{#vendorExtensions.x-swift-is-not-codable}} - if let object = try JSONSerialization.jsonObject(with: response.data, options: []) as? {{{returnType}}} { - return object - } else { - throw OpenAPITransportError.invalidResponseMappingError(data: response.data) + {{/vendorExtensions.x-swift-custom-error-type}} + .tryMap { response in + {{#returnType}} + {{#vendorExtensions.x-swift-is-not-codable}} + if let object = try JSONSerialization.jsonObject(with: response.data, options: []) as? {{{returnType}}} { + return object + } else { + throw OpenAPITransportError.invalidResponseMappingError(data: response.data) + } + {{/vendorExtensions.x-swift-is-not-codable}} + {{^vendorExtensions.x-swift-is-not-codable}} + try self.decoder.decode({{{returnType}}}.self, from: response.data) + {{/vendorExtensions.x-swift-is-not-codable}} + {{/returnType}} + {{^returnType}} + return () + {{/returnType}} } - {{/vendorExtensions.x-swift-is-not-codable}} - {{^vendorExtensions.x-swift-is-not-codable}} - try self.decoder.decode({{{returnType}}}.self, from: response.data) - {{/vendorExtensions.x-swift-is-not-codable}} - {{/returnType}} - {{^returnType}} - return () - {{/returnType}} - } - .eraseToAnyPublisher() + .eraseToAnyPublisher() + }.eraseToAnyPublisher() } {{/operation}} } diff --git a/modules/openapi-generator/src/main/resources/swift-alt/toData.mustache b/modules/openapi-generator/src/main/resources/swift-alt/toData.mustache new file mode 100644 index 000000000000..0456e7c0e352 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/swift-alt/toData.mustache @@ -0,0 +1 @@ +{{#isBinary}}{{#mapFileBinaryToData}}{{{paramName}}}{{/mapFileBinaryToData}}{{^mapFileBinaryToData}}try Data(contentsOf: {{{paramName}}}){{/mapFileBinaryToData}}{{/isBinary}}{{#isModel}}try self.encoder.encode({{paramName}}){{/isModel}}{{#isByteArray}}{{paramName}}.base64EncodedData(){{/isByteArray}}{{#isString}}{{paramName}}.data(using: .utf8) ?? Data(){{/isString}} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/swift-alt/toString.mustache b/modules/openapi-generator/src/main/resources/swift-alt/toString.mustache index 6fe4f1e27a98..794f88c0fb65 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/toString.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/toString.mustache @@ -1 +1 @@ -{{#vendorExtensions.x-swift-is-enum-type}}{{paramName}}.rawValue{{/vendorExtensions.x-swift-is-enum-type}}{{^isEnum}}{{#isString}}{{paramName}}{{/isString}}{{#isInteger}}"\({{paramName}})"{{/isInteger}}{{#isDouble}}"\({{paramName}})"{{/isDouble}}{{#isFloat}}"\({{paramName}})"{{/isFloat}}{{#isNumber}}"\({{paramName}})"{{/isNumber}}{{#isBoolean}}{{paramName}} ? "true" : "false"{{/isBoolean}}{{#isArray}}{{paramName}}{{#vendorExtensions.x-swift-is-base-type-enum}}.map { $0.rawValue }{{/vendorExtensions.x-swift-is-base-type-enum}}.joined(separator: ", "){{/isArray}}{{/isEnum}} \ No newline at end of file +{{#vendorExtensions.x-swift-is-enum-type}}{{paramName}}.rawValue{{/vendorExtensions.x-swift-is-enum-type}}{{^isEnum}}{{#isString}}{{paramName}}{{/isString}}{{#isInteger}}"\({{paramName}})"{{/isInteger}}{{#isDouble}}"\({{paramName}})"{{/isDouble}}{{#isFloat}}"\({{paramName}})"{{/isFloat}}{{#isNumber}}"\({{paramName}})"{{/isNumber}}{{#isBoolean}}{{paramName}} ? "true" : "false"{{/isBoolean}}{{#isArray}}{{paramName}}{{#vendorExtensions.x-swift-is-base-type-enum}}.map { $0.rawValue }{{/vendorExtensions.x-swift-is-base-type-enum}}.joined(separator: ", "){{/isArray}}{{/isEnum}}{{#isModel}}String(data: try self.encoder.encode({{paramName}}), encoding: .utf8){{/isModel}} \ No newline at end of file From 68bdd547d4153d563e3d3de87ab9917616f7a712 Mon Sep 17 00:00:00 2001 From: Anton Davydov Date: Mon, 14 Feb 2022 10:19:03 +0300 Subject: [PATCH 15/33] swift-alt v0.8.0 --- .../languages/SwiftAltClientCodegen.java | 40 ++++++++++++++----- .../src/main/resources/swift-alt/api.mustache | 29 ++------------ .../toMultipartFormDataAppend.mustache | 37 +++++++++++++++++ .../resources/swift-alt/toString.mustache | 2 +- 4 files changed, 71 insertions(+), 37 deletions(-) create mode 100644 modules/openapi-generator/src/main/resources/swift-alt/toMultipartFormDataAppend.mustache diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java index aa8f06225b2f..d4ba12d54ee2 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java @@ -113,9 +113,6 @@ public SwiftAltClientCodegen() { reservedWords = new HashSet<>( Arrays.asList( - // name used by swift client - "ErrorResponse", "Response", - // Swift keywords. This list is taken from here: // https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/doc/uid/TP40014097-CH30-ID410 // @@ -285,7 +282,7 @@ public String getTypeDeclaration(Schema p) { Schema target = ModelUtils.isGenerateAliasAsModel() ? p : schema; if (ModelUtils.isArraySchema(target)) { Schema items = getSchemaItems((ArraySchema) schema); - return ModelUtils.isSet(target) ? "Set<" + getTypeDeclaration(items) + ">" : "[" + getTypeDeclaration(items) + "]"; + return ModelUtils.isSet(target) && ModelUtils.isObjectSchema(items) ? "Set<" + getTypeDeclaration(items) + ">" : "[" + getTypeDeclaration(items) + "]"; } else if (ModelUtils.isMapSchema(target)) { // Note: ModelUtils.isMapSchema(p) returns true when p is a composed schema that also defines // additionalproperties: true @@ -735,7 +732,7 @@ public Map postProcessOperationsWithModels(Map o operation.allParams.forEach(cp -> addVendorExtensions(cp, operation, modelMaps)); operation.queryParams.forEach(cp -> addVendorExtensions(cp, operation, modelMaps)); operation.bodyParams.forEach(cp -> addVendorExtensions(cp, operation, modelMaps)); - operation.formParams.forEach(cp -> addVendorExtensions(cp, operation, modelMaps)); + operation.formParams.forEach(cp -> addFormVendorExtensions(cp, operation, modelMaps)); if (notCodableTypes.contains(operation.returnType) || notCodableTypes.contains(operation.returnBaseType)) { operation.vendorExtensions.put("x-swift-is-not-codable", true); } @@ -753,15 +750,36 @@ public Map postProcessOperationsWithModels(Map o } protected void addVendorExtensions(CodegenParameter cp, CodegenOperation operation, HashMap modelMaps) { - boolean isBaseTypeEnum = cp.isArray && cp.baseType != null && modelMaps.get(cp.baseType) != null && modelMaps.get(cp.baseType).isEnum; - cp.vendorExtensions.put("x-swift-is-base-type-enum", isBaseTypeEnum); - if (cp.isEnum) { - cp.vendorExtensions.put("x-swift-nested-enum-type", WordUtils.capitalize(operation.operationId) + WordUtils.capitalize(cp.enumName)); - } CodegenModel model = modelMaps.get(cp.dataType); + if (cp.isArray && cp.items != null) { + CodegenModel baseModel = modelMaps.get(cp.items.dataType); + boolean isBaseTypeEnum = cp.items.isEnum || cp.isEnum || (baseModel != null && baseModel.isEnum); + cp.vendorExtensions.put("x-swift-is-base-type-enum", isBaseTypeEnum); + } if (cp.isEnum || (model != null && model.isEnum)) { cp.vendorExtensions.put("x-swift-is-enum-type", true); } + if (cp.isEnum) { + String newDataType = WordUtils.capitalize(operation.operationId) + WordUtils.capitalize(cp.enumName); + cp.vendorExtensions.put("x-swift-nested-enum-type", newDataType); + if (cp.isArray) { + if (cp.uniqueItems) { + cp.dataType = "Set<" + newDataType + ">"; + } else { + cp.dataType = "[" + newDataType + "]"; + } + } else { + cp.baseType = cp.dataType; + cp.dataType = newDataType; + } + } + } + + protected void addFormVendorExtensions(CodegenParameter cp, CodegenOperation operation, HashMap modelMaps) { + addVendorExtensions(cp, operation, modelMaps); + if (operation.isMultipart && cp.isArray && cp.items.isFile) { + cp.vendorExtensions.put("x-swift-enumerate-multipart", true); + } } @Override @@ -769,7 +787,7 @@ public void postProcess() { System.out.println("################################################################################"); System.out.println("# Thanks for using OpenAPI Generator. #"); System.out.println("# swift alternative generator is contributed by @dydus0x14 and @ptiz. #"); - System.out.println("# swift alternative generator v0.7.0 #"); + System.out.println("# swift alternative generator v0.8.0 #"); System.out.println("################################################################################"); } } diff --git a/modules/openapi-generator/src/main/resources/swift-alt/api.mustache b/modules/openapi-generator/src/main/resources/swift-alt/api.mustache index 9afcb3030272..2f68c3ab6c04 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/api.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/api.mustache @@ -35,7 +35,7 @@ open class {{classname}} { /** * enum for parameter {{paramName}} */ - public enum {{{vendorExtensions.x-swift-nested-enum-type}}}: {{dataType}}, Hashable, Codable, CaseIterable { + public enum {{{vendorExtensions.x-swift-nested-enum-type}}}: {{{baseType}}}, Codable, CaseIterable { {{#allowableValues}} {{#enumVars}} case {{name}} = {{{value}}} @@ -92,7 +92,7 @@ open class {{classname}} { {{/allParams}} - returns: AnyPublisher<{{{returnType}}}{{^returnType}}Void{{/returnType}}, Error> {{description}} */ - open func {{operationId}}({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{vendorExtensions.x-swift-nested-enum-type}}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}) -> AnyPublisher<{{{returnType}}}{{^returnType}}Void{{/returnType}}, Error> { + open func {{operationId}}({{#allParams}}{{paramName}}: {{{dataType}}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}) -> AnyPublisher<{{{returnType}}}{{^returnType}}Void{{/returnType}}, Error> { return Result { guard let baseURL = transport.baseURL ?? self.baseURL else { throw OpenAPITransportError.badURLError() @@ -142,30 +142,9 @@ open class {{classname}} { let multipartBoundary = String(format: "Boundary+%08X%08X", arc4random(), arc4random()) var multipartData = Data() {{#formParams}} - let {{paramName}}Header = "--\(multipartBoundary)\r\n" - {{#isFile}} - .appending("Content-Disposition:form-data; name=\"{{paramName}}\"; filename=\"{{paramName}}\"\r\n") - {{/isFile}} - {{^isFile}} - .appending("Content-Disposition:form-data; name=\"{{paramName}}\"\r\n") - {{/isFile}} - {{#contentType}} - .appending("Content-Type: {{{contentType}}}\r\n") - {{/contentType}} - .appending("\r\n") - if let {{paramName}}HeaderData = {{paramName}}Header.data(using: .utf8) { - multipartData.append({{paramName}}HeaderData) - } - {{#required}}multipartData.append({{> toData}}){{/required}}{{^required}}if let {{paramName}} = {{paramName}} { multipartData.append({{> toData}}) }{{/required}} - {{^-last}} - if let separator = "\r\n".data(using: .utf8) { - multipartData.append(separator) - } - {{/-last}} +{{> toMultipartFormDataAppend}} {{/formParams}} - if let footer = "\r\n--\(multipartBoundary)--\r\n".data(using: .utf8) { - multipartData.append(footer) - } + multipartData.append("\r\n--\(multipartBoundary)--\r\n".data(using: .utf8) ?? Data()) request.httpBody = multipartData request.setValue("\(multipartData.count)", forHTTPHeaderField: "Content-Length") request.setValue("multipart/form-data; boundary=\(multipartBoundary)", forHTTPHeaderField: "Content-Type") diff --git a/modules/openapi-generator/src/main/resources/swift-alt/toMultipartFormDataAppend.mustache b/modules/openapi-generator/src/main/resources/swift-alt/toMultipartFormDataAppend.mustache new file mode 100644 index 000000000000..9837a666ed6e --- /dev/null +++ b/modules/openapi-generator/src/main/resources/swift-alt/toMultipartFormDataAppend.mustache @@ -0,0 +1,37 @@ + {{#vendorExtensions.x-swift-enumerate-multipart}} + {{^mapFileBinaryToData}}try {{/mapFileBinaryToData}}{{paramName}}{{^required}}?{{/required}}.enumerated().forEach { index, {{paramName}} in + {{#mapFileBinaryToData}} + let filename = "\({{paramName}})\(index)" + {{/mapFileBinaryToData}} + {{^mapFileBinaryToData}} + let filename = {{paramName}}.lastPathComponent + {{/mapFileBinaryToData}} + let {{paramName}}Header = "--\(multipartBoundary)\r\n" + .appending("Content-Disposition:form-data; name=\"{{paramName}}\"; filename=\"\(filename)\"\r\n") + {{#contentType}} + .appending("Content-Type: {{{contentType}}}\r\n") + {{/contentType}} + .appending("\r\n") + multipartData.append({{paramName}}Header.data(using: .utf8) ?? Data()) + multipartData.append({{#items}}{{> toData}}{{/items}}) + multipartData.append("\r\n".data(using: .utf8) ?? Data()) + } + {{/vendorExtensions.x-swift-enumerate-multipart}} + {{^vendorExtensions.x-swift-enumerate-multipart}} + let {{paramName}}Header = "--\(multipartBoundary)\r\n" + {{#isFile}} + .appending("Content-Disposition:form-data; name=\"{{paramName}}\"; filename=\"{{paramName}}\"\r\n") + {{/isFile}} + {{^isFile}} + .appending("Content-Disposition:form-data; name=\"{{paramName}}\"\r\n") + {{/isFile}} + {{#contentType}} + .appending("Content-Type: {{{contentType}}}\r\n") + {{/contentType}} + .appending("\r\n") + multipartData.append({{paramName}}Header.data(using: .utf8) ?? Data()) + {{#required}}multipartData.append({{> toData}}){{/required}}{{^required}}if let {{paramName}} = {{paramName}} { multipartData.append({{> toData}}) }{{/required}} + {{^-last}} + multipartData.append("\r\n".data(using: .utf8) ?? Data()) + {{/-last}} + {{/vendorExtensions.x-swift-enumerate-multipart}} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/swift-alt/toString.mustache b/modules/openapi-generator/src/main/resources/swift-alt/toString.mustache index 794f88c0fb65..659f3627dd7c 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/toString.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/toString.mustache @@ -1 +1 @@ -{{#vendorExtensions.x-swift-is-enum-type}}{{paramName}}.rawValue{{/vendorExtensions.x-swift-is-enum-type}}{{^isEnum}}{{#isString}}{{paramName}}{{/isString}}{{#isInteger}}"\({{paramName}})"{{/isInteger}}{{#isDouble}}"\({{paramName}})"{{/isDouble}}{{#isFloat}}"\({{paramName}})"{{/isFloat}}{{#isNumber}}"\({{paramName}})"{{/isNumber}}{{#isBoolean}}{{paramName}} ? "true" : "false"{{/isBoolean}}{{#isArray}}{{paramName}}{{#vendorExtensions.x-swift-is-base-type-enum}}.map { $0.rawValue }{{/vendorExtensions.x-swift-is-base-type-enum}}.joined(separator: ", "){{/isArray}}{{/isEnum}}{{#isModel}}String(data: try self.encoder.encode({{paramName}}), encoding: .utf8){{/isModel}} \ No newline at end of file +{{#isModel}}String(data: try self.encoder.encode({{paramName}}), encoding: .utf8){{/isModel}}{{^isModel}}{{#isArray}}{{paramName}}{{#vendorExtensions.x-swift-is-base-type-enum}}.map { $0.rawValue }{{/vendorExtensions.x-swift-is-base-type-enum}}.joined(separator: ", "){{/isArray}}{{^isArray}}{{#vendorExtensions.x-swift-is-enum-type}}{{paramName}}.rawValue{{/vendorExtensions.x-swift-is-enum-type}}{{^isEnum}}{{#isString}}{{paramName}}{{/isString}}{{#isInteger}}"\({{paramName}})"{{/isInteger}}{{#isDouble}}"\({{paramName}})"{{/isDouble}}{{#isFloat}}"\({{paramName}})"{{/isFloat}}{{#isNumber}}"\({{paramName}})"{{/isNumber}}{{#isBoolean}}{{paramName}} ? "true" : "false"{{/isBoolean}}{{/isEnum}}{{/isArray}}{{/isModel}} \ No newline at end of file From e2cb098e46b97741aa390f5b2f13a256c601c765 Mon Sep 17 00:00:00 2001 From: Anton Davydov Date: Fri, 18 Feb 2022 15:19:30 +0300 Subject: [PATCH 16/33] swift-alt v0.9.0 --- .../openapitools/codegen/languages/SwiftAltClientCodegen.java | 2 +- .../src/main/resources/swift-alt/api.mustache | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java index d4ba12d54ee2..17d83ffabc9d 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java @@ -787,7 +787,7 @@ public void postProcess() { System.out.println("################################################################################"); System.out.println("# Thanks for using OpenAPI Generator. #"); System.out.println("# swift alternative generator is contributed by @dydus0x14 and @ptiz. #"); - System.out.println("# swift alternative generator v0.8.0 #"); + System.out.println("# swift alternative generator v0.9.0 #"); System.out.println("################################################################################"); } } diff --git a/modules/openapi-generator/src/main/resources/swift-alt/api.mustache b/modules/openapi-generator/src/main/resources/swift-alt/api.mustache index 2f68c3ab6c04..753d7e1e70f4 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/api.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/api.mustache @@ -106,7 +106,7 @@ open class {{classname}} { {{#hasQueryParams}} var queryItems: [URLQueryItem] = [] {{#queryParams}} - {{#required}}queryItems.append(URLQueryItem(name: "{{paramName}}", value: {{> toString}})){{/required}}{{^required}}if let {{paramName}} = {{paramName}} { queryItems.append(URLQueryItem(name: "{{paramName}}", value: {{> toString}})) } {{/required}} + {{#required}}queryItems.append(URLQueryItem(name: "{{baseName}}", value: {{> toString}})){{/required}}{{^required}}if let {{paramName}} = {{paramName}} { queryItems.append(URLQueryItem(name: "{{baseName}}", value: {{> toString}})) } {{/required}} {{/queryParams}} components?.queryItems = queryItems {{/hasQueryParams}} @@ -153,7 +153,7 @@ open class {{classname}} { {{! Begin form urlencoded }} var formEncodedItems: [String] = [] {{#formParams}} - {{#required}}formEncodedItems.append("{{paramName}}=\({{> toString}})"){{/required}}{{^required}}if let {{paramName}} = {{paramName}} { formEncodedItems.append("{{paramName}}=\({{> toString}})") } {{/required}} + {{#required}}formEncodedItems.append("{{baseName}}=\({{> toString}})"){{/required}}{{^required}}if let {{paramName}} = {{paramName}} { formEncodedItems.append("{{baseName}}=\({{> toString}})") } {{/required}} {{/formParams}} request.httpBody = formEncodedItems.joined(separator: "&").data(using: .utf8) request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type") From 7c66d53a0ba5b9e30364dfb958e1aa06aa66c5e6 Mon Sep 17 00:00:00 2001 From: Anton Davydov Date: Wed, 23 Mar 2022 18:07:18 +0300 Subject: [PATCH 17/33] swift-alt v0.12.0 --- .../languages/SwiftAltClientCodegen.java | 29 +++++++++++- .../swift-alt/OpenAPITransport.mustache | 44 +++++++++++++++++-- .../OpenISO8601DateFormatter.mustache | 2 + .../resources/swift-alt/toString.mustache | 2 +- 4 files changed, 71 insertions(+), 6 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java index 17d83ffabc9d..13e8129263cc 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java @@ -18,6 +18,7 @@ package org.openapitools.codegen.languages; import io.swagger.v3.oas.models.media.ArraySchema; +import io.swagger.v3.oas.models.media.ComposedSchema; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.media.StringSchema; import org.apache.commons.io.FilenameUtils; @@ -62,8 +63,9 @@ public class SwiftAltClientCodegen extends DefaultCodegen implements CodegenConf */ public SwiftAltClientCodegen() { super(); + this.supportsMultipleInheritance = true; this.useOneOfInterfaces = true; - this.supportsInheritance = true; + this.supportsAdditionalPropertiesWithComposedSchema = true; generatorMetadata = GeneratorMetadata.newBuilder(generatorMetadata) .stability(Stability.STABLE) @@ -210,6 +212,22 @@ public String getHelp() { return "Generates a Swift 5 alternative client library."; } +// @Override +// protected void addAdditionPropertiesToCodeGenModel(CodegenModel codegenModel, +// Schema schema) { +// final Schema additionalProperties = getAdditionalProperties(schema); +// if (additionalProperties != null) { +// Schema inner = null; +// if (ModelUtils.isArraySchema(schema)) { +// ArraySchema ap = (ArraySchema) schema; +// inner = ap.getItems(); +// } else if (ModelUtils.isMapSchema(schema)) { +// inner = getAdditionalProperties(schema); +// } +// codegenModel.additionalPropertiesType = inner != null ? getTypeDeclaration(inner) : getSchemaType(additionalProperties); +// } +// } + @Override public void processOpts() { super.processOpts(); @@ -293,6 +311,13 @@ public String getTypeDeclaration(Schema p) { p.setAdditionalProperties(inner); } return "[String: " + getTypeDeclaration(inner) + "]"; + } else if (ModelUtils.isComposedSchema(target)) { + List schemas = ModelUtils.getInterfaces((ComposedSchema)target); + if (schemas.size() == 1) { + return getTypeDeclaration(schemas.get(0)); + } else { + super.getTypeDeclaration(target); + } } return super.getTypeDeclaration(target); } @@ -787,7 +812,7 @@ public void postProcess() { System.out.println("################################################################################"); System.out.println("# Thanks for using OpenAPI Generator. #"); System.out.println("# swift alternative generator is contributed by @dydus0x14 and @ptiz. #"); - System.out.println("# swift alternative generator v0.9.0 #"); + System.out.println("# swift alternative generator v0.12.0 #"); System.out.println("################################################################################"); } } diff --git a/modules/openapi-generator/src/main/resources/swift-alt/OpenAPITransport.mustache b/modules/openapi-generator/src/main/resources/swift-alt/OpenAPITransport.mustache index afd19cb133ee..bb7fca57c712 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/OpenAPITransport.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/OpenAPITransport.mustache @@ -182,11 +182,15 @@ public extension OpenAPITransportError { data: data ) } + + static let retryErrorCode = 606 + static let retryError = OpenAPITransportError(statusCode: OpenAPITransportError.retryErrorCode) } public protocol URLSessionOpenAPITransportDelegate: AnyObject { func willStart(request: URLRequest) func didFinish(request: URLRequest, response: HTTPURLResponse?, data: Data) + func didFinish(request: URLRequest, error: Error) } open class URLSessionOpenAPITransport: OpenAPITransport { @@ -210,7 +214,10 @@ open class URLSessionOpenAPITransport: OpenAPITransport { self.config.delegate?.willStart(request: request) // Perform network call return self.config.session.dataTaskPublisher(for: request) - .mapError { OpenAPITransportError(statusCode: $0.code.rawValue, description: "Network call finished fails") } + .mapError { + self.config.delegate?.didFinish(request: request, error: $0) + return OpenAPITransportError(statusCode: $0.code.rawValue, description: "Network call finished fails") + } .flatMap { output in self.config.processor.decode(output: output) } @@ -225,7 +232,7 @@ open class URLSessionOpenAPITransport: OpenAPITransport { let transportResponse = OpenAPITransportResponse(data: output.data, statusCode: 200) return Result.success(transportResponse).publisher.eraseToAnyPublisher() case .retry: - return self.send(request: request, securitySchemes: securitySchemes) + return Fail(error: OpenAPITransportError.retryError).eraseToAnyPublisher() case .failure: let code = response?.statusCode ?? OpenAPITransportError.noResponseCode let transportError = OpenAPITransportError(statusCode: code, data: output.data) @@ -235,7 +242,9 @@ open class URLSessionOpenAPITransport: OpenAPITransport { } .eraseToAnyPublisher() } - .eraseToAnyPublisher() + .retry(times: 2) { error -> Bool in + return error.statusCode == OpenAPITransportError.retryError.statusCode + }.eraseToAnyPublisher() } open func cancelAll() { @@ -258,3 +267,32 @@ public extension URLSessionOpenAPITransport { } } } + +fileprivate extension Publishers { + struct RetryIf: Publisher { + typealias Output = P.Output + typealias Failure = P.Failure + + let publisher: P + let times: Int + let condition: (P.Failure) -> Bool + + func receive(subscriber: S) where S : Subscriber, Failure == S.Failure, Output == S.Input { + guard times > 0 else { return publisher.receive(subscriber: subscriber) } + + publisher.catch { (error: P.Failure) -> AnyPublisher in + if condition(error) { + return RetryIf(publisher: publisher, times: times - 1, condition: condition).eraseToAnyPublisher() + } else { + return Fail(error: error).eraseToAnyPublisher() + } + }.receive(subscriber: subscriber) + } + } +} + +fileprivate extension Publisher { + func retry(times: Int, if condition: @escaping (Failure) -> Bool) -> Publishers.RetryIf { + Publishers.RetryIf(publisher: self, times: times, condition: condition) + } +} diff --git a/modules/openapi-generator/src/main/resources/swift-alt/OpenISO8601DateFormatter.mustache b/modules/openapi-generator/src/main/resources/swift-alt/OpenISO8601DateFormatter.mustache index aeb29f3767db..f6a6fc82b733 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/OpenISO8601DateFormatter.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/OpenISO8601DateFormatter.mustache @@ -25,6 +25,8 @@ class OpenISO8601DateFormatter: DateFormatter { dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ" } + static var shared = OpenISO8601DateFormatter() + override init() { super.init() setup() diff --git a/modules/openapi-generator/src/main/resources/swift-alt/toString.mustache b/modules/openapi-generator/src/main/resources/swift-alt/toString.mustache index 659f3627dd7c..8d2a392a45a9 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/toString.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/toString.mustache @@ -1 +1 @@ -{{#isModel}}String(data: try self.encoder.encode({{paramName}}), encoding: .utf8){{/isModel}}{{^isModel}}{{#isArray}}{{paramName}}{{#vendorExtensions.x-swift-is-base-type-enum}}.map { $0.rawValue }{{/vendorExtensions.x-swift-is-base-type-enum}}.joined(separator: ", "){{/isArray}}{{^isArray}}{{#vendorExtensions.x-swift-is-enum-type}}{{paramName}}.rawValue{{/vendorExtensions.x-swift-is-enum-type}}{{^isEnum}}{{#isString}}{{paramName}}{{/isString}}{{#isInteger}}"\({{paramName}})"{{/isInteger}}{{#isDouble}}"\({{paramName}})"{{/isDouble}}{{#isFloat}}"\({{paramName}})"{{/isFloat}}{{#isNumber}}"\({{paramName}})"{{/isNumber}}{{#isBoolean}}{{paramName}} ? "true" : "false"{{/isBoolean}}{{/isEnum}}{{/isArray}}{{/isModel}} \ No newline at end of file +{{#isModel}}String(data: try self.encoder.encode({{paramName}}), encoding: .utf8){{/isModel}}{{^isModel}}{{#isArray}}{{paramName}}{{#vendorExtensions.x-swift-is-base-type-enum}}.map { $0.rawValue }{{/vendorExtensions.x-swift-is-base-type-enum}}.joined(separator: ", "){{/isArray}}{{^isArray}}{{#vendorExtensions.x-swift-is-enum-type}}{{paramName}}.rawValue{{/vendorExtensions.x-swift-is-enum-type}}{{^isEnum}}{{#isString}}{{paramName}}{{/isString}}{{#isInteger}}"\({{paramName}})"{{/isInteger}}{{#isDouble}}"\({{paramName}})"{{/isDouble}}{{#isFloat}}"\({{paramName}})"{{/isFloat}}{{#isNumber}}"\({{paramName}})"{{/isNumber}}{{#isBoolean}}{{paramName}} ? "true" : "false"{{/isBoolean}}{{/isEnum}}{{/isArray}}{{/isModel}}{{#isDateTime}}OpenISO8601DateFormatter.shared.string(from: {{paramName}}){{/isDateTime}} \ No newline at end of file From a70e04d34eb74beaca7efa019758ec7b266acb61 Mon Sep 17 00:00:00 2001 From: Anton Davydov Date: Sun, 10 Apr 2022 16:54:50 +0300 Subject: [PATCH 18/33] swift-alt v0.13.0 --- .../languages/SwiftAltClientCodegen.java | 6 +- .../src/main/resources/swift-alt/api.mustache | 143 +++++++++--------- .../resources/swift-alt/toString.mustache | 2 +- 3 files changed, 76 insertions(+), 75 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java index 13e8129263cc..e0c15d3b05d8 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java @@ -776,10 +776,14 @@ public Map postProcessOperationsWithModels(Map o protected void addVendorExtensions(CodegenParameter cp, CodegenOperation operation, HashMap modelMaps) { CodegenModel model = modelMaps.get(cp.dataType); + cp.vendorExtensions.put("x-swift-use-encoder", cp.isModel); if (cp.isArray && cp.items != null) { CodegenModel baseModel = modelMaps.get(cp.items.dataType); boolean isBaseTypeEnum = cp.items.isEnum || cp.isEnum || (baseModel != null && baseModel.isEnum); cp.vendorExtensions.put("x-swift-is-base-type-enum", isBaseTypeEnum); + + boolean useEncoder = !isBaseTypeEnum && !cp.items.isString || (baseModel != null && !baseModel.isString); + cp.vendorExtensions.put("x-swift-use-encoder", useEncoder); } if (cp.isEnum || (model != null && model.isEnum)) { cp.vendorExtensions.put("x-swift-is-enum-type", true); @@ -812,7 +816,7 @@ public void postProcess() { System.out.println("################################################################################"); System.out.println("# Thanks for using OpenAPI Generator. #"); System.out.println("# swift alternative generator is contributed by @dydus0x14 and @ptiz. #"); - System.out.println("# swift alternative generator v0.12.0 #"); + System.out.println("# swift alternative generator v0.13.0 #"); System.out.println("################################################################################"); } } diff --git a/modules/openapi-generator/src/main/resources/swift-alt/api.mustache b/modules/openapi-generator/src/main/resources/swift-alt/api.mustache index 753d7e1e70f4..4150283a2872 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/api.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/api.mustache @@ -15,7 +15,6 @@ open class {{classname}} { public var encoder: JSONEncoder = { let encoder = JSONEncoder() encoder.dateEncodingStrategy = .formatted(OpenISO8601DateFormatter()) - encoder.outputFormatting = .prettyPrinted return encoder }() public var decoder: JSONDecoder = { @@ -42,10 +41,8 @@ open class {{classname}} { {{/enumVars}} {{/allowableValues}} } - {{/isEnum}} {{/allParams}} - {{#vendorExtensions.x-swift-custom-error-type}} public enum {{{vendorExtensions.x-swift-custom-error-type}}}: Error, CustomStringConvertible { {{#responses}} @@ -93,76 +90,76 @@ open class {{classname}} { - returns: AnyPublisher<{{{returnType}}}{{^returnType}}Void{{/returnType}}, Error> {{description}} */ open func {{operationId}}({{#allParams}}{{paramName}}: {{{dataType}}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}) -> AnyPublisher<{{{returnType}}}{{^returnType}}Void{{/returnType}}, Error> { - return Result { - guard let baseURL = transport.baseURL ?? self.baseURL else { - throw OpenAPITransportError.badURLError() - } - let path = "{{path}}" - {{#pathParams}} - .replacingOccurrences(of: "{{=<% %>=}}{<%baseName%>}<%={{ }}=%>", with: "\({{paramName}})") - {{/pathParams}} - let url = baseURL.appendingPathComponent(path) - {{#hasQueryParams}}var{{/hasQueryParams}}{{^hasQueryParams}}let{{/hasQueryParams}} components = URLComponents(url: url, resolvingAgainstBaseURL: false) - {{#hasQueryParams}} - var queryItems: [URLQueryItem] = [] - {{#queryParams}} - {{#required}}queryItems.append(URLQueryItem(name: "{{baseName}}", value: {{> toString}})){{/required}}{{^required}}if let {{paramName}} = {{paramName}} { queryItems.append(URLQueryItem(name: "{{baseName}}", value: {{> toString}})) } {{/required}} - {{/queryParams}} - components?.queryItems = queryItems - {{/hasQueryParams}} - guard let requestURL = components?.url else { - throw OpenAPITransportError.badURLError() - } - var request = URLRequest(url: requestURL) - request.httpMethod = "{{httpMethod}}" - {{! Begin headers }} - {{#headerParams}} - {{#-last}} - request.allHTTPHeaderFields = [ - {{/-last}} - {{/headerParams}} - {{#headerParams}} - "{{baseName}}": {{paramName}}{{^-last}}, {{/-last}} - {{/headerParams}} - {{#headerParams}} - {{#-last}} - ].compactMapValues { $0 } - {{/-last}} - {{/headerParams}} - {{! Begin body }} - {{#hasBodyParam}} - {{#bodyParam}} - request.httpBody = try encoder.encode({{paramName}}) - request.setValue("application/json", forHTTPHeaderField: "Content-Type") - {{/bodyParam}} - {{/hasBodyParam}} - {{! Begin multipart form }} - {{#hasFormParams}} - {{#isMultipart}} - let multipartBoundary = String(format: "Boundary+%08X%08X", arc4random(), arc4random()) - var multipartData = Data() - {{#formParams}} -{{> toMultipartFormDataAppend}} - {{/formParams}} - multipartData.append("\r\n--\(multipartBoundary)--\r\n".data(using: .utf8) ?? Data()) - request.httpBody = multipartData - request.setValue("\(multipartData.count)", forHTTPHeaderField: "Content-Length") - request.setValue("multipart/form-data; boundary=\(multipartBoundary)", forHTTPHeaderField: "Content-Type") - {{/isMultipart}} - {{^isMultipart}} - {{! Begin form urlencoded }} - var formEncodedItems: [String] = [] - {{#formParams}} - {{#required}}formEncodedItems.append("{{baseName}}=\({{> toString}})"){{/required}}{{^required}}if let {{paramName}} = {{paramName}} { formEncodedItems.append("{{baseName}}=\({{> toString}})") } {{/required}} - {{/formParams}} - request.httpBody = formEncodedItems.joined(separator: "&").data(using: .utf8) - request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type") - {{/isMultipart}} - {{/hasFormParams}} - return request - } - .publisher - .flatMap { request -> AnyPublisher<{{{returnType}}}{{^returnType}}Void{{/returnType}}, Error> in + Deferred { + Result { + guard let baseURL = self.transport.baseURL ?? self.baseURL else { + throw OpenAPITransportError.badURLError() + } + {{#pathParams}}{{#-last}}var{{/-last}}{{/pathParams}}{{^pathParams}}let{{/pathParams}} path = "{{path}}" + {{#pathParams}} + {{#required}}path = path.replacingOccurrences(of: "{{=<% %>=}}{<%baseName%>}<%={{ }}=%>", with: {{> toString}}){{/required}}{{^required}}if let {{paramName}} = {{paramName}} { path = path.replacingOccurrences(of: "{{=<% %>=}}{<%baseName%>}<%={{ }}=%>", with: {{> toString}}) } {{/required}} + {{/pathParams}} + let url = baseURL.appendingPathComponent(path) + {{#hasQueryParams}}var{{/hasQueryParams}}{{^hasQueryParams}}let{{/hasQueryParams}} components = URLComponents(url: url, resolvingAgainstBaseURL: false) + {{#hasQueryParams}} + var queryItems: [URLQueryItem] = [] + {{#queryParams}} + {{#required}}queryItems.append(URLQueryItem(name: "{{baseName}}", value: {{> toString}})){{/required}}{{^required}}if let {{paramName}} = {{paramName}} { queryItems.append(URLQueryItem(name: "{{baseName}}", value: {{> toString}})) } {{/required}} + {{/queryParams}} + components?.queryItems = queryItems + {{/hasQueryParams}} + guard let requestURL = components?.url else { + throw OpenAPITransportError.badURLError() + } + var request = URLRequest(url: requestURL) + request.httpMethod = "{{httpMethod}}" + {{! Begin headers }} + {{#headerParams}} + {{#-last}} + request.allHTTPHeaderFields = [ + {{/-last}} + {{/headerParams}} + {{#headerParams}} + "{{baseName}}": {{paramName}}{{^-last}}, {{/-last}} + {{/headerParams}} + {{#headerParams}} + {{#-last}} + ].compactMapValues { $0 } + {{/-last}} + {{/headerParams}} + {{! Begin body }} + {{#hasBodyParam}} + {{#bodyParam}} + request.httpBody = try self.encoder.encode({{paramName}}) + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + {{/bodyParam}} + {{/hasBodyParam}} + {{! Begin multipart form }} + {{#hasFormParams}} + {{#isMultipart}} + let multipartBoundary = String(format: "Boundary+%08X%08X", arc4random(), arc4random()) + var multipartData = Data() + {{#formParams}} + {{> toMultipartFormDataAppend}} + {{/formParams}} + multipartData.append("\r\n--\(multipartBoundary)--\r\n".data(using: .utf8) ?? Data()) + request.httpBody = multipartData + request.setValue("\(multipartData.count)", forHTTPHeaderField: "Content-Length") + request.setValue("multipart/form-data; boundary=\(multipartBoundary)", forHTTPHeaderField: "Content-Type") + {{/isMultipart}} + {{^isMultipart}} + {{! Begin form urlencoded }} + var formEncodedItems: [String] = [] + {{#formParams}} + {{#required}}formEncodedItems.append("{{baseName}}=\({{> toString}})"){{/required}}{{^required}}if let {{paramName}} = {{paramName}} { formEncodedItems.append("{{baseName}}=\({{> toString}})") } {{/required}} + {{/formParams}} + request.httpBody = formEncodedItems.joined(separator: "&").data(using: .utf8) + request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type") + {{/isMultipart}} + {{/hasFormParams}} + return request + }.publisher + }.flatMap { request -> AnyPublisher<{{{returnType}}}{{^returnType}}Void{{/returnType}}, Error> in let securitySchemes: [SecurityScheme] = [{{#authMethods}}{{#isBasicBearer}}.bearer{{/isBasicBearer}}{{/authMethods}}] return self.transport.send(request: request, securitySchemes: securitySchemes) {{#vendorExtensions.x-swift-custom-error-type}} diff --git a/modules/openapi-generator/src/main/resources/swift-alt/toString.mustache b/modules/openapi-generator/src/main/resources/swift-alt/toString.mustache index 8d2a392a45a9..8c9d6cf1fb76 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/toString.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/toString.mustache @@ -1 +1 @@ -{{#isModel}}String(data: try self.encoder.encode({{paramName}}), encoding: .utf8){{/isModel}}{{^isModel}}{{#isArray}}{{paramName}}{{#vendorExtensions.x-swift-is-base-type-enum}}.map { $0.rawValue }{{/vendorExtensions.x-swift-is-base-type-enum}}.joined(separator: ", "){{/isArray}}{{^isArray}}{{#vendorExtensions.x-swift-is-enum-type}}{{paramName}}.rawValue{{/vendorExtensions.x-swift-is-enum-type}}{{^isEnum}}{{#isString}}{{paramName}}{{/isString}}{{#isInteger}}"\({{paramName}})"{{/isInteger}}{{#isDouble}}"\({{paramName}})"{{/isDouble}}{{#isFloat}}"\({{paramName}})"{{/isFloat}}{{#isNumber}}"\({{paramName}})"{{/isNumber}}{{#isBoolean}}{{paramName}} ? "true" : "false"{{/isBoolean}}{{/isEnum}}{{/isArray}}{{/isModel}}{{#isDateTime}}OpenISO8601DateFormatter.shared.string(from: {{paramName}}){{/isDateTime}} \ No newline at end of file +{{#isDateTime}}OpenISO8601DateFormatter.shared.string(from: {{paramName}}){{/isDateTime}}{{#vendorExtensions.x-swift-use-encoder}}String(data: try self.encoder.encode({{paramName}}), encoding: .utf8) ?? ""{{/vendorExtensions.x-swift-use-encoder}}{{^vendorExtensions.x-swift-use-encoder}}{{#isArray}}{{paramName}}{{#vendorExtensions.x-swift-is-base-type-enum}}.map { $0.rawValue }{{/vendorExtensions.x-swift-is-base-type-enum}}.joined(separator: ", "){{/isArray}}{{^isArray}}{{#vendorExtensions.x-swift-is-enum-type}}{{paramName}}.rawValue{{/vendorExtensions.x-swift-is-enum-type}}{{^isEnum}}{{#isString}}{{#isUuid}}{{paramName}}.uuidString{{/isUuid}}{{^isUuid}}{{paramName}}{{/isUuid}}{{/isString}}{{#isInteger}}"\({{paramName}})"{{/isInteger}}{{#isDouble}}"\({{paramName}})"{{/isDouble}}{{#isFloat}}"\({{paramName}})"{{/isFloat}}{{#isNumber}}"\({{paramName}})"{{/isNumber}}{{#isBoolean}}{{paramName}} ? "true" : "false"{{/isBoolean}}{{/isEnum}}{{/isArray}}{{/vendorExtensions.x-swift-use-encoder}} \ No newline at end of file From 43a60ecf6b59e4dfe9e6ced463e05d4330afe77d Mon Sep 17 00:00:00 2001 From: Anton Davydov Date: Fri, 29 Apr 2022 11:50:04 +0300 Subject: [PATCH 19/33] swift-alt v0.14.0 --- .../languages/SwiftAltClientCodegen.java | 6 ++-- .../src/main/resources/swift-alt/api.mustache | 26 +++++++--------- .../main/resources/swift-alt/model.mustache | 31 +++++++++++++++---- .../resources/swift-alt/modelObject.mustache | 6 ++-- .../swift-alt/modelObjectCustom.mustache | 4 +-- .../resources/swift-alt/modelOneOf.mustache | 2 +- .../resources/swift-alt/toString.mustache | 2 +- 7 files changed, 48 insertions(+), 29 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java index e0c15d3b05d8..23709fed18c8 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java @@ -55,7 +55,7 @@ public class SwiftAltClientCodegen extends DefaultCodegen implements CodegenConf protected String privateFolder = "Sources/Private"; protected String sourceFolder = "Sources"; protected String transportFolder = "OpenAPITransport"; - protected List notCodableTypes = Arrays.asList("Any", "AnyObject", "[String: Any]", "[String: [String: Any]"); + protected List notCodableTypes = Arrays.asList("Any", "AnyObject", "[String: Any]", "[String: [String: Any]]"); protected boolean mapFileBinaryToData = true; /** @@ -781,6 +781,8 @@ protected void addVendorExtensions(CodegenParameter cp, CodegenOperation operati CodegenModel baseModel = modelMaps.get(cp.items.dataType); boolean isBaseTypeEnum = cp.items.isEnum || cp.isEnum || (baseModel != null && baseModel.isEnum); cp.vendorExtensions.put("x-swift-is-base-type-enum", isBaseTypeEnum); + boolean isBaseTypeUdid = cp.items.isUuid || cp.isUuid; + cp.vendorExtensions.put("x-swift-is-base-type-udid", isBaseTypeUdid); boolean useEncoder = !isBaseTypeEnum && !cp.items.isString || (baseModel != null && !baseModel.isString); cp.vendorExtensions.put("x-swift-use-encoder", useEncoder); @@ -816,7 +818,7 @@ public void postProcess() { System.out.println("################################################################################"); System.out.println("# Thanks for using OpenAPI Generator. #"); System.out.println("# swift alternative generator is contributed by @dydus0x14 and @ptiz. #"); - System.out.println("# swift alternative generator v0.13.0 #"); + System.out.println("# swift alternative generator v0.14.0 #"); System.out.println("################################################################################"); } } diff --git a/modules/openapi-generator/src/main/resources/swift-alt/api.mustache b/modules/openapi-generator/src/main/resources/swift-alt/api.mustache index 4150283a2872..de218a2d3b8c 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/api.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/api.mustache @@ -65,30 +65,28 @@ open class {{classname}} { } {{/vendorExtensions.x-swift-custom-error-type}} - /** {{#summary}} - {{{.}}} + /// {{{.}}} {{/summary}} - - {{httpMethod}} {{{path}}}{{#notes}} - - {{{.}}}{{/notes}}{{#subresourceOperation}} - - subresourceOperation: {{.}}{{/subresourceOperation}}{{#defaultResponse}} - - defaultResponse: {{.}}{{/defaultResponse}} + /// - {{httpMethod}} {{{path}}}{{#notes}} + /// - {{{.}}}{{/notes}}{{#subresourceOperation}} + /// - subresourceOperation: {{.}}{{/subresourceOperation}}{{#defaultResponse}} + /// - defaultResponse: {{.}}{{/defaultResponse}} {{#authMethods}} - - {{#isBasic}}BASIC{{/isBasic}}{{#isOAuth}}OAuth{{/isOAuth}}{{#isApiKey}}API Key{{/isApiKey}}: - - type: {{type}}{{#keyParamName}} {{keyParamName}} {{#isKeyInQuery}}(QUERY){{/isKeyInQuery}}{{#isKeyInHeaer}}(HEADER){{/isKeyInHeaer}}{{/keyParamName}} - - name: {{name}} + /// - {{#isBasic}}BASIC{{/isBasic}}{{#isOAuth}}OAuth{{/isOAuth}}{{#isApiKey}}API Key{{/isApiKey}}: + /// - type: {{type}}{{#keyParamName}} {{keyParamName}} {{#isKeyInQuery}}(QUERY){{/isKeyInQuery}}{{#isKeyInHeaer}}(HEADER){{/isKeyInHeaer}}{{/keyParamName}} + /// - name: {{name}} {{/authMethods}} {{#hasResponseHeaders}} - - responseHeaders: [{{#responseHeaders}}{{{baseName}}}({{{dataType}}}){{^-last}}, {{/-last}}{{/responseHeaders}}] + /// - responseHeaders: [{{#responseHeaders}}{{{baseName}}}({{{dataType}}}){{^-last}}, {{/-last}}{{/responseHeaders}}] {{/hasResponseHeaders}} {{#externalDocs}} - - externalDocs: {{.}} + /// - externalDocs: {{.}} {{/externalDocs}} {{#allParams}} - - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + /// - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} {{/allParams}} - - returns: AnyPublisher<{{{returnType}}}{{^returnType}}Void{{/returnType}}, Error> {{description}} - */ + /// - returns: AnyPublisher<{{{returnType}}}{{^returnType}}Void{{/returnType}}, Error> {{description}} open func {{operationId}}({{#allParams}}{{paramName}}: {{{dataType}}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}) -> AnyPublisher<{{{returnType}}}{{^returnType}}Void{{/returnType}}, Error> { Deferred { Result { diff --git a/modules/openapi-generator/src/main/resources/swift-alt/model.mustache b/modules/openapi-generator/src/main/resources/swift-alt/model.mustache index 095cbabf12f0..02ec0fe4eb13 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/model.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/model.mustache @@ -7,10 +7,29 @@ import Foundation -{{#description}}/** {{.}} */{{/description}} +{{#description}} +/// {{.}} +{{/description}} {{#vendorExtensions.x-is-one-of-interface}} -{{> modelOneOf}}{{/vendorExtensions.x-is-one-of-interface}}{{^vendorExtensions.x-is-one-of-interface}}{{#isArray}} -{{> modelArray}}{{/isArray}}{{^isArray}}{{#isEnum}} -{{> modelEnum}}{{/isEnum}}{{^isEnum}}{{#vendorExtensions.x-swift-contains-not-codable}} -{{> modelObjectCustom}}{{/vendorExtensions.x-swift-contains-not-codable}}{{^vendorExtensions.x-swift-contains-not-codable}} -{{> modelObject}}{{/vendorExtensions.x-swift-contains-not-codable}}{{/isEnum}}{{/isArray}}{{/vendorExtensions.x-is-one-of-interface}}{{/model}}{{/models}} \ No newline at end of file +{{> modelOneOf}} +{{/vendorExtensions.x-is-one-of-interface}} +{{^vendorExtensions.x-is-one-of-interface}} +{{#isArray}} +{{> modelArray}} +{{/isArray}} +{{^isArray}} +{{#isEnum}} +{{> modelEnum}} +{{/isEnum}} +{{^isEnum}} +{{#vendorExtensions.x-swift-contains-not-codable}} +{{> modelObjectCustom}} +{{/vendorExtensions.x-swift-contains-not-codable}} +{{^vendorExtensions.x-swift-contains-not-codable}} +{{> modelObject}} +{{/vendorExtensions.x-swift-contains-not-codable}} +{{/isEnum}} +{{/isArray}} +{{/vendorExtensions.x-is-one-of-interface}} +{{/model}} +{{/models}} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/swift-alt/modelObject.mustache b/modules/openapi-generator/src/main/resources/swift-alt/modelObject.mustache index 11c4cf5d8a55..4ebc78dd99dd 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/modelObject.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/modelObject.mustache @@ -6,11 +6,11 @@ public struct {{{classname}}}: Codable { {{/allVars}} {{#allVars}} {{#isEnum}} - {{#description}}/** {{{.}}} */ + {{#description}}/// {{{.}}} {{/description}}public var {{{name}}}: {{{datatypeWithEnum}}}{{#required}}{{#isNullable}}?{{/isNullable}}{{/required}}{{^required}}?{{/required}}{{#defaultValue}} = {{{.}}}{{/defaultValue}} {{/isEnum}} {{^isEnum}} - {{#description}}/** {{{.}}} */ + {{#description}}/// {{{.}}} {{/description}}public var {{{name}}}: {{{datatype}}}{{#required}}{{#isNullable}}?{{/isNullable}}{{/required}}{{^required}}?{{/required}}{{#defaultValue}} = {{{.}}}{{/defaultValue}} {{/isEnum}} {{/allVars}} @@ -22,4 +22,4 @@ public struct {{{classname}}}: Codable { {{/allVars}} } {{/hasVars}} -} +} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/swift-alt/modelObjectCustom.mustache b/modules/openapi-generator/src/main/resources/swift-alt/modelObjectCustom.mustache index 2a5c3065847a..6b5b4d37c506 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/modelObjectCustom.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/modelObjectCustom.mustache @@ -6,11 +6,11 @@ public struct {{{classname}}}: Codable { {{/allVars}} {{#allVars}} {{#isEnum}} - {{#description}}/** {{{.}}} */ + {{#description}}/// {{{.}}} {{/description}}public var {{{name}}}: {{{datatypeWithEnum}}}{{#required}}{{#isNullable}}?{{/isNullable}}{{/required}}{{^required}}?{{/required}}{{#defaultValue}} = {{{.}}}{{/defaultValue}} {{/isEnum}} {{^isEnum}} - {{#description}}/** {{{.}}} */ + {{#description}}/// {{{.}}} {{/description}}public var {{{name}}}: {{{datatype}}}{{#required}}{{#isNullable}}?{{/isNullable}}{{/required}}{{^required}}?{{/required}}{{#defaultValue}} = {{{.}}}{{/defaultValue}} {{/isEnum}} {{/allVars}} diff --git a/modules/openapi-generator/src/main/resources/swift-alt/modelOneOf.mustache b/modules/openapi-generator/src/main/resources/swift-alt/modelOneOf.mustache index 8aeddcc3c123..db231c08fb5d 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/modelOneOf.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/modelOneOf.mustache @@ -28,4 +28,4 @@ public enum {{classname}}: Codable { throw DecodingError.typeMismatch(Self.Type.self, .init(codingPath: decoder.codingPath, debugDescription: "Unable to decode instance of {{classname}}")) } } -} +} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/swift-alt/toString.mustache b/modules/openapi-generator/src/main/resources/swift-alt/toString.mustache index 8c9d6cf1fb76..77f957f4d761 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/toString.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/toString.mustache @@ -1 +1 @@ -{{#isDateTime}}OpenISO8601DateFormatter.shared.string(from: {{paramName}}){{/isDateTime}}{{#vendorExtensions.x-swift-use-encoder}}String(data: try self.encoder.encode({{paramName}}), encoding: .utf8) ?? ""{{/vendorExtensions.x-swift-use-encoder}}{{^vendorExtensions.x-swift-use-encoder}}{{#isArray}}{{paramName}}{{#vendorExtensions.x-swift-is-base-type-enum}}.map { $0.rawValue }{{/vendorExtensions.x-swift-is-base-type-enum}}.joined(separator: ", "){{/isArray}}{{^isArray}}{{#vendorExtensions.x-swift-is-enum-type}}{{paramName}}.rawValue{{/vendorExtensions.x-swift-is-enum-type}}{{^isEnum}}{{#isString}}{{#isUuid}}{{paramName}}.uuidString{{/isUuid}}{{^isUuid}}{{paramName}}{{/isUuid}}{{/isString}}{{#isInteger}}"\({{paramName}})"{{/isInteger}}{{#isDouble}}"\({{paramName}})"{{/isDouble}}{{#isFloat}}"\({{paramName}})"{{/isFloat}}{{#isNumber}}"\({{paramName}})"{{/isNumber}}{{#isBoolean}}{{paramName}} ? "true" : "false"{{/isBoolean}}{{/isEnum}}{{/isArray}}{{/vendorExtensions.x-swift-use-encoder}} \ No newline at end of file +{{#isDateTime}}OpenISO8601DateFormatter.shared.string(from: {{paramName}}){{/isDateTime}}{{#vendorExtensions.x-swift-use-encoder}}String(data: try self.encoder.encode({{paramName}}), encoding: .utf8) ?? ""{{/vendorExtensions.x-swift-use-encoder}}{{^vendorExtensions.x-swift-use-encoder}}{{#isArray}}{{paramName}}{{#vendorExtensions.x-swift-is-base-type-udid}}.map { $0.uuidString }{{/vendorExtensions.x-swift-is-base-type-udid}}{{#vendorExtensions.x-swift-is-base-type-enum}}.map { $0.rawValue }{{/vendorExtensions.x-swift-is-base-type-enum}}.joined(separator: ", "){{/isArray}}{{^isArray}}{{#vendorExtensions.x-swift-is-enum-type}}{{paramName}}.rawValue{{/vendorExtensions.x-swift-is-enum-type}}{{^isEnum}}{{#isString}}{{#isUuid}}{{paramName}}.uuidString{{/isUuid}}{{^isUuid}}{{paramName}}{{/isUuid}}{{/isString}}{{#isInteger}}"\({{paramName}})"{{/isInteger}}{{#isDouble}}"\({{paramName}})"{{/isDouble}}{{#isFloat}}"\({{paramName}})"{{/isFloat}}{{#isNumber}}"\({{paramName}})"{{/isNumber}}{{#isBoolean}}{{paramName}} ? "true" : "false"{{/isBoolean}}{{/isEnum}}{{/isArray}}{{/vendorExtensions.x-swift-use-encoder}} \ No newline at end of file From 84b32f3349bf8e7f9ed4989ad0165d2e3833a840 Mon Sep 17 00:00:00 2001 From: Anton Davydov Date: Thu, 12 May 2022 12:27:11 +0300 Subject: [PATCH 20/33] swift-alt v0.15.0 --- .../languages/SwiftAltClientCodegen.java | 2 +- .../src/main/resources/swift-alt/api.mustache | 2 +- .../toMultipartFormDataAppend.mustache | 82 ++++++++++++------- 3 files changed, 54 insertions(+), 32 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java index 23709fed18c8..8e5efd8e0fbd 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java @@ -818,7 +818,7 @@ public void postProcess() { System.out.println("################################################################################"); System.out.println("# Thanks for using OpenAPI Generator. #"); System.out.println("# swift alternative generator is contributed by @dydus0x14 and @ptiz. #"); - System.out.println("# swift alternative generator v0.14.0 #"); + System.out.println("# swift alternative generator v0.15.0 #"); System.out.println("################################################################################"); } } diff --git a/modules/openapi-generator/src/main/resources/swift-alt/api.mustache b/modules/openapi-generator/src/main/resources/swift-alt/api.mustache index de218a2d3b8c..32a7d96e3e80 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/api.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/api.mustache @@ -138,7 +138,7 @@ open class {{classname}} { let multipartBoundary = String(format: "Boundary+%08X%08X", arc4random(), arc4random()) var multipartData = Data() {{#formParams}} - {{> toMultipartFormDataAppend}} +{{> toMultipartFormDataAppend}} {{/formParams}} multipartData.append("\r\n--\(multipartBoundary)--\r\n".data(using: .utf8) ?? Data()) request.httpBody = multipartData diff --git a/modules/openapi-generator/src/main/resources/swift-alt/toMultipartFormDataAppend.mustache b/modules/openapi-generator/src/main/resources/swift-alt/toMultipartFormDataAppend.mustache index 9837a666ed6e..de65327b131a 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/toMultipartFormDataAppend.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/toMultipartFormDataAppend.mustache @@ -1,37 +1,59 @@ - {{#vendorExtensions.x-swift-enumerate-multipart}} - {{^mapFileBinaryToData}}try {{/mapFileBinaryToData}}{{paramName}}{{^required}}?{{/required}}.enumerated().forEach { index, {{paramName}} in - {{#mapFileBinaryToData}} - let filename = "\({{paramName}})\(index)" - {{/mapFileBinaryToData}} - {{^mapFileBinaryToData}} - let filename = {{paramName}}.lastPathComponent - {{/mapFileBinaryToData}} + {{#vendorExtensions.x-swift-enumerate-multipart}} + {{^mapFileBinaryToData}}try {{/mapFileBinaryToData}}{{paramName}}{{^required}}?{{/required}}.enumerated().forEach { index, {{paramName}} in + {{#mapFileBinaryToData}} + let filename = "\({{paramName}})\(index)" + {{/mapFileBinaryToData}} + {{^mapFileBinaryToData}} + let filename = {{paramName}}.lastPathComponent + {{/mapFileBinaryToData}} + let {{paramName}}Header = "--\(multipartBoundary)\r\n" + .appending("Content-Disposition:form-data; name=\"{{paramName}}\"; filename=\"\(filename)\"\r\n") + {{#contentType}} + .appending("Content-Type: {{{contentType}}}\r\n") + {{/contentType}} + .appending("\r\n") + multipartData.append({{paramName}}Header.data(using: .utf8) ?? Data()) + multipartData.append({{#items}}{{> toData}}{{/items}}) + multipartData.append("\r\n".data(using: .utf8) ?? Data()) + } + {{/vendorExtensions.x-swift-enumerate-multipart}} + {{^vendorExtensions.x-swift-enumerate-multipart}} + {{#required}} let {{paramName}}Header = "--\(multipartBoundary)\r\n" - .appending("Content-Disposition:form-data; name=\"{{paramName}}\"; filename=\"\(filename)\"\r\n") + {{#isFile}} + .appending("Content-Disposition:form-data; name=\"{{paramName}}\"; filename=\"{{paramName}}\"\r\n") + {{/isFile}} + {{^isFile}} + .appending("Content-Disposition:form-data; name=\"{{paramName}}\"\r\n") + {{/isFile}} {{#contentType}} .appending("Content-Type: {{{contentType}}}\r\n") {{/contentType}} .appending("\r\n") multipartData.append({{paramName}}Header.data(using: .utf8) ?? Data()) - multipartData.append({{#items}}{{> toData}}{{/items}}) + multipartData.append({{> toData}}) + {{^-last}} multipartData.append("\r\n".data(using: .utf8) ?? Data()) - } - {{/vendorExtensions.x-swift-enumerate-multipart}} - {{^vendorExtensions.x-swift-enumerate-multipart}} - let {{paramName}}Header = "--\(multipartBoundary)\r\n" - {{#isFile}} - .appending("Content-Disposition:form-data; name=\"{{paramName}}\"; filename=\"{{paramName}}\"\r\n") - {{/isFile}} - {{^isFile}} - .appending("Content-Disposition:form-data; name=\"{{paramName}}\"\r\n") - {{/isFile}} - {{#contentType}} - .appending("Content-Type: {{{contentType}}}\r\n") - {{/contentType}} - .appending("\r\n") - multipartData.append({{paramName}}Header.data(using: .utf8) ?? Data()) - {{#required}}multipartData.append({{> toData}}){{/required}}{{^required}}if let {{paramName}} = {{paramName}} { multipartData.append({{> toData}}) }{{/required}} - {{^-last}} - multipartData.append("\r\n".data(using: .utf8) ?? Data()) - {{/-last}} - {{/vendorExtensions.x-swift-enumerate-multipart}} \ No newline at end of file + {{/-last}} + {{/required}} + {{^required}} + if let {{paramName}} = {{paramName}} { + let {{paramName}}Header = "--\(multipartBoundary)\r\n" + {{#isFile}} + .appending("Content-Disposition:form-data; name=\"{{paramName}}\"; filename=\"{{paramName}}\"\r\n") + {{/isFile}} + {{^isFile}} + .appending("Content-Disposition:form-data; name=\"{{paramName}}\"\r\n") + {{/isFile}} + {{#contentType}} + .appending("Content-Type: {{{contentType}}}\r\n") + {{/contentType}} + .appending("\r\n") + multipartData.append({{paramName}}Header.data(using: .utf8) ?? Data()) + multipartData.append({{> toData}}) + {{^-last}} + multipartData.append("\r\n".data(using: .utf8) ?? Data()) + {{/-last}} + } + {{/required}} + {{/vendorExtensions.x-swift-enumerate-multipart}} \ No newline at end of file From c9d5cc50612f3d9bbef336084dc4c3cbcba6104c Mon Sep 17 00:00:00 2001 From: Anton Davydov Date: Tue, 14 Jun 2022 18:33:58 +0300 Subject: [PATCH 21/33] swift-alt v0.16.0 --- .../openapitools/codegen/languages/SwiftAltClientCodegen.java | 2 +- .../src/main/resources/swift-alt/OpenAPITransport.mustache | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java index 8e5efd8e0fbd..e8b1afa334e6 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java @@ -818,7 +818,7 @@ public void postProcess() { System.out.println("################################################################################"); System.out.println("# Thanks for using OpenAPI Generator. #"); System.out.println("# swift alternative generator is contributed by @dydus0x14 and @ptiz. #"); - System.out.println("# swift alternative generator v0.15.0 #"); + System.out.println("# swift alternative generator v0.16.0 #"); System.out.println("################################################################################"); } } diff --git a/modules/openapi-generator/src/main/resources/swift-alt/OpenAPITransport.mustache b/modules/openapi-generator/src/main/resources/swift-alt/OpenAPITransport.mustache index bb7fca57c712..99dc41cc125e 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/OpenAPITransport.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/OpenAPITransport.mustache @@ -63,7 +63,7 @@ final class DefaultURLRequestProcessor: URLRequestProcessor { // MARK: - OpenAPITransport -public protocol OpenAPITransport { +public protocol OpenAPITransport: AnyObject { var baseURL: URL? { get } func send( From 31f0ef03c9c6cf0deb018ead950d12dfbb621d3b Mon Sep 17 00:00:00 2001 From: Anton Davydov Date: Fri, 4 Nov 2022 10:22:27 +0300 Subject: [PATCH 22/33] swift-alt v0.17.0 --- .../codegen/languages/SwiftAltClientCodegen.java | 2 +- .../resources/swift-alt/OpenAPITransportPackage.mustache | 1 - .../src/main/resources/swift-alt/Package.mustache | 1 - .../src/main/resources/swift-alt/api.mustache | 8 ++++---- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java index e8b1afa334e6..6f9e97e5ff97 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java @@ -818,7 +818,7 @@ public void postProcess() { System.out.println("################################################################################"); System.out.println("# Thanks for using OpenAPI Generator. #"); System.out.println("# swift alternative generator is contributed by @dydus0x14 and @ptiz. #"); - System.out.println("# swift alternative generator v0.16.0 #"); + System.out.println("# swift alternative generator v0.17.0 #"); System.out.println("################################################################################"); } } diff --git a/modules/openapi-generator/src/main/resources/swift-alt/OpenAPITransportPackage.mustache b/modules/openapi-generator/src/main/resources/swift-alt/OpenAPITransportPackage.mustache index 1235c42ca84e..916f6dfd64d0 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/OpenAPITransportPackage.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/OpenAPITransportPackage.mustache @@ -11,7 +11,6 @@ let package = Package( products: [ .library( name: "OpenAPITransport", - type: .static, targets: ["OpenAPITransport"] ), ], diff --git a/modules/openapi-generator/src/main/resources/swift-alt/Package.mustache b/modules/openapi-generator/src/main/resources/swift-alt/Package.mustache index 31e8eeda6b5c..c1cc2a5f3a77 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/Package.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/Package.mustache @@ -11,7 +11,6 @@ let package = Package( products: [ .library( name: "{{projectName}}", - type: .static, targets: ["{{projectName}}"] ), ], diff --git a/modules/openapi-generator/src/main/resources/swift-alt/api.mustache b/modules/openapi-generator/src/main/resources/swift-alt/api.mustache index 32a7d96e3e80..7b75f930ab32 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/api.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/api.mustache @@ -9,7 +9,7 @@ import Combine import OpenAPITransport {{#description}} -/** {{{.}}} */{{/description}} +/// {{{.}}} {{/description}} open class {{classname}} { private let transport: OpenAPITransport public var encoder: JSONEncoder = { @@ -31,9 +31,9 @@ open class {{classname}} { {{#allParams}} {{#isEnum}} - /** - * enum for parameter {{paramName}} - */ + /// + /// Enum for parameter {{paramName}} + /// public enum {{{vendorExtensions.x-swift-nested-enum-type}}}: {{{baseType}}}, Codable, CaseIterable { {{#allowableValues}} {{#enumVars}} From 16225d7077108d2205955ecc0cf9ca0c9bb76437 Mon Sep 17 00:00:00 2001 From: Anton Davydov Date: Wed, 9 Nov 2022 11:57:07 +0300 Subject: [PATCH 23/33] swift-alt v0.18.0 --- .../openapitools/codegen/languages/SwiftAltClientCodegen.java | 2 +- .../src/main/resources/swift-alt/api.mustache | 3 +++ .../src/main/resources/swift-alt/modelObject.mustache | 3 +++ .../src/main/resources/swift-alt/modelObjectCustom.mustache | 3 +++ .../src/main/resources/swift-alt/modelOneOf.mustache | 3 +++ 5 files changed, 13 insertions(+), 1 deletion(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java index 6f9e97e5ff97..887d392fc9bd 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java @@ -818,7 +818,7 @@ public void postProcess() { System.out.println("################################################################################"); System.out.println("# Thanks for using OpenAPI Generator. #"); System.out.println("# swift alternative generator is contributed by @dydus0x14 and @ptiz. #"); - System.out.println("# swift alternative generator v0.17.0 #"); + System.out.println("# swift alternative generator v0.18.0 #"); System.out.println("################################################################################"); } } diff --git a/modules/openapi-generator/src/main/resources/swift-alt/api.mustache b/modules/openapi-generator/src/main/resources/swift-alt/api.mustache index 7b75f930ab32..c83e364bb103 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/api.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/api.mustache @@ -87,6 +87,9 @@ open class {{classname}} { /// - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} {{/allParams}} /// - returns: AnyPublisher<{{{returnType}}}{{^returnType}}Void{{/returnType}}, Error> {{description}} + {{#isDeprecated}} + @available(*, deprecated, message: "Deprecated API operation") + {{/isDeprecated}} open func {{operationId}}({{#allParams}}{{paramName}}: {{{dataType}}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}) -> AnyPublisher<{{{returnType}}}{{^returnType}}Void{{/returnType}}, Error> { Deferred { Result { diff --git a/modules/openapi-generator/src/main/resources/swift-alt/modelObject.mustache b/modules/openapi-generator/src/main/resources/swift-alt/modelObject.mustache index 4ebc78dd99dd..fbd65a9806d1 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/modelObject.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/modelObject.mustache @@ -1,3 +1,6 @@ +{{#isDeprecated}} +@available(*, deprecated, message: "Deprecated API parameter") +{{/isDeprecated}} public struct {{{classname}}}: Codable { {{#allVars}} {{#isEnum}} diff --git a/modules/openapi-generator/src/main/resources/swift-alt/modelObjectCustom.mustache b/modules/openapi-generator/src/main/resources/swift-alt/modelObjectCustom.mustache index 6b5b4d37c506..3a350e194318 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/modelObjectCustom.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/modelObjectCustom.mustache @@ -1,3 +1,6 @@ +{{#isDeprecated}} +@available(*, deprecated, message: "Deprecated API parameter") +{{/isDeprecated}} public struct {{{classname}}}: Codable { {{#allVars}} {{#isEnum}} diff --git a/modules/openapi-generator/src/main/resources/swift-alt/modelOneOf.mustache b/modules/openapi-generator/src/main/resources/swift-alt/modelOneOf.mustache index db231c08fb5d..a9fc95282106 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/modelOneOf.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/modelOneOf.mustache @@ -1,3 +1,6 @@ +{{#isDeprecated}} +@available(*, deprecated, message: "Deprecated API parameter") +{{/isDeprecated}} public enum {{classname}}: Codable { {{#oneOf}} case type{{.}}({{.}}) From b040b9a25dd4ec421540251a778325318dda25e7 Mon Sep 17 00:00:00 2001 From: Anton Davydov Date: Sun, 20 Nov 2022 11:51:12 +0300 Subject: [PATCH 24/33] swift-alt v0.19.0 Support for raw value in header --- .../openapitools/codegen/languages/SwiftAltClientCodegen.java | 3 ++- .../src/main/resources/swift-alt/api.mustache | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java index 887d392fc9bd..112402b0bc8d 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java @@ -756,6 +756,7 @@ public Map postProcessOperationsWithModels(Map o for (CodegenOperation operation : operations) { operation.allParams.forEach(cp -> addVendorExtensions(cp, operation, modelMaps)); operation.queryParams.forEach(cp -> addVendorExtensions(cp, operation, modelMaps)); + operation.headerParams.forEach(cp -> addVendorExtensions(cp, operation, modelMaps)); operation.bodyParams.forEach(cp -> addVendorExtensions(cp, operation, modelMaps)); operation.formParams.forEach(cp -> addFormVendorExtensions(cp, operation, modelMaps)); if (notCodableTypes.contains(operation.returnType) || notCodableTypes.contains(operation.returnBaseType)) { @@ -818,7 +819,7 @@ public void postProcess() { System.out.println("################################################################################"); System.out.println("# Thanks for using OpenAPI Generator. #"); System.out.println("# swift alternative generator is contributed by @dydus0x14 and @ptiz. #"); - System.out.println("# swift alternative generator v0.18.0 #"); + System.out.println("# swift alternative generator v0.19.0 #"); System.out.println("################################################################################"); } } diff --git a/modules/openapi-generator/src/main/resources/swift-alt/api.mustache b/modules/openapi-generator/src/main/resources/swift-alt/api.mustache index c83e364bb103..a069c86f9353 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/api.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/api.mustache @@ -121,7 +121,7 @@ open class {{classname}} { {{/-last}} {{/headerParams}} {{#headerParams}} - "{{baseName}}": {{paramName}}{{^-last}}, {{/-last}} + "{{baseName}}": {{> toString}}{{^-last}}, {{/-last}} {{/headerParams}} {{#headerParams}} {{#-last}} From 1cab8c2288b39b30dad2df69a2dcc4abb5425661 Mon Sep 17 00:00:00 2001 From: Anton Davydov Date: Fri, 17 Feb 2023 18:05:29 +0300 Subject: [PATCH 25/33] swift-alt v0.20.0 --- .../openapitools/codegen/languages/SwiftAltClientCodegen.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java index 112402b0bc8d..701b43269459 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java @@ -421,6 +421,8 @@ public String toDefaultValue(Schema p) { Instant instant = ((OffsetDateTime) p.getDefault()).toInstant(); long epochMicro = TimeUnit.SECONDS.toMicros(instant.getEpochSecond()) + (instant.get(ChronoField.MICRO_OF_SECOND)); return "Date(timeIntervalSince1970: " + String.valueOf(epochMicro) + ".0 / 1_000_000)"; + } else if (ModelUtils.isUUIDSchema(p)) { + return "\"" + escapeText(p.getDefault().toString()) + "\""; } else if (ModelUtils.isStringSchema(p)) { return "\"" + escapeText((String) p.getDefault()) + "\""; } @@ -819,7 +821,7 @@ public void postProcess() { System.out.println("################################################################################"); System.out.println("# Thanks for using OpenAPI Generator. #"); System.out.println("# swift alternative generator is contributed by @dydus0x14 and @ptiz. #"); - System.out.println("# swift alternative generator v0.19.0 #"); + System.out.println("# swift alternative generator v0.20.0 #"); System.out.println("################################################################################"); } } From bf952c05ad91f333f18835fb44f75bde65607a9d Mon Sep 17 00:00:00 2001 From: Anton Davydov Date: Tue, 16 May 2023 11:07:16 +0300 Subject: [PATCH 26/33] swift-alt v0.21.0 --- .../languages/SwiftAltClientCodegen.java | 35 +++--- .../resources/swift-alt/AnyDecodable.mustache | 117 ++++++++++++++++++ .../src/main/resources/swift-alt/api.mustache | 6 +- .../swift-alt/modelObjectCustom.mustache | 20 --- 4 files changed, 139 insertions(+), 39 deletions(-) create mode 100644 modules/openapi-generator/src/main/resources/swift-alt/AnyDecodable.mustache diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java index 701b43269459..5b20b7320cd6 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java @@ -55,9 +55,11 @@ public class SwiftAltClientCodegen extends DefaultCodegen implements CodegenConf protected String privateFolder = "Sources/Private"; protected String sourceFolder = "Sources"; protected String transportFolder = "OpenAPITransport"; - protected List notCodableTypes = Arrays.asList("Any", "AnyObject", "[String: Any]", "[String: [String: Any]]"); + protected List notCodableTypes = Arrays.asList("Any", "AnyObject", "[String: Any]", "[String: [String: Any]]", "[Any]"); protected boolean mapFileBinaryToData = true; + protected boolean anyDecoderWasAdded = false; + /** * Constructor for the swift alt language codegen module. */ @@ -232,6 +234,7 @@ public String getHelp() { public void processOpts() { super.processOpts(); + anyDecoderWasAdded = false; if (StringUtils.isEmpty(System.getenv("SWIFT_POST_PROCESS_FILE"))) { LOGGER.info("Environment variable SWIFT_POST_PROCESS_FILE not defined so the Swift code may not be properly formatted. To define it, try 'export SWIFT_POST_PROCESS_FILE=/usr/local/bin/swiftformat' (Linux/Mac)"); LOGGER.info("NOTE: To enable file post-processing, 'enablePostProcessFile' must be set to `true` (--enable-post-process-file for CLI)."); @@ -665,20 +668,6 @@ public String toEnumName(CodegenProperty property) { @Override public Map postProcessModels(Map objs) { Map postProcessedModelsEnum = postProcessModelsEnum(objs); - - // We iterate through the list of models, and also iterate through each of the - // properties for each model. For each property, if: - // - // CodegenProperty.name != CodegenProperty.baseName - // - // then we set - // - // CodegenProperty.vendorExtensions["x-codegen-escaped-property-name"] = true - // - // Also, if any property in the model has x-codegen-escaped-property-name=true, then we mark: - // - // CodegenModel.vendorExtensions["x-codegen-has-escaped-property-names"] = true - // List models = (List) postProcessedModelsEnum.get("models"); for (Object _mo : models) { Map mo = (Map) _mo; @@ -694,6 +683,7 @@ public Map postProcessModels(Map objs) { } if (modelHasPropertyWithEscapedName || notCodableTypes.contains(prop.dataType) || notCodableTypes.contains(prop.baseType)) { cm.vendorExtensions.put("x-swift-contains-not-codable", true); + addAnyDecoderIfNeeded(); } } if (modelHasPropertyWithEscapedName) { @@ -763,6 +753,7 @@ public Map postProcessOperationsWithModels(Map o operation.formParams.forEach(cp -> addFormVendorExtensions(cp, operation, modelMaps)); if (notCodableTypes.contains(operation.returnType) || notCodableTypes.contains(operation.returnBaseType)) { operation.vendorExtensions.put("x-swift-is-not-codable", true); + addAnyDecoderIfNeeded(); } List responses = operation.responses; for (CodegenResponse response : responses) { @@ -821,7 +812,19 @@ public void postProcess() { System.out.println("################################################################################"); System.out.println("# Thanks for using OpenAPI Generator. #"); System.out.println("# swift alternative generator is contributed by @dydus0x14 and @ptiz. #"); - System.out.println("# swift alternative generator v0.20.0 #"); + System.out.println("# swift alternative generator v0.21.0 #"); System.out.println("################################################################################"); } + + @Override + public GeneratorLanguage generatorLanguage() { return GeneratorLanguage.SWIFT; } + + protected void addAnyDecoderIfNeeded() { + if (!anyDecoderWasAdded) { + supportingFiles.add(new SupportingFile("AnyDecodable.mustache", + projectName + File.separator + privateFolder, + "AnyDecodable.swift")); + anyDecoderWasAdded = true; + } + } } diff --git a/modules/openapi-generator/src/main/resources/swift-alt/AnyDecodable.mustache b/modules/openapi-generator/src/main/resources/swift-alt/AnyDecodable.mustache new file mode 100644 index 000000000000..0897aa88829e --- /dev/null +++ b/modules/openapi-generator/src/main/resources/swift-alt/AnyDecodable.mustache @@ -0,0 +1,117 @@ +// AnyDecodable.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + +extension KeyedDecodingContainer { + func decode(_ type: Dictionary.Type, forKey key: K) throws -> Dictionary { + let container = try self.nestedContainer(keyedBy: AnyCodingKeys.self, forKey: key) + return try container.decode(type) + } + + func decodeIfPresent(_ type: Dictionary.Type, forKey key: K) throws -> Dictionary? { + if contains(key) { + return try decode(type, forKey: key) + } + return nil + } + + func decode(_ type: Array.Type, forKey key: K) throws -> Array { + var container = try self.nestedUnkeyedContainer(forKey: key) + return try container.decode(type) + } + + func decodeIfPresent(_ type: Array.Type, forKey key: K) throws -> Array? { + if contains(key) { + return try decode(type, forKey: key) + } + return nil + } + + func decode(_ type: Dictionary>.Type, forKey key: K) throws -> Dictionary> { + let container = try self.nestedContainer(keyedBy: AnyCodingKeys.self, forKey: key) + return try container.decode(type) + } + + func decodeIfPresent(_ type: Dictionary>.Type, forKey key: K) throws -> Dictionary>? { + if contains(key) { + return try decode(type, forKey: key) + } + return nil + } + + func decode(_ type: Dictionary.Type) throws -> Dictionary { + var dictionary = Dictionary() + + for key in allKeys { + if let boolValue = try? decode(Bool.self, forKey: key) { + dictionary[key.stringValue] = boolValue + } else if let stringValue = try? decode(String.self, forKey: key) { + dictionary[key.stringValue] = stringValue + } else if let intValue = try? decode(Int.self, forKey: key) { + dictionary[key.stringValue] = intValue + } else if let doubleValue = try? decode(Double.self, forKey: key) { + dictionary[key.stringValue] = doubleValue + } else if let nestedDictionary = try? decode(Dictionary.self, forKey: key) { + dictionary[key.stringValue] = nestedDictionary + } else if let nestedArray = try? decode(Array.self, forKey: key) { + dictionary[key.stringValue] = nestedArray + } + } + return dictionary + } + + func decode(_ type: Dictionary>.Type) throws -> Dictionary> { + var dictionary = Dictionary>() + + for key in allKeys { + if let nestedDictionary = try? decode(Dictionary.self, forKey: key) { + dictionary[key.stringValue] = nestedDictionary + } + } + return dictionary + } +} + +extension UnkeyedDecodingContainer { + mutating func decode(_ type: Array.Type) throws -> Array { + var array: [Any] = [] + while isAtEnd == false { + if let value = try? decode(Bool.self) { + array.append(value) + } else if let value = try? decode(Double.self) { + array.append(value) + } else if let value = try? decode(String.self) { + array.append(value) + } else if let nestedDictionary = try? decode(Dictionary.self) { + array.append(nestedDictionary) + } else if let nestedArray = try? decode(Array.self) { + array.append(nestedArray) + } + } + return array + } + + mutating func decode(_ type: Dictionary.Type) throws -> Dictionary { + let nestedContainer = try self.nestedContainer(keyedBy: AnyCodingKeys.self) + return try nestedContainer.decode(type) + } +} + +private struct AnyCodingKeys: CodingKey { + var stringValue: String + + init(stringValue: String) { + self.stringValue = stringValue + } + + var intValue: Int? + + init?(intValue: Int) { + self.init(stringValue: "\(intValue)") + self.intValue = intValue + } +} diff --git a/modules/openapi-generator/src/main/resources/swift-alt/api.mustache b/modules/openapi-generator/src/main/resources/swift-alt/api.mustache index a069c86f9353..1e1b981773f2 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/api.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/api.mustache @@ -117,15 +117,15 @@ open class {{classname}} { {{! Begin headers }} {{#headerParams}} {{#-last}} - request.allHTTPHeaderFields = [ + var headers = [String: String]() {{/-last}} {{/headerParams}} {{#headerParams}} - "{{baseName}}": {{> toString}}{{^-last}}, {{/-last}} + {{#required}}headers["{{baseName}}"] = {{> toString}}{{/required}}{{^required}}if let {{paramName}} = {{paramName}} { headers["{{baseName}}"] = {{> toString}} }{{/required}} {{/headerParams}} {{#headerParams}} {{#-last}} - ].compactMapValues { $0 } + request.allHTTPHeaderFields = headers {{/-last}} {{/headerParams}} {{! Begin body }} diff --git a/modules/openapi-generator/src/main/resources/swift-alt/modelObjectCustom.mustache b/modules/openapi-generator/src/main/resources/swift-alt/modelObjectCustom.mustache index 3a350e194318..4b1ecf700e64 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/modelObjectCustom.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/modelObjectCustom.mustache @@ -35,27 +35,7 @@ public struct {{{classname}}}: Codable { public init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) {{#allVars}} - {{#vendorExtensions.x-swift-is-not-codable}} - {{#required}} - if let object = try JSONSerialization.jsonObject(with: try container.decode(Data.self, forKey: .{{{name}}})) as? {{{datatypeWithEnum}}} { - {{{name}}} = object - } else { - throw DecodingError.typeMismatch({{{datatypeWithEnum}}}.self, .init(codingPath: [CodingKeys.{{{name}}}], debugDescription: "Unable to cast types while decoding {{{classname}}}")) - } - {{/required}} - {{^required}} - if container.contains(.{{{name}}}) { - if let object = try JSONSerialization.jsonObject(with: try container.decode(Data.self, forKey: .{{{name}}})) as? {{{datatypeWithEnum}}} { - {{{name}}} = object - } else { - throw DecodingError.typeMismatch({{{datatypeWithEnum}}}.self, .init(codingPath: [CodingKeys.{{{name}}}], debugDescription: "Unable to cast types while decoding {{{classname}}}")) - } - } - {{/required}} - {{/vendorExtensions.x-swift-is-not-codable}} - {{^vendorExtensions.x-swift-is-not-codable}} {{{name}}} = try container.decode{{^required}}IfPresent{{/required}}({{{datatypeWithEnum}}}.self, forKey: .{{{name}}}) - {{/vendorExtensions.x-swift-is-not-codable}} {{/allVars}} } From 1d1f4e5876877ed65eabbbeefe0b0cbeb4542e84 Mon Sep 17 00:00:00 2001 From: Anton Davydov Date: Thu, 8 Jun 2023 16:25:28 +0300 Subject: [PATCH 27/33] swift-alt v0.22.0 --- .../languages/SwiftAltClientCodegen.java | 52 +++++++------------ .../resources/swift-alt/toString.mustache | 2 +- .../SwiftAltClientCodegenModelTest.java | 29 ----------- .../SwiftAltClientCodegenOptionsTest.java | 30 ----------- .../swift-alt/SwiftAltClientCodegenTest.java | 19 ------- 5 files changed, 21 insertions(+), 111 deletions(-) delete mode 100644 modules/openapi-generator/src/test/java/org/openapitools/codegen/swift-alt/SwiftAltClientCodegenModelTest.java delete mode 100644 modules/openapi-generator/src/test/java/org/openapitools/codegen/swift-alt/SwiftAltClientCodegenOptionsTest.java delete mode 100644 modules/openapi-generator/src/test/java/org/openapitools/codegen/swift-alt/SwiftAltClientCodegenTest.java diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java index 5b20b7320cd6..d8fc1072fca7 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java @@ -27,6 +27,9 @@ import org.openapitools.codegen.*; import org.openapitools.codegen.meta.GeneratorMetadata; import org.openapitools.codegen.meta.Stability; +import org.openapitools.codegen.model.ModelMap; +import org.openapitools.codegen.model.ModelsMap; +import org.openapitools.codegen.model.OperationsMap; import org.openapitools.codegen.utils.ModelUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -44,6 +47,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import static org.openapitools.codegen.utils.CamelizeOption.LOWERCASE_FIRST_LETTER; import static org.openapitools.codegen.utils.StringUtils.camelize; public class SwiftAltClientCodegen extends DefaultCodegen implements CodegenConfig { @@ -211,24 +215,8 @@ public String getName() { @Override public String getHelp() { - return "Generates a Swift 5 alternative client library."; - } - -// @Override -// protected void addAdditionPropertiesToCodeGenModel(CodegenModel codegenModel, -// Schema schema) { -// final Schema additionalProperties = getAdditionalProperties(schema); -// if (additionalProperties != null) { -// Schema inner = null; -// if (ModelUtils.isArraySchema(schema)) { -// ArraySchema ap = (ArraySchema) schema; -// inner = ap.getItems(); -// } else if (ModelUtils.isMapSchema(schema)) { -// inner = getAdditionalProperties(schema); -// } -// codegenModel.additionalPropertiesType = inner != null ? getTypeDeclaration(inner) : getSchemaType(additionalProperties); -// } -// } + return "Generates a Swift alternative client library."; + } @Override public void processOpts() { @@ -466,7 +454,7 @@ public String toApiDocFilename(String name) { @Override public String toOperationId(String operationId) { - operationId = camelize(sanitizeName(operationId), true); + operationId = camelize(sanitizeName(operationId), LOWERCASE_FIRST_LETTER); // Throw exception if method name is empty. // This should not happen but keep the check just in case @@ -476,15 +464,15 @@ public String toOperationId(String operationId) { // method name cannot use reserved keyword, e.g. return if (isReservedWord(operationId)) { - String newOperationId = camelize(("call_" + operationId), true); + String newOperationId = camelize(("call_" + operationId), LOWERCASE_FIRST_LETTER); LOGGER.warn("{} (reserved word) cannot be used as method name. Renamed to {}", operationId, newOperationId); return newOperationId; } // operationId starts with a number if (operationId.matches("^\\d.*")) { - LOGGER.warn("{} (starting with a number) cannot be used as method name. Renamed to {}", operationId, camelize(sanitizeName("call_" + operationId), true)); - operationId = camelize(sanitizeName("call_" + operationId), true); + LOGGER.warn("{} (starting with a number) cannot be used as method name. Renamed to {}", operationId, camelize(sanitizeName("call_" + operationId), LOWERCASE_FIRST_LETTER)); + operationId = camelize(sanitizeName("call_" + operationId), LOWERCASE_FIRST_LETTER); } @@ -503,7 +491,7 @@ public String toVarName(String name) { // camelize the variable name // pet_id => petId - name = camelize(name, true); + name = camelize(name, LOWERCASE_FIRST_LETTER); // for reserved words surround with `` or append _ if (isReservedWord(name)) { @@ -533,7 +521,7 @@ public String toParamName(String name) { // camelize(lower) the variable name // pet_id => petId - name = camelize(name, true); + name = camelize(name, LOWERCASE_FIRST_LETTER); // for reserved words surround with `` if (isReservedWord(name)) { @@ -601,18 +589,18 @@ public String toEnumVarName(String name, String datatype) { String startingNumbers = startWithNumberMatcher.group(0); String nameWithoutStartingNumbers = name.substring(startingNumbers.length()); - return "_" + startingNumbers + camelize(nameWithoutStartingNumbers, true); + return "_" + startingNumbers + camelize(nameWithoutStartingNumbers, LOWERCASE_FIRST_LETTER); } // for symbol, e.g. $, # if (getSymbolName(name) != null) { - return camelize(WordUtils.capitalizeFully(getSymbolName(name).toUpperCase(Locale.ROOT)), true); + return camelize(WordUtils.capitalizeFully(getSymbolName(name).toUpperCase(Locale.ROOT)), LOWERCASE_FIRST_LETTER); } // Camelize only when we have a structure defined below Boolean camelized = false; if (name.matches("[A-Z][a-z0-9]+[a-zA-Z0-9]*")) { - name = camelize(name, true); + name = camelize(name, LOWERCASE_FIRST_LETTER); camelized = true; } @@ -641,7 +629,7 @@ public String toEnumVarName(String name, String datatype) { char[] separators = {'-', '_', ' ', ':', '(', ')'}; return camelize(WordUtils.capitalizeFully(StringUtils.lowerCase(name), separators) .replaceAll("[-_ :\\(\\)]", ""), - true); + LOWERCASE_FIRST_LETTER); } @Override @@ -666,8 +654,8 @@ public String toEnumName(CodegenProperty property) { } @Override - public Map postProcessModels(Map objs) { - Map postProcessedModelsEnum = postProcessModelsEnum(objs); + public ModelsMap postProcessModels(ModelsMap objs) { + ModelsMap postProcessedModelsEnum = postProcessModelsEnum(objs); List models = (List) postProcessedModelsEnum.get("models"); for (Object _mo : models) { Map mo = (Map) _mo; @@ -734,7 +722,7 @@ public void postProcessFile(File file, String fileType) { } @Override - public Map postProcessOperationsWithModels(Map objs, List allModels) { + public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List allModels) { Map objectMap = (Map) objs.get("operations"); HashMap modelMaps = new HashMap(); @@ -812,7 +800,7 @@ public void postProcess() { System.out.println("################################################################################"); System.out.println("# Thanks for using OpenAPI Generator. #"); System.out.println("# swift alternative generator is contributed by @dydus0x14 and @ptiz. #"); - System.out.println("# swift alternative generator v0.21.0 #"); + System.out.println("# swift alternative generator v0.22.0 #"); System.out.println("################################################################################"); } diff --git a/modules/openapi-generator/src/main/resources/swift-alt/toString.mustache b/modules/openapi-generator/src/main/resources/swift-alt/toString.mustache index 77f957f4d761..8e9d14247d1f 100644 --- a/modules/openapi-generator/src/main/resources/swift-alt/toString.mustache +++ b/modules/openapi-generator/src/main/resources/swift-alt/toString.mustache @@ -1 +1 @@ -{{#isDateTime}}OpenISO8601DateFormatter.shared.string(from: {{paramName}}){{/isDateTime}}{{#vendorExtensions.x-swift-use-encoder}}String(data: try self.encoder.encode({{paramName}}), encoding: .utf8) ?? ""{{/vendorExtensions.x-swift-use-encoder}}{{^vendorExtensions.x-swift-use-encoder}}{{#isArray}}{{paramName}}{{#vendorExtensions.x-swift-is-base-type-udid}}.map { $0.uuidString }{{/vendorExtensions.x-swift-is-base-type-udid}}{{#vendorExtensions.x-swift-is-base-type-enum}}.map { $0.rawValue }{{/vendorExtensions.x-swift-is-base-type-enum}}.joined(separator: ", "){{/isArray}}{{^isArray}}{{#vendorExtensions.x-swift-is-enum-type}}{{paramName}}.rawValue{{/vendorExtensions.x-swift-is-enum-type}}{{^isEnum}}{{#isString}}{{#isUuid}}{{paramName}}.uuidString{{/isUuid}}{{^isUuid}}{{paramName}}{{/isUuid}}{{/isString}}{{#isInteger}}"\({{paramName}})"{{/isInteger}}{{#isDouble}}"\({{paramName}})"{{/isDouble}}{{#isFloat}}"\({{paramName}})"{{/isFloat}}{{#isNumber}}"\({{paramName}})"{{/isNumber}}{{#isBoolean}}{{paramName}} ? "true" : "false"{{/isBoolean}}{{/isEnum}}{{/isArray}}{{/vendorExtensions.x-swift-use-encoder}} \ No newline at end of file +{{#isDateTime}}OpenISO8601DateFormatter.shared.string(from: {{paramName}}){{/isDateTime}}{{#vendorExtensions.x-swift-use-encoder}}String(data: try self.encoder.encode({{paramName}}), encoding: .utf8) ?? ""{{/vendorExtensions.x-swift-use-encoder}}{{^vendorExtensions.x-swift-use-encoder}}{{#isArray}}{{paramName}}{{#vendorExtensions.x-swift-is-base-type-udid}}.map { $0.uuidString }{{/vendorExtensions.x-swift-is-base-type-udid}}{{#vendorExtensions.x-swift-is-base-type-enum}}.map { $0.rawValue }{{/vendorExtensions.x-swift-is-base-type-enum}}.joined(separator: ","){{/isArray}}{{^isArray}}{{#vendorExtensions.x-swift-is-enum-type}}{{paramName}}.rawValue{{/vendorExtensions.x-swift-is-enum-type}}{{^isEnum}}{{#isString}}{{#isUuid}}{{paramName}}.uuidString{{/isUuid}}{{^isUuid}}{{paramName}}{{/isUuid}}{{/isString}}{{#isInteger}}"\({{paramName}})"{{/isInteger}}{{#isDouble}}"\({{paramName}})"{{/isDouble}}{{#isFloat}}"\({{paramName}})"{{/isFloat}}{{#isNumber}}"\({{paramName}})"{{/isNumber}}{{#isBoolean}}{{paramName}} ? "true" : "false"{{/isBoolean}}{{/isEnum}}{{/isArray}}{{/vendorExtensions.x-swift-use-encoder}} \ No newline at end of file diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/swift-alt/SwiftAltClientCodegenModelTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/swift-alt/SwiftAltClientCodegenModelTest.java deleted file mode 100644 index 070300882844..000000000000 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/swift-alt/SwiftAltClientCodegenModelTest.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.openapitools.codegen.swift.alt; - -import org.openapitools.codegen.*; -import org.openapitools.codegen.languages.SwiftAltClientCodegen; -import io.swagger.models.*; -import io.swagger.models.properties.*; - -import org.testng.Assert; -import org.testng.annotations.Test; - -@SuppressWarnings("static-method") -public class SwiftAltClientCodegenModelTest { - - @Test(description = "convert a simple java model") - public void simpleModelTest() { - final Model model = new ModelImpl() - .description("a sample model") - .property("id", new LongProperty()) - .property("name", new StringProperty()) - .required("id") - .required("name"); - final DefaultCodegen codegen = new SwiftAltClientCodegen(); - - // TODO: Complete this test. - Assert.fail("Not implemented."); - } - -} - diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/swift-alt/SwiftAltClientCodegenOptionsTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/swift-alt/SwiftAltClientCodegenOptionsTest.java deleted file mode 100644 index 56dd84c038be..000000000000 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/swift-alt/SwiftAltClientCodegenOptionsTest.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.openapitools.codegen.swift.alt; - -import org.openapitools.codegen.AbstractOptionsTest; -import org.openapitools.codegen.CodegenConfig; -import org.openapitools.codegen.languages.SwiftAltClientCodegen; -import org.openapitools.codegen.options.SwiftAltClientCodegenOptionsProvider; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; - -public class SwiftAltClientCodegenOptionsTest extends AbstractOptionsTest { - private SwiftAltClientCodegen codegen = mock(SwiftAltClientCodegen.class, mockSettings); - - public SwiftAltClientCodegenOptionsTest() { - super(new SwiftAltClientCodegenOptionsProvider()); - } - - @Override - protected CodegenConfig getCodegenConfig() { - return codegen; - } - - @SuppressWarnings("unused") - @Override - protected void verifyOptions() { - // TODO: Complete options using Mockito - // verify(codegen).someMethod(arguments) - } -} - diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/swift-alt/SwiftAltClientCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/swift-alt/SwiftAltClientCodegenTest.java deleted file mode 100644 index b37e4a7505ea..000000000000 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/swift-alt/SwiftAltClientCodegenTest.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.openapitools.codegen.swift.alt; - -import org.openapitools.codegen.*; -import org.openapitools.codegen.languages.SwiftAltClientCodegen; -import io.swagger.models.*; -import io.swagger.parser.SwaggerParser; -import org.testng.Assert; -import org.testng.annotations.Test; - -public class SwiftAltClientCodegenTest { - - SwiftAltClientCodegen codegen = new SwiftAltClientCodegen(); - - @Test - public void shouldSucceed() throws Exception { - // TODO: Complete this test. - Assert.fail("Not implemented."); - } -} From a519966a173794ee3f827a0dc13cef5229facbff Mon Sep 17 00:00:00 2001 From: Anton Davydov Date: Thu, 8 Jun 2023 18:33:49 +0300 Subject: [PATCH 28/33] swift-combine v0.23.0 --- ...ew.yaml => swift-combine-petstore-new.yaml} | 0 ...gen.java => SwiftCombineClientCodegen.java} | 18 +++++++++--------- .../org.openapitools.codegen.CodegenConfig | 2 +- .../AnyDecodable.mustache | 0 .../OpenAPITransport.mustache | 0 .../OpenAPITransportPackage.mustache | 0 .../OpenISO8601DateFormatter.mustache | 0 .../Package.mustache | 0 .../README.mustache | 0 .../{swift-alt => swift-combine}/api.mustache | 0 .../model.mustache | 0 .../modelArray.mustache | 0 .../modelEnum.mustache | 0 .../modelInlineEnumDeclaration.mustache | 0 .../modelObject.mustache | 0 .../modelObjectCustom.mustache | 0 .../modelOneOf.mustache | 0 .../toData.mustache | 0 .../toMultipartFormDataAppend.mustache | 0 .../toString.mustache | 0 ...ftCombineClientCodegenOptionsProvider.java} | 9 ++++----- 21 files changed, 14 insertions(+), 15 deletions(-) rename bin/configs/{swift-alt-petstore-new.yaml => swift-combine-petstore-new.yaml} (100%) rename modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/{SwiftAltClientCodegen.java => SwiftCombineClientCodegen.java} (98%) rename modules/openapi-generator/src/main/resources/{swift-alt => swift-combine}/AnyDecodable.mustache (100%) rename modules/openapi-generator/src/main/resources/{swift-alt => swift-combine}/OpenAPITransport.mustache (100%) rename modules/openapi-generator/src/main/resources/{swift-alt => swift-combine}/OpenAPITransportPackage.mustache (100%) rename modules/openapi-generator/src/main/resources/{swift-alt => swift-combine}/OpenISO8601DateFormatter.mustache (100%) rename modules/openapi-generator/src/main/resources/{swift-alt => swift-combine}/Package.mustache (100%) rename modules/openapi-generator/src/main/resources/{swift-alt => swift-combine}/README.mustache (100%) rename modules/openapi-generator/src/main/resources/{swift-alt => swift-combine}/api.mustache (100%) rename modules/openapi-generator/src/main/resources/{swift-alt => swift-combine}/model.mustache (100%) rename modules/openapi-generator/src/main/resources/{swift-alt => swift-combine}/modelArray.mustache (100%) rename modules/openapi-generator/src/main/resources/{swift-alt => swift-combine}/modelEnum.mustache (100%) rename modules/openapi-generator/src/main/resources/{swift-alt => swift-combine}/modelInlineEnumDeclaration.mustache (100%) rename modules/openapi-generator/src/main/resources/{swift-alt => swift-combine}/modelObject.mustache (100%) rename modules/openapi-generator/src/main/resources/{swift-alt => swift-combine}/modelObjectCustom.mustache (100%) rename modules/openapi-generator/src/main/resources/{swift-alt => swift-combine}/modelOneOf.mustache (100%) rename modules/openapi-generator/src/main/resources/{swift-alt => swift-combine}/toData.mustache (100%) rename modules/openapi-generator/src/main/resources/{swift-alt => swift-combine}/toMultipartFormDataAppend.mustache (100%) rename modules/openapi-generator/src/main/resources/{swift-alt => swift-combine}/toString.mustache (100%) rename modules/openapi-generator/src/test/java/org/openapitools/codegen/options/{SwiftAltClientCodegenOptionsProvider.java => SwiftCombineClientCodegenOptionsProvider.java} (63%) diff --git a/bin/configs/swift-alt-petstore-new.yaml b/bin/configs/swift-combine-petstore-new.yaml similarity index 100% rename from bin/configs/swift-alt-petstore-new.yaml rename to bin/configs/swift-combine-petstore-new.yaml diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftCombineClientCodegen.java similarity index 98% rename from modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java rename to modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftCombineClientCodegen.java index d8fc1072fca7..3c25785c07d9 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftAltClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftCombineClientCodegen.java @@ -50,8 +50,8 @@ import static org.openapitools.codegen.utils.CamelizeOption.LOWERCASE_FIRST_LETTER; import static org.openapitools.codegen.utils.StringUtils.camelize; -public class SwiftAltClientCodegen extends DefaultCodegen implements CodegenConfig { - private final Logger LOGGER = LoggerFactory.getLogger(SwiftAltClientCodegen.class); +public class SwiftCombineClientCodegen extends DefaultCodegen implements CodegenConfig { + private final Logger LOGGER = LoggerFactory.getLogger(SwiftCombineClientCodegen.class); public static final String PROJECT_NAME = "projectName"; public static final String MAP_FILE_BINARY_TO_DATA = "mapFileBinaryToData"; @@ -65,9 +65,9 @@ public class SwiftAltClientCodegen extends DefaultCodegen implements CodegenConf protected boolean anyDecoderWasAdded = false; /** - * Constructor for the swift alt language codegen module. + * Constructor for the swift language codegen module. */ - public SwiftAltClientCodegen() { + public SwiftCombineClientCodegen() { super(); this.supportsMultipleInheritance = true; this.useOneOfInterfaces = true; @@ -80,7 +80,7 @@ public SwiftAltClientCodegen() { outputFolder = "generated-code" + File.separator + "swift"; modelTemplateFiles.put("model.mustache", ".swift"); apiTemplateFiles.put("api.mustache", ".swift"); - embeddedTemplateDir = templateDir = "swift-alt"; + embeddedTemplateDir = templateDir = "swift-combine"; apiPackage = File.separator + "APIs"; modelPackage = File.separator + "Models"; @@ -210,12 +210,12 @@ public CodegenType getTag() { @Override public String getName() { - return "swift-alt"; + return "swift-combine"; } @Override public String getHelp() { - return "Generates a Swift alternative client library."; + return "Generates a Swift Combine client library."; } @Override @@ -799,8 +799,8 @@ protected void addFormVendorExtensions(CodegenParameter cp, CodegenOperation ope public void postProcess() { System.out.println("################################################################################"); System.out.println("# Thanks for using OpenAPI Generator. #"); - System.out.println("# swift alternative generator is contributed by @dydus0x14 and @ptiz. #"); - System.out.println("# swift alternative generator v0.22.0 #"); + System.out.println("# swift combine generator is contributed by @dydus0x14 and @ptiz. #"); + System.out.println("# swift combine generator v0.23.0 #"); System.out.println("################################################################################"); } diff --git a/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig b/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig index 13f3937dd412..b435154f332a 100644 --- a/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig +++ b/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig @@ -138,4 +138,4 @@ org.openapitools.codegen.languages.TypeScriptReduxQueryClientCodegen org.openapitools.codegen.languages.TypeScriptRxjsClientCodegen org.openapitools.codegen.languages.WsdlSchemaCodegen org.openapitools.codegen.languages.XojoClientCodegen -org.openapitools.codegen.languages.SwiftAltClientCodegen +org.openapitools.codegen.languages.SwiftCombineClientCodegen diff --git a/modules/openapi-generator/src/main/resources/swift-alt/AnyDecodable.mustache b/modules/openapi-generator/src/main/resources/swift-combine/AnyDecodable.mustache similarity index 100% rename from modules/openapi-generator/src/main/resources/swift-alt/AnyDecodable.mustache rename to modules/openapi-generator/src/main/resources/swift-combine/AnyDecodable.mustache diff --git a/modules/openapi-generator/src/main/resources/swift-alt/OpenAPITransport.mustache b/modules/openapi-generator/src/main/resources/swift-combine/OpenAPITransport.mustache similarity index 100% rename from modules/openapi-generator/src/main/resources/swift-alt/OpenAPITransport.mustache rename to modules/openapi-generator/src/main/resources/swift-combine/OpenAPITransport.mustache diff --git a/modules/openapi-generator/src/main/resources/swift-alt/OpenAPITransportPackage.mustache b/modules/openapi-generator/src/main/resources/swift-combine/OpenAPITransportPackage.mustache similarity index 100% rename from modules/openapi-generator/src/main/resources/swift-alt/OpenAPITransportPackage.mustache rename to modules/openapi-generator/src/main/resources/swift-combine/OpenAPITransportPackage.mustache diff --git a/modules/openapi-generator/src/main/resources/swift-alt/OpenISO8601DateFormatter.mustache b/modules/openapi-generator/src/main/resources/swift-combine/OpenISO8601DateFormatter.mustache similarity index 100% rename from modules/openapi-generator/src/main/resources/swift-alt/OpenISO8601DateFormatter.mustache rename to modules/openapi-generator/src/main/resources/swift-combine/OpenISO8601DateFormatter.mustache diff --git a/modules/openapi-generator/src/main/resources/swift-alt/Package.mustache b/modules/openapi-generator/src/main/resources/swift-combine/Package.mustache similarity index 100% rename from modules/openapi-generator/src/main/resources/swift-alt/Package.mustache rename to modules/openapi-generator/src/main/resources/swift-combine/Package.mustache diff --git a/modules/openapi-generator/src/main/resources/swift-alt/README.mustache b/modules/openapi-generator/src/main/resources/swift-combine/README.mustache similarity index 100% rename from modules/openapi-generator/src/main/resources/swift-alt/README.mustache rename to modules/openapi-generator/src/main/resources/swift-combine/README.mustache diff --git a/modules/openapi-generator/src/main/resources/swift-alt/api.mustache b/modules/openapi-generator/src/main/resources/swift-combine/api.mustache similarity index 100% rename from modules/openapi-generator/src/main/resources/swift-alt/api.mustache rename to modules/openapi-generator/src/main/resources/swift-combine/api.mustache diff --git a/modules/openapi-generator/src/main/resources/swift-alt/model.mustache b/modules/openapi-generator/src/main/resources/swift-combine/model.mustache similarity index 100% rename from modules/openapi-generator/src/main/resources/swift-alt/model.mustache rename to modules/openapi-generator/src/main/resources/swift-combine/model.mustache diff --git a/modules/openapi-generator/src/main/resources/swift-alt/modelArray.mustache b/modules/openapi-generator/src/main/resources/swift-combine/modelArray.mustache similarity index 100% rename from modules/openapi-generator/src/main/resources/swift-alt/modelArray.mustache rename to modules/openapi-generator/src/main/resources/swift-combine/modelArray.mustache diff --git a/modules/openapi-generator/src/main/resources/swift-alt/modelEnum.mustache b/modules/openapi-generator/src/main/resources/swift-combine/modelEnum.mustache similarity index 100% rename from modules/openapi-generator/src/main/resources/swift-alt/modelEnum.mustache rename to modules/openapi-generator/src/main/resources/swift-combine/modelEnum.mustache diff --git a/modules/openapi-generator/src/main/resources/swift-alt/modelInlineEnumDeclaration.mustache b/modules/openapi-generator/src/main/resources/swift-combine/modelInlineEnumDeclaration.mustache similarity index 100% rename from modules/openapi-generator/src/main/resources/swift-alt/modelInlineEnumDeclaration.mustache rename to modules/openapi-generator/src/main/resources/swift-combine/modelInlineEnumDeclaration.mustache diff --git a/modules/openapi-generator/src/main/resources/swift-alt/modelObject.mustache b/modules/openapi-generator/src/main/resources/swift-combine/modelObject.mustache similarity index 100% rename from modules/openapi-generator/src/main/resources/swift-alt/modelObject.mustache rename to modules/openapi-generator/src/main/resources/swift-combine/modelObject.mustache diff --git a/modules/openapi-generator/src/main/resources/swift-alt/modelObjectCustom.mustache b/modules/openapi-generator/src/main/resources/swift-combine/modelObjectCustom.mustache similarity index 100% rename from modules/openapi-generator/src/main/resources/swift-alt/modelObjectCustom.mustache rename to modules/openapi-generator/src/main/resources/swift-combine/modelObjectCustom.mustache diff --git a/modules/openapi-generator/src/main/resources/swift-alt/modelOneOf.mustache b/modules/openapi-generator/src/main/resources/swift-combine/modelOneOf.mustache similarity index 100% rename from modules/openapi-generator/src/main/resources/swift-alt/modelOneOf.mustache rename to modules/openapi-generator/src/main/resources/swift-combine/modelOneOf.mustache diff --git a/modules/openapi-generator/src/main/resources/swift-alt/toData.mustache b/modules/openapi-generator/src/main/resources/swift-combine/toData.mustache similarity index 100% rename from modules/openapi-generator/src/main/resources/swift-alt/toData.mustache rename to modules/openapi-generator/src/main/resources/swift-combine/toData.mustache diff --git a/modules/openapi-generator/src/main/resources/swift-alt/toMultipartFormDataAppend.mustache b/modules/openapi-generator/src/main/resources/swift-combine/toMultipartFormDataAppend.mustache similarity index 100% rename from modules/openapi-generator/src/main/resources/swift-alt/toMultipartFormDataAppend.mustache rename to modules/openapi-generator/src/main/resources/swift-combine/toMultipartFormDataAppend.mustache diff --git a/modules/openapi-generator/src/main/resources/swift-alt/toString.mustache b/modules/openapi-generator/src/main/resources/swift-combine/toString.mustache similarity index 100% rename from modules/openapi-generator/src/main/resources/swift-alt/toString.mustache rename to modules/openapi-generator/src/main/resources/swift-combine/toString.mustache diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/SwiftAltClientCodegenOptionsProvider.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/SwiftCombineClientCodegenOptionsProvider.java similarity index 63% rename from modules/openapi-generator/src/test/java/org/openapitools/codegen/options/SwiftAltClientCodegenOptionsProvider.java rename to modules/openapi-generator/src/test/java/org/openapitools/codegen/options/SwiftCombineClientCodegenOptionsProvider.java index 058c59c379cb..e5bca028aa3a 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/SwiftAltClientCodegenOptionsProvider.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/SwiftCombineClientCodegenOptionsProvider.java @@ -1,25 +1,24 @@ package org.openapitools.codegen.options; -import org.openapitools.codegen.CodegenConstants; -import org.openapitools.codegen.languages.SwiftAltClientCodegen; +import org.openapitools.codegen.languages.SwiftCombineClientCodegen; import com.google.common.collect.ImmutableMap; import java.util.Map; -public class SwiftAltClientCodegenOptionsProvider implements OptionsProvider { +public class SwiftCombineClientCodegenOptionsProvider implements OptionsProvider { public static final String PROJECT_NAME_VALUE = "OpenAPI"; @Override public String getLanguage() { - return "swift-alt"; + return "swift-combine"; } @Override public Map createOptions() { ImmutableMap.Builder builder = new ImmutableMap.Builder(); return builder - .put(SwiftAltClientCodegen.PROJECT_NAME, PROJECT_NAME_VALUE) + .put(SwiftCombineClientCodegen.PROJECT_NAME, PROJECT_NAME_VALUE) .build(); } From 358694c2a26e23bd820fb5cab928e37f0b715c6c Mon Sep 17 00:00:00 2001 From: Anton Davydov Date: Thu, 8 Jun 2023 19:30:05 +0300 Subject: [PATCH 29/33] swift-combine PR rules adoption --- bin/configs/swift-combine-petstore-new.yaml | 6 +- docs/generators.md | 1 + docs/generators/swift-combine.md | 328 +++++++++++ .../client/.openapi-generator/VERSION | 1 - .../PetstoreOpenAPI/Sources/APIs/PetAPI.swift | 363 ------------- .../Sources/APIs/StoreAPI.swift | 182 ------- .../Sources/APIs/UserAPI.swift | 359 ------------ .../Sources/Models/ApiResponse.swift | 37 -- .../Sources/Models/Category.swift | 33 -- .../Sources/Models/Order.swift | 55 -- .../PetstoreOpenAPI/Sources/Models/Pet.swift | 55 -- .../PetstoreOpenAPI/Sources/Models/Tag.swift | 33 -- .../PetstoreOpenAPI/Sources/Models/User.swift | 58 -- .../{swift-alt => swift-combine}/.gitignore | 0 .../client/.openapi-generator-ignore | 0 .../client/.openapi-generator/FILES | 0 .../client/.openapi-generator/VERSION | 1 + .../client/OpenAPITransport/Package.swift | 0 .../Sources/OpenAPITransport.swift | 144 ++--- .../client/PetstoreOpenAPI/Package.swift | 0 .../PetstoreOpenAPI/Sources/APIs/PetAPI.swift | 512 ++++++++++++++++++ .../Sources/APIs/StoreAPI.swift | 228 ++++++++ .../Sources/APIs/UserAPI.swift | 409 ++++++++++++++ .../Sources/Models/ApiResponse.swift | 21 + .../Sources/Models/Category.swift | 19 + .../Sources/Models/Order.swift | 33 ++ .../PetstoreOpenAPI/Sources/Models/Pet.swift | 33 ++ .../PetstoreOpenAPI/Sources/Models/Tag.swift | 19 + .../PetstoreOpenAPI/Sources/Models/User.swift | 32 ++ .../Private/OpenISO8601DateFormatter.swift | 2 + .../tests/Package.swift | 0 .../Sources/TestClientTests/PetAPITests.swift | 0 .../lib/src/model/dog.dart | 12 + 33 files changed, 1727 insertions(+), 1249 deletions(-) create mode 100644 docs/generators/swift-combine.md delete mode 100644 samples/client/petstore/swift-alt/client/.openapi-generator/VERSION delete mode 100644 samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/APIs/PetAPI.swift delete mode 100644 samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/APIs/StoreAPI.swift delete mode 100644 samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/APIs/UserAPI.swift delete mode 100644 samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/Models/ApiResponse.swift delete mode 100644 samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/Models/Category.swift delete mode 100644 samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/Models/Order.swift delete mode 100644 samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/Models/Pet.swift delete mode 100644 samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/Models/Tag.swift delete mode 100644 samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/Models/User.swift rename samples/client/petstore/{swift-alt => swift-combine}/.gitignore (100%) rename samples/client/petstore/{swift-alt => swift-combine}/client/.openapi-generator-ignore (100%) rename samples/client/petstore/{swift-alt => swift-combine}/client/.openapi-generator/FILES (100%) create mode 100644 samples/client/petstore/swift-combine/client/.openapi-generator/VERSION rename samples/client/petstore/{swift-alt => swift-combine}/client/OpenAPITransport/Package.swift (100%) rename samples/client/petstore/{swift-alt => swift-combine}/client/OpenAPITransport/Sources/OpenAPITransport.swift (65%) rename samples/client/petstore/{swift-alt => swift-combine}/client/PetstoreOpenAPI/Package.swift (100%) create mode 100644 samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/APIs/PetAPI.swift create mode 100644 samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/APIs/StoreAPI.swift create mode 100644 samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/APIs/UserAPI.swift create mode 100644 samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/Models/ApiResponse.swift create mode 100644 samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/Models/Category.swift create mode 100644 samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/Models/Order.swift create mode 100644 samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/Models/Pet.swift create mode 100644 samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/Models/Tag.swift create mode 100644 samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/Models/User.swift rename samples/client/petstore/{swift-alt => swift-combine}/client/PetstoreOpenAPI/Sources/Private/OpenISO8601DateFormatter.swift (95%) rename samples/client/petstore/{swift-alt => swift-combine}/tests/Package.swift (100%) rename samples/client/petstore/{swift-alt => swift-combine}/tests/Sources/TestClientTests/PetAPITests.swift (100%) diff --git a/bin/configs/swift-combine-petstore-new.yaml b/bin/configs/swift-combine-petstore-new.yaml index d8d88889e1a7..5349e056a5b8 100644 --- a/bin/configs/swift-combine-petstore-new.yaml +++ b/bin/configs/swift-combine-petstore-new.yaml @@ -1,7 +1,7 @@ -generatorName: swift-alt -outputDir: samples/client/petstore/swift-alt/client +generatorName: swift-combine +outputDir: samples/client/petstore/swift-combine/client inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml -templateDir: modules/openapi-generator/src/main/resources/swift-alt +templateDir: modules/openapi-generator/src/main/resources/swift-combine additionalProperties: hideGenerationTimestamp: "true" projectName: "PetstoreOpenAPI" diff --git a/docs/generators.md b/docs/generators.md index be5dbba7348f..28bed17d3d06 100644 --- a/docs/generators.md +++ b/docs/generators.md @@ -59,6 +59,7 @@ The following generators are available: * [scala-gatling](generators/scala-gatling.md) * [scala-sttp (beta)](generators/scala-sttp.md) * [scalaz](generators/scalaz.md) +* [swift-combine](generators/swift-combine.md) * [swift5](generators/swift5.md) * [typescript (experimental)](generators/typescript.md) * [typescript-angular](generators/typescript-angular.md) diff --git a/docs/generators/swift-combine.md b/docs/generators/swift-combine.md new file mode 100644 index 000000000000..4b2a58f7ca75 --- /dev/null +++ b/docs/generators/swift-combine.md @@ -0,0 +1,328 @@ +--- +title: Documentation for the swift-combine Generator +--- + +## METADATA + +| Property | Value | Notes | +| -------- | ----- | ----- | +| generator name | swift-combine | pass this to the generate command after -g | +| generator stability | STABLE | | +| generator type | CLIENT | | +| generator language | Swift | | +| generator default templating engine | mustache | | +| helpTxt | Generates a Swift Combine client library. | | + +## CONFIG OPTIONS +These options may be applied as additional-properties (cli) or configOptions (plugins). Refer to [configuration docs](https://openapi-generator.tech/docs/configuration) for more details. + +| Option | Description | Values | Default | +| ------ | ----------- | ------ | ------- | +|allowUnicodeIdentifiers|boolean, toggles whether unicode identifiers are allowed in names or not, default is false| |false| +|apiNamePrefix|Prefix that will be appended to all API names ('tags'). Default: empty string. e.g. Pet => Pet.| |null| +|disallowAdditionalPropertiesIfNotPresent|If false, the 'additionalProperties' implementation (set to true by default) is compliant with the OAS and JSON schema specifications. If true (default), keep the old (incorrect) behaviour that 'additionalProperties' is set to false by default.|
**false**
The 'additionalProperties' implementation is compliant with the OAS and JSON schema specifications.
**true**
Keep the old (incorrect) behaviour that 'additionalProperties' is set to false by default.
|true| +|ensureUniqueParams|Whether to ensure parameter names are unique in an operation (rename parameters that are not).| |true| +|enumUnknownDefaultCase|If the server adds new enum cases, that are unknown by an old spec/client, the client will fail to parse the network response.With this option enabled, each enum will have a new case, 'unknown_default_open_api', so that when the server sends an enum case that is not known by the client/spec, they can safely fallback to this case.|
**false**
No changes to the enum's are made, this is the default option.
**true**
With this option enabled, each enum will have a new case, 'unknown_default_open_api', so that when the enum case sent by the server is not known by the client/spec, can safely be decoded to this case.
|false| +|legacyDiscriminatorBehavior|Set to false for generators with better support for discriminators. (Python, Java, Go, PowerShell, C# have this enabled by default).|
**true**
The mapping in the discriminator includes descendent schemas that allOf inherit from self and the discriminator mapping schemas in the OAS document.
**false**
The mapping in the discriminator includes any descendent schemas that allOf inherit from self, any oneOf schemas, any anyOf schemas, any x-discriminator-values, and the discriminator mapping schemas in the OAS document AND Codegen validates that oneOf and anyOf schemas contain the required discriminator and throws an error if the discriminator is missing.
|true| +|mapFileBinaryToData|Map File and Binary to Data (default: true)| |true| +|prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| +|projectName|Project name in Xcode| |null| +|sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| +|sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| + +## IMPORT MAPPING + +| Type/Alias | Imports | +| ---------- | ------- | + + +## INSTANTIATION TYPES + +| Type/Alias | Instantiated By | +| ---------- | --------------- | +|array|Array| +|list|Array| + + +## LANGUAGE PRIMITIVES + +
    +
  • Any
  • +
  • AnyObject
  • +
  • Bool
  • +
  • Character
  • +
  • Data
  • +
  • Date
  • +
  • Decimal
  • +
  • Double
  • +
  • Float
  • +
  • Int
  • +
  • Int32
  • +
  • Int64
  • +
  • String
  • +
  • URL
  • +
  • UUID
  • +
  • Void
  • +
  • [String: Any]
  • +
+ +## RESERVED WORDS + +
    +
  • #available
  • +
  • #colorLiteral
  • +
  • #column
  • +
  • #else
  • +
  • #elseif
  • +
  • #endif
  • +
  • #file
  • +
  • #fileLiteral
  • +
  • #function
  • +
  • #if
  • +
  • #imageLiteral
  • +
  • #line
  • +
  • #selector
  • +
  • #sourceLocation
  • +
  • Any
  • +
  • AnyObject
  • +
  • Array
  • +
  • Bool
  • +
  • COLUMN
  • +
  • Character
  • +
  • Class
  • +
  • ClosedRange
  • +
  • Codable
  • +
  • CountableClosedRange
  • +
  • CountableRange
  • +
  • Data
  • +
  • Decodable
  • +
  • Dictionary
  • +
  • Double
  • +
  • Encodable
  • +
  • Error
  • +
  • FILE
  • +
  • FUNCTION
  • +
  • Float
  • +
  • Float32
  • +
  • Float64
  • +
  • Float80
  • +
  • Int
  • +
  • Int16
  • +
  • Int32
  • +
  • Int64
  • +
  • Int8
  • +
  • LINE
  • +
  • OptionSet
  • +
  • Optional
  • +
  • Protocol
  • +
  • Range
  • +
  • Result
  • +
  • Self
  • +
  • Set
  • +
  • StaticString
  • +
  • String
  • +
  • Type
  • +
  • UInt
  • +
  • UInt16
  • +
  • UInt32
  • +
  • UInt64
  • +
  • UInt8
  • +
  • URL
  • +
  • Unicode
  • +
  • Void
  • +
  • _
  • +
  • as
  • +
  • associatedtype
  • +
  • associativity
  • +
  • break
  • +
  • case
  • +
  • catch
  • +
  • class
  • +
  • continue
  • +
  • convenience
  • +
  • default
  • +
  • defer
  • +
  • deinit
  • +
  • didSet
  • +
  • do
  • +
  • dynamic
  • +
  • dynamicType
  • +
  • else
  • +
  • enum
  • +
  • extension
  • +
  • fallthrough
  • +
  • false
  • +
  • fileprivate
  • +
  • final
  • +
  • for
  • +
  • func
  • +
  • get
  • +
  • guard
  • +
  • if
  • +
  • import
  • +
  • in
  • +
  • indirect
  • +
  • infix
  • +
  • init
  • +
  • inout
  • +
  • internal
  • +
  • is
  • +
  • lazy
  • +
  • left
  • +
  • let
  • +
  • mutating
  • +
  • nil
  • +
  • none
  • +
  • nonmutating
  • +
  • open
  • +
  • operator
  • +
  • optional
  • +
  • override
  • +
  • postfix
  • +
  • precedence
  • +
  • prefix
  • +
  • private
  • +
  • protocol
  • +
  • public
  • +
  • repeat
  • +
  • required
  • +
  • rethrows
  • +
  • return
  • +
  • right
  • +
  • self
  • +
  • set
  • +
  • static
  • +
  • struct
  • +
  • subscript
  • +
  • super
  • +
  • switch
  • +
  • throw
  • +
  • throws
  • +
  • true
  • +
  • try
  • +
  • typealias
  • +
  • unowned
  • +
  • var
  • +
  • weak
  • +
  • where
  • +
  • while
  • +
  • willSet
  • +
+ +## FEATURE SET + + +### Client Modification Feature +| Name | Supported | Defined By | +| ---- | --------- | ---------- | +|BasePath|✗|ToolingExtension +|Authorizations|✗|ToolingExtension +|UserAgent|✗|ToolingExtension +|MockServer|✗|ToolingExtension + +### Data Type Feature +| Name | Supported | Defined By | +| ---- | --------- | ---------- | +|Custom|✗|OAS2,OAS3 +|Int32|✓|OAS2,OAS3 +|Int64|✓|OAS2,OAS3 +|Float|✓|OAS2,OAS3 +|Double|✓|OAS2,OAS3 +|Decimal|✓|ToolingExtension +|String|✓|OAS2,OAS3 +|Byte|✓|OAS2,OAS3 +|Binary|✓|OAS2,OAS3 +|Boolean|✓|OAS2,OAS3 +|Date|✓|OAS2,OAS3 +|DateTime|✓|OAS2,OAS3 +|Password|✓|OAS2,OAS3 +|File|✓|OAS2 +|Uuid|✗| +|Array|✓|OAS2,OAS3 +|Null|✗|OAS3 +|AnyType|✗|OAS2,OAS3 +|Object|✓|OAS2,OAS3 +|Maps|✓|ToolingExtension +|CollectionFormat|✓|OAS2 +|CollectionFormatMulti|✓|OAS2 +|Enum|✓|OAS2,OAS3 +|ArrayOfEnum|✓|ToolingExtension +|ArrayOfModel|✓|ToolingExtension +|ArrayOfCollectionOfPrimitives|✓|ToolingExtension +|ArrayOfCollectionOfModel|✓|ToolingExtension +|ArrayOfCollectionOfEnum|✓|ToolingExtension +|MapOfEnum|✓|ToolingExtension +|MapOfModel|✓|ToolingExtension +|MapOfCollectionOfPrimitives|✓|ToolingExtension +|MapOfCollectionOfModel|✓|ToolingExtension +|MapOfCollectionOfEnum|✓|ToolingExtension + +### Documentation Feature +| Name | Supported | Defined By | +| ---- | --------- | ---------- | +|Readme|✗|ToolingExtension +|Model|✓|ToolingExtension +|Api|✓|ToolingExtension + +### Global Feature +| Name | Supported | Defined By | +| ---- | --------- | ---------- | +|Host|✓|OAS2,OAS3 +|BasePath|✓|OAS2,OAS3 +|Info|✓|OAS2,OAS3 +|Schemes|✗|OAS2,OAS3 +|PartialSchemes|✓|OAS2,OAS3 +|Consumes|✓|OAS2 +|Produces|✓|OAS2 +|ExternalDocumentation|✓|OAS2,OAS3 +|Examples|✓|OAS2,OAS3 +|XMLStructureDefinitions|✗|OAS2,OAS3 +|MultiServer|✗|OAS3 +|ParameterizedServer|✗|OAS3 +|ParameterStyling|✗|OAS3 +|Callbacks|✓|OAS3 +|LinkObjects|✗|OAS3 + +### Parameter Feature +| Name | Supported | Defined By | +| ---- | --------- | ---------- | +|Path|✓|OAS2,OAS3 +|Query|✓|OAS2,OAS3 +|Header|✓|OAS2,OAS3 +|Body|✓|OAS2 +|FormUnencoded|✓|OAS2 +|FormMultipart|✓|OAS2 +|Cookie|✓|OAS3 + +### Schema Support Feature +| Name | Supported | Defined By | +| ---- | --------- | ---------- | +|Simple|✓|OAS2,OAS3 +|Composite|✓|OAS2,OAS3 +|Polymorphism|✓|OAS2,OAS3 +|Union|✗|OAS3 +|allOf|✗|OAS2,OAS3 +|anyOf|✗|OAS3 +|oneOf|✗|OAS3 +|not|✗|OAS3 + +### Security Feature +| Name | Supported | Defined By | +| ---- | --------- | ---------- | +|BasicAuth|✓|OAS2,OAS3 +|ApiKey|✓|OAS2,OAS3 +|OpenIDConnect|✓|OAS3 +|BearerToken|✓|OAS3 +|OAuth2_Implicit|✓|OAS2,OAS3 +|OAuth2_Password|✓|OAS2,OAS3 +|OAuth2_ClientCredentials|✓|OAS2,OAS3 +|OAuth2_AuthorizationCode|✓|OAS2,OAS3 +|SignatureAuth|✗|OAS3 + +### Wire Format Feature +| Name | Supported | Defined By | +| ---- | --------- | ---------- | +|JSON|✓|OAS2,OAS3 +|XML|✓|OAS2,OAS3 +|PROTOBUF|✗|ToolingExtension +|Custom|✗|OAS2,OAS3 diff --git a/samples/client/petstore/swift-alt/client/.openapi-generator/VERSION b/samples/client/petstore/swift-alt/client/.openapi-generator/VERSION deleted file mode 100644 index 4b448de535c7..000000000000 --- a/samples/client/petstore/swift-alt/client/.openapi-generator/VERSION +++ /dev/null @@ -1 +0,0 @@ -5.3.0-SNAPSHOT \ No newline at end of file diff --git a/samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/APIs/PetAPI.swift b/samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/APIs/PetAPI.swift deleted file mode 100644 index 9fb858ac90e3..000000000000 --- a/samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/APIs/PetAPI.swift +++ /dev/null @@ -1,363 +0,0 @@ -// -// PetAPI.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech - -import Foundation -import Combine -import OpenAPITransport - - -open class PetAPI { - private static let encoder: JSONEncoder = { - let encoder = JSONEncoder() - encoder.dateEncodingStrategy = .formatted(OpenISO8601DateFormatter()) - encoder.outputFormatting = .prettyPrinted - return encoder - }() - private static let decoder: JSONDecoder = { - let decoder = JSONDecoder() - decoder.dateDecodingStrategy = .formatted(OpenISO8601DateFormatter()) - return decoder - }() - private let transport: OpenAPITransport - public let baseURL = URL(string: "http://petstore.swagger.io/v2") - - public init(_ transport: OpenAPITransport) { - self.transport = transport - } - - /** - Add a new pet to the store - - POST /pet - - OAuth: - - type: oauth2 - - name: petstore_auth - - parameter pet: (body) Pet object that needs to be added to the store - - returns: AnyPublisher - */ - open func addPet(pet: Pet) -> AnyPublisher { - // Creating final URL with query items and path - guard let baseURL = transport.baseURL ?? self.baseURL else { - return Fail(error: OpenAPITransportError.badURLError()) - .eraseToAnyPublisher() - } - - let path = "/pet" - let url = baseURL.appendingPathComponent(path) - let components = URLComponents(url: url, resolvingAgainstBaseURL: false) - - guard let requestURL = components?.url else { - return Fail(error: OpenAPITransportError.badURLError()) - .eraseToAnyPublisher() - } - - var request = URLRequest(url: requestURL) - request.httpMethod = "POST" - - // Setting body parameters - request.httpBody = try? PetAPI.encoder.encode(pet) - if request.value(forHTTPHeaderField: "Content-Type") == nil { - request.setValue("application/json", forHTTPHeaderField: "Content-Type") - } - - // Getting auth type - let securitySchemes: [SecurityScheme] = [] - return transport.send(request: request, securitySchemes: securitySchemes) - .tryMap { response in - try PetAPI.decoder.decode(Pet.self, from: response.data) - } - .eraseToAnyPublisher() - } - - /** - Deletes a pet - - DELETE /pet/{petId} - - OAuth: - - type: oauth2 - - name: petstore_auth - - parameter petId: (path) Pet id to delete - - parameter apiKey: (header) (optional) - - returns: AnyPublisher - */ - open func deletePet(petId: Int64, apiKey: String? = nil) -> AnyPublisher { - // Creating final URL with query items and path - guard let baseURL = transport.baseURL ?? self.baseURL else { - return Fail(error: OpenAPITransportError.badURLError()) - .eraseToAnyPublisher() - } - - let path = "/pet/{petId}" - .replacingOccurrences(of: "{petId}", with: "\(petId)") - let url = baseURL.appendingPathComponent(path) - let components = URLComponents(url: url, resolvingAgainstBaseURL: false) - - guard let requestURL = components?.url else { - return Fail(error: OpenAPITransportError.badURLError()) - .eraseToAnyPublisher() - } - - var request = URLRequest(url: requestURL) - request.httpMethod = "DELETE" - // Setting headers - request.allHTTPHeaderFields = [ - "api_key": apiKey - ].compactMapValues { $0 } - - // Getting auth type - let securitySchemes: [SecurityScheme] = [] - return transport.send(request: request, securitySchemes: securitySchemes) - .tryMap { response in - return () - } - .eraseToAnyPublisher() - } - - /** - Finds Pets by status - - GET /pet/findByStatus - - Multiple status values can be provided with comma separated strings - - OAuth: - - type: oauth2 - - name: petstore_auth - - parameter status: (query) Status values that need to be considered for filter - - returns: AnyPublisher<[Pet], Error> - */ - open func findPetsByStatus(status: [String]) -> AnyPublisher<[Pet], Error> { - // Creating final URL with query items and path - guard let baseURL = transport.baseURL ?? self.baseURL else { - return Fail(error: OpenAPITransportError.badURLError()) - .eraseToAnyPublisher() - } - - let path = "/pet/findByStatus" - let url = baseURL.appendingPathComponent(path) - var components = URLComponents(url: url, resolvingAgainstBaseURL: false) - components?.queryItems = [ - URLQueryItem(name: "status", value: status.joined(separator: ", ")) - ] - guard let requestURL = components?.url else { - return Fail(error: OpenAPITransportError.badURLError()) - .eraseToAnyPublisher() - } - - var request = URLRequest(url: requestURL) - request.httpMethod = "GET" - - - // Getting auth type - let securitySchemes: [SecurityScheme] = [] - return transport.send(request: request, securitySchemes: securitySchemes) - .tryMap { response in - try PetAPI.decoder.decode([Pet].self, from: response.data) - } - .eraseToAnyPublisher() - } - - /** - Finds Pets by tags - - GET /pet/findByTags - - Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. - - OAuth: - - type: oauth2 - - name: petstore_auth - - parameter tags: (query) Tags to filter by - - returns: AnyPublisher<[Pet], Error> - */ - open func findPetsByTags(tags: [String]) -> AnyPublisher<[Pet], Error> { - // Creating final URL with query items and path - guard let baseURL = transport.baseURL ?? self.baseURL else { - return Fail(error: OpenAPITransportError.badURLError()) - .eraseToAnyPublisher() - } - - let path = "/pet/findByTags" - let url = baseURL.appendingPathComponent(path) - var components = URLComponents(url: url, resolvingAgainstBaseURL: false) - components?.queryItems = [ - URLQueryItem(name: "tags", value: tags.joined(separator: ", ")) - ] - guard let requestURL = components?.url else { - return Fail(error: OpenAPITransportError.badURLError()) - .eraseToAnyPublisher() - } - - var request = URLRequest(url: requestURL) - request.httpMethod = "GET" - - - // Getting auth type - let securitySchemes: [SecurityScheme] = [] - return transport.send(request: request, securitySchemes: securitySchemes) - .tryMap { response in - try PetAPI.decoder.decode([Pet].self, from: response.data) - } - .eraseToAnyPublisher() - } - - /** - Find pet by ID - - GET /pet/{petId} - - Returns a single pet - - API Key: - - type: apiKey api_key - - name: api_key - - parameter petId: (path) ID of pet to return - - returns: AnyPublisher - */ - open func getPetById(petId: Int64) -> AnyPublisher { - // Creating final URL with query items and path - guard let baseURL = transport.baseURL ?? self.baseURL else { - return Fail(error: OpenAPITransportError.badURLError()) - .eraseToAnyPublisher() - } - - let path = "/pet/{petId}" - .replacingOccurrences(of: "{petId}", with: "\(petId)") - let url = baseURL.appendingPathComponent(path) - let components = URLComponents(url: url, resolvingAgainstBaseURL: false) - - guard let requestURL = components?.url else { - return Fail(error: OpenAPITransportError.badURLError()) - .eraseToAnyPublisher() - } - - var request = URLRequest(url: requestURL) - request.httpMethod = "GET" - - - // Getting auth type - let securitySchemes: [SecurityScheme] = [] - return transport.send(request: request, securitySchemes: securitySchemes) - .tryMap { response in - try PetAPI.decoder.decode(Pet.self, from: response.data) - } - .eraseToAnyPublisher() - } - - /** - Update an existing pet - - PUT /pet - - OAuth: - - type: oauth2 - - name: petstore_auth - - parameter pet: (body) Pet object that needs to be added to the store - - returns: AnyPublisher - */ - open func updatePet(pet: Pet) -> AnyPublisher { - // Creating final URL with query items and path - guard let baseURL = transport.baseURL ?? self.baseURL else { - return Fail(error: OpenAPITransportError.badURLError()) - .eraseToAnyPublisher() - } - - let path = "/pet" - let url = baseURL.appendingPathComponent(path) - let components = URLComponents(url: url, resolvingAgainstBaseURL: false) - - guard let requestURL = components?.url else { - return Fail(error: OpenAPITransportError.badURLError()) - .eraseToAnyPublisher() - } - - var request = URLRequest(url: requestURL) - request.httpMethod = "PUT" - - // Setting body parameters - request.httpBody = try? PetAPI.encoder.encode(pet) - if request.value(forHTTPHeaderField: "Content-Type") == nil { - request.setValue("application/json", forHTTPHeaderField: "Content-Type") - } - - // Getting auth type - let securitySchemes: [SecurityScheme] = [] - return transport.send(request: request, securitySchemes: securitySchemes) - .tryMap { response in - try PetAPI.decoder.decode(Pet.self, from: response.data) - } - .eraseToAnyPublisher() - } - - /** - Updates a pet in the store with form data - - POST /pet/{petId} - - OAuth: - - type: oauth2 - - name: petstore_auth - - parameter petId: (path) ID of pet that needs to be updated - - parameter name: (form) Updated name of the pet (optional) - - parameter status: (form) Updated status of the pet (optional) - - returns: AnyPublisher - */ - open func updatePetWithForm(petId: Int64, name: String? = nil, status: String? = nil) -> AnyPublisher { - // Creating final URL with query items and path - guard let baseURL = transport.baseURL ?? self.baseURL else { - return Fail(error: OpenAPITransportError.badURLError()) - .eraseToAnyPublisher() - } - - let path = "/pet/{petId}" - .replacingOccurrences(of: "{petId}", with: "\(petId)") - let url = baseURL.appendingPathComponent(path) - let components = URLComponents(url: url, resolvingAgainstBaseURL: false) - - guard let requestURL = components?.url else { - return Fail(error: OpenAPITransportError.badURLError()) - .eraseToAnyPublisher() - } - - var request = URLRequest(url: requestURL) - request.httpMethod = "POST" - - - // Getting auth type - let securitySchemes: [SecurityScheme] = [] - return transport.send(request: request, securitySchemes: securitySchemes) - .tryMap { response in - return () - } - .eraseToAnyPublisher() - } - - /** - uploads an image - - POST /pet/{petId}/uploadImage - - OAuth: - - type: oauth2 - - name: petstore_auth - - parameter petId: (path) ID of pet to update - - parameter additionalMetadata: (form) Additional data to pass to server (optional) - - parameter file: (form) file to upload (optional) - - returns: AnyPublisher - */ - open func uploadFile(petId: Int64, additionalMetadata: String? = nil, file: Data? = nil) -> AnyPublisher { - // Creating final URL with query items and path - guard let baseURL = transport.baseURL ?? self.baseURL else { - return Fail(error: OpenAPITransportError.badURLError()) - .eraseToAnyPublisher() - } - - let path = "/pet/{petId}/uploadImage" - .replacingOccurrences(of: "{petId}", with: "\(petId)") - let url = baseURL.appendingPathComponent(path) - let components = URLComponents(url: url, resolvingAgainstBaseURL: false) - - guard let requestURL = components?.url else { - return Fail(error: OpenAPITransportError.badURLError()) - .eraseToAnyPublisher() - } - - var request = URLRequest(url: requestURL) - request.httpMethod = "POST" - - - // Getting auth type - let securitySchemes: [SecurityScheme] = [] - return transport.send(request: request, securitySchemes: securitySchemes) - .tryMap { response in - try PetAPI.decoder.decode(ApiResponse.self, from: response.data) - } - .eraseToAnyPublisher() - } -} diff --git a/samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/APIs/StoreAPI.swift b/samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/APIs/StoreAPI.swift deleted file mode 100644 index ba96d8dfdc37..000000000000 --- a/samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/APIs/StoreAPI.swift +++ /dev/null @@ -1,182 +0,0 @@ -// -// StoreAPI.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech - -import Foundation -import Combine -import OpenAPITransport - - -open class StoreAPI { - private static let encoder: JSONEncoder = { - let encoder = JSONEncoder() - encoder.dateEncodingStrategy = .formatted(OpenISO8601DateFormatter()) - encoder.outputFormatting = .prettyPrinted - return encoder - }() - private static let decoder: JSONDecoder = { - let decoder = JSONDecoder() - decoder.dateDecodingStrategy = .formatted(OpenISO8601DateFormatter()) - return decoder - }() - private let transport: OpenAPITransport - public let baseURL = URL(string: "http://petstore.swagger.io/v2") - - public init(_ transport: OpenAPITransport) { - self.transport = transport - } - - /** - Delete purchase order by ID - - DELETE /store/order/{orderId} - - For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors - - parameter orderId: (path) ID of the order that needs to be deleted - - returns: AnyPublisher - */ - open func deleteOrder(orderId: String) -> AnyPublisher { - // Creating final URL with query items and path - guard let baseURL = transport.baseURL ?? self.baseURL else { - return Fail(error: OpenAPITransportError.badURLError()) - .eraseToAnyPublisher() - } - - let path = "/store/order/{orderId}" - .replacingOccurrences(of: "{orderId}", with: "\(orderId)") - let url = baseURL.appendingPathComponent(path) - let components = URLComponents(url: url, resolvingAgainstBaseURL: false) - - guard let requestURL = components?.url else { - return Fail(error: OpenAPITransportError.badURLError()) - .eraseToAnyPublisher() - } - - var request = URLRequest(url: requestURL) - request.httpMethod = "DELETE" - - - // Getting auth type - let securitySchemes: [SecurityScheme] = [] - return transport.send(request: request, securitySchemes: securitySchemes) - .tryMap { response in - return () - } - .eraseToAnyPublisher() - } - - /** - Returns pet inventories by status - - GET /store/inventory - - Returns a map of status codes to quantities - - API Key: - - type: apiKey api_key - - name: api_key - - returns: AnyPublisher<[String: Int], Error> - */ - open func getInventory() -> AnyPublisher<[String: Int], Error> { - // Creating final URL with query items and path - guard let baseURL = transport.baseURL ?? self.baseURL else { - return Fail(error: OpenAPITransportError.badURLError()) - .eraseToAnyPublisher() - } - - let path = "/store/inventory" - let url = baseURL.appendingPathComponent(path) - let components = URLComponents(url: url, resolvingAgainstBaseURL: false) - - guard let requestURL = components?.url else { - return Fail(error: OpenAPITransportError.badURLError()) - .eraseToAnyPublisher() - } - - var request = URLRequest(url: requestURL) - request.httpMethod = "GET" - - - // Getting auth type - let securitySchemes: [SecurityScheme] = [] - return transport.send(request: request, securitySchemes: securitySchemes) - .tryMap { response in - try StoreAPI.decoder.decode([String: Int].self, from: response.data) - } - .eraseToAnyPublisher() - } - - /** - Find purchase order by ID - - GET /store/order/{orderId} - - For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions - - parameter orderId: (path) ID of pet that needs to be fetched - - returns: AnyPublisher - */ - open func getOrderById(orderId: Int64) -> AnyPublisher { - // Creating final URL with query items and path - guard let baseURL = transport.baseURL ?? self.baseURL else { - return Fail(error: OpenAPITransportError.badURLError()) - .eraseToAnyPublisher() - } - - let path = "/store/order/{orderId}" - .replacingOccurrences(of: "{orderId}", with: "\(orderId)") - let url = baseURL.appendingPathComponent(path) - let components = URLComponents(url: url, resolvingAgainstBaseURL: false) - - guard let requestURL = components?.url else { - return Fail(error: OpenAPITransportError.badURLError()) - .eraseToAnyPublisher() - } - - var request = URLRequest(url: requestURL) - request.httpMethod = "GET" - - - // Getting auth type - let securitySchemes: [SecurityScheme] = [] - return transport.send(request: request, securitySchemes: securitySchemes) - .tryMap { response in - try StoreAPI.decoder.decode(Order.self, from: response.data) - } - .eraseToAnyPublisher() - } - - /** - Place an order for a pet - - POST /store/order - - parameter order: (body) order placed for purchasing the pet - - returns: AnyPublisher - */ - open func placeOrder(order: Order) -> AnyPublisher { - // Creating final URL with query items and path - guard let baseURL = transport.baseURL ?? self.baseURL else { - return Fail(error: OpenAPITransportError.badURLError()) - .eraseToAnyPublisher() - } - - let path = "/store/order" - let url = baseURL.appendingPathComponent(path) - let components = URLComponents(url: url, resolvingAgainstBaseURL: false) - - guard let requestURL = components?.url else { - return Fail(error: OpenAPITransportError.badURLError()) - .eraseToAnyPublisher() - } - - var request = URLRequest(url: requestURL) - request.httpMethod = "POST" - - // Setting body parameters - request.httpBody = try? StoreAPI.encoder.encode(order) - if request.value(forHTTPHeaderField: "Content-Type") == nil { - request.setValue("application/json", forHTTPHeaderField: "Content-Type") - } - - // Getting auth type - let securitySchemes: [SecurityScheme] = [] - return transport.send(request: request, securitySchemes: securitySchemes) - .tryMap { response in - try StoreAPI.decoder.decode(Order.self, from: response.data) - } - .eraseToAnyPublisher() - } -} diff --git a/samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/APIs/UserAPI.swift b/samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/APIs/UserAPI.swift deleted file mode 100644 index cc189c962ee4..000000000000 --- a/samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/APIs/UserAPI.swift +++ /dev/null @@ -1,359 +0,0 @@ -// -// UserAPI.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech - -import Foundation -import Combine -import OpenAPITransport - - -open class UserAPI { - private static let encoder: JSONEncoder = { - let encoder = JSONEncoder() - encoder.dateEncodingStrategy = .formatted(OpenISO8601DateFormatter()) - encoder.outputFormatting = .prettyPrinted - return encoder - }() - private static let decoder: JSONDecoder = { - let decoder = JSONDecoder() - decoder.dateDecodingStrategy = .formatted(OpenISO8601DateFormatter()) - return decoder - }() - private let transport: OpenAPITransport - public let baseURL = URL(string: "http://petstore.swagger.io/v2") - - public init(_ transport: OpenAPITransport) { - self.transport = transport - } - - /** - Create user - - POST /user - - This can only be done by the logged in user. - - API Key: - - type: apiKey api_key - - name: api_key - - parameter user: (body) Created user object - - returns: AnyPublisher - */ - open func createUser(user: User) -> AnyPublisher { - // Creating final URL with query items and path - guard let baseURL = transport.baseURL ?? self.baseURL else { - return Fail(error: OpenAPITransportError.badURLError()) - .eraseToAnyPublisher() - } - - let path = "/user" - let url = baseURL.appendingPathComponent(path) - let components = URLComponents(url: url, resolvingAgainstBaseURL: false) - - guard let requestURL = components?.url else { - return Fail(error: OpenAPITransportError.badURLError()) - .eraseToAnyPublisher() - } - - var request = URLRequest(url: requestURL) - request.httpMethod = "POST" - - // Setting body parameters - request.httpBody = try? UserAPI.encoder.encode(user) - if request.value(forHTTPHeaderField: "Content-Type") == nil { - request.setValue("application/json", forHTTPHeaderField: "Content-Type") - } - - // Getting auth type - let securitySchemes: [SecurityScheme] = [] - return transport.send(request: request, securitySchemes: securitySchemes) - .tryMap { response in - return () - } - .eraseToAnyPublisher() - } - - /** - Creates list of users with given input array - - POST /user/createWithArray - - API Key: - - type: apiKey api_key - - name: api_key - - parameter user: (body) List of user object - - returns: AnyPublisher - */ - open func createUsersWithArrayInput(user: [User]) -> AnyPublisher { - // Creating final URL with query items and path - guard let baseURL = transport.baseURL ?? self.baseURL else { - return Fail(error: OpenAPITransportError.badURLError()) - .eraseToAnyPublisher() - } - - let path = "/user/createWithArray" - let url = baseURL.appendingPathComponent(path) - let components = URLComponents(url: url, resolvingAgainstBaseURL: false) - - guard let requestURL = components?.url else { - return Fail(error: OpenAPITransportError.badURLError()) - .eraseToAnyPublisher() - } - - var request = URLRequest(url: requestURL) - request.httpMethod = "POST" - - // Setting body parameters - request.httpBody = try? UserAPI.encoder.encode(user) - if request.value(forHTTPHeaderField: "Content-Type") == nil { - request.setValue("application/json", forHTTPHeaderField: "Content-Type") - } - - // Getting auth type - let securitySchemes: [SecurityScheme] = [] - return transport.send(request: request, securitySchemes: securitySchemes) - .tryMap { response in - return () - } - .eraseToAnyPublisher() - } - - /** - Creates list of users with given input array - - POST /user/createWithList - - API Key: - - type: apiKey api_key - - name: api_key - - parameter user: (body) List of user object - - returns: AnyPublisher - */ - open func createUsersWithListInput(user: [User]) -> AnyPublisher { - // Creating final URL with query items and path - guard let baseURL = transport.baseURL ?? self.baseURL else { - return Fail(error: OpenAPITransportError.badURLError()) - .eraseToAnyPublisher() - } - - let path = "/user/createWithList" - let url = baseURL.appendingPathComponent(path) - let components = URLComponents(url: url, resolvingAgainstBaseURL: false) - - guard let requestURL = components?.url else { - return Fail(error: OpenAPITransportError.badURLError()) - .eraseToAnyPublisher() - } - - var request = URLRequest(url: requestURL) - request.httpMethod = "POST" - - // Setting body parameters - request.httpBody = try? UserAPI.encoder.encode(user) - if request.value(forHTTPHeaderField: "Content-Type") == nil { - request.setValue("application/json", forHTTPHeaderField: "Content-Type") - } - - // Getting auth type - let securitySchemes: [SecurityScheme] = [] - return transport.send(request: request, securitySchemes: securitySchemes) - .tryMap { response in - return () - } - .eraseToAnyPublisher() - } - - /** - Delete user - - DELETE /user/{username} - - This can only be done by the logged in user. - - API Key: - - type: apiKey api_key - - name: api_key - - parameter username: (path) The name that needs to be deleted - - returns: AnyPublisher - */ - open func deleteUser(username: String) -> AnyPublisher { - // Creating final URL with query items and path - guard let baseURL = transport.baseURL ?? self.baseURL else { - return Fail(error: OpenAPITransportError.badURLError()) - .eraseToAnyPublisher() - } - - let path = "/user/{username}" - .replacingOccurrences(of: "{username}", with: "\(username)") - let url = baseURL.appendingPathComponent(path) - let components = URLComponents(url: url, resolvingAgainstBaseURL: false) - - guard let requestURL = components?.url else { - return Fail(error: OpenAPITransportError.badURLError()) - .eraseToAnyPublisher() - } - - var request = URLRequest(url: requestURL) - request.httpMethod = "DELETE" - - - // Getting auth type - let securitySchemes: [SecurityScheme] = [] - return transport.send(request: request, securitySchemes: securitySchemes) - .tryMap { response in - return () - } - .eraseToAnyPublisher() - } - - /** - Get user by user name - - GET /user/{username} - - parameter username: (path) The name that needs to be fetched. Use user1 for testing. - - returns: AnyPublisher - */ - open func getUserByName(username: String) -> AnyPublisher { - // Creating final URL with query items and path - guard let baseURL = transport.baseURL ?? self.baseURL else { - return Fail(error: OpenAPITransportError.badURLError()) - .eraseToAnyPublisher() - } - - let path = "/user/{username}" - .replacingOccurrences(of: "{username}", with: "\(username)") - let url = baseURL.appendingPathComponent(path) - let components = URLComponents(url: url, resolvingAgainstBaseURL: false) - - guard let requestURL = components?.url else { - return Fail(error: OpenAPITransportError.badURLError()) - .eraseToAnyPublisher() - } - - var request = URLRequest(url: requestURL) - request.httpMethod = "GET" - - - // Getting auth type - let securitySchemes: [SecurityScheme] = [] - return transport.send(request: request, securitySchemes: securitySchemes) - .tryMap { response in - try UserAPI.decoder.decode(User.self, from: response.data) - } - .eraseToAnyPublisher() - } - - /** - Logs user into the system - - GET /user/login - - responseHeaders: [Set-Cookie(String), X-Rate-Limit(Int), X-Expires-After(Date)] - - parameter username: (query) The user name for login - - parameter password: (query) The password for login in clear text - - returns: AnyPublisher - */ - open func loginUser(username: String, password: String) -> AnyPublisher { - // Creating final URL with query items and path - guard let baseURL = transport.baseURL ?? self.baseURL else { - return Fail(error: OpenAPITransportError.badURLError()) - .eraseToAnyPublisher() - } - - let path = "/user/login" - let url = baseURL.appendingPathComponent(path) - var components = URLComponents(url: url, resolvingAgainstBaseURL: false) - components?.queryItems = [ - URLQueryItem(name: "username", value: username), - URLQueryItem(name: "password", value: password) - ] - guard let requestURL = components?.url else { - return Fail(error: OpenAPITransportError.badURLError()) - .eraseToAnyPublisher() - } - - var request = URLRequest(url: requestURL) - request.httpMethod = "GET" - - - // Getting auth type - let securitySchemes: [SecurityScheme] = [] - return transport.send(request: request, securitySchemes: securitySchemes) - .tryMap { response in - try UserAPI.decoder.decode(String.self, from: response.data) - } - .eraseToAnyPublisher() - } - - /** - Logs out current logged in user session - - GET /user/logout - - API Key: - - type: apiKey api_key - - name: api_key - - returns: AnyPublisher - */ - open func logoutUser() -> AnyPublisher { - // Creating final URL with query items and path - guard let baseURL = transport.baseURL ?? self.baseURL else { - return Fail(error: OpenAPITransportError.badURLError()) - .eraseToAnyPublisher() - } - - let path = "/user/logout" - let url = baseURL.appendingPathComponent(path) - let components = URLComponents(url: url, resolvingAgainstBaseURL: false) - - guard let requestURL = components?.url else { - return Fail(error: OpenAPITransportError.badURLError()) - .eraseToAnyPublisher() - } - - var request = URLRequest(url: requestURL) - request.httpMethod = "GET" - - - // Getting auth type - let securitySchemes: [SecurityScheme] = [] - return transport.send(request: request, securitySchemes: securitySchemes) - .tryMap { response in - return () - } - .eraseToAnyPublisher() - } - - /** - Updated user - - PUT /user/{username} - - This can only be done by the logged in user. - - API Key: - - type: apiKey api_key - - name: api_key - - parameter username: (path) name that need to be deleted - - parameter user: (body) Updated user object - - returns: AnyPublisher - */ - open func updateUser(username: String, user: User) -> AnyPublisher { - // Creating final URL with query items and path - guard let baseURL = transport.baseURL ?? self.baseURL else { - return Fail(error: OpenAPITransportError.badURLError()) - .eraseToAnyPublisher() - } - - let path = "/user/{username}" - .replacingOccurrences(of: "{username}", with: "\(username)") - let url = baseURL.appendingPathComponent(path) - let components = URLComponents(url: url, resolvingAgainstBaseURL: false) - - guard let requestURL = components?.url else { - return Fail(error: OpenAPITransportError.badURLError()) - .eraseToAnyPublisher() - } - - var request = URLRequest(url: requestURL) - request.httpMethod = "PUT" - - // Setting body parameters - request.httpBody = try? UserAPI.encoder.encode(user) - if request.value(forHTTPHeaderField: "Content-Type") == nil { - request.setValue("application/json", forHTTPHeaderField: "Content-Type") - } - - // Getting auth type - let securitySchemes: [SecurityScheme] = [] - return transport.send(request: request, securitySchemes: securitySchemes) - .tryMap { response in - return () - } - .eraseToAnyPublisher() - } -} diff --git a/samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/Models/ApiResponse.swift b/samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/Models/ApiResponse.swift deleted file mode 100644 index b6098eb34a0e..000000000000 --- a/samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/Models/ApiResponse.swift +++ /dev/null @@ -1,37 +0,0 @@ -// -// ApiResponse.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech -// - -import Foundation - -/** Describes the result of uploading an image resource */ - -public struct ApiResponse: Codable, Hashable { - public var code: Int? - public var type: String? - public var message: String? - - public init(code: Int? = nil, type: String? = nil, message: String? = nil) { - self.code = code - self.type = type - self.message = message - } - - public enum CodingKeys: String, CodingKey, CaseIterable { - case code - case type - case message - } - - // Encodable protocol methods - - public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encodeIfPresent(code, forKey: .code) - try container.encodeIfPresent(type, forKey: .type) - try container.encodeIfPresent(message, forKey: .message) - } -} diff --git a/samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/Models/Category.swift b/samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/Models/Category.swift deleted file mode 100644 index bbb2a6e804d8..000000000000 --- a/samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/Models/Category.swift +++ /dev/null @@ -1,33 +0,0 @@ -// -// Category.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech -// - -import Foundation - -/** A category for a pet */ - -public struct Category: Codable, Hashable { - public var id: Int64? - public var name: String? - - public init(id: Int64? = nil, name: String? = nil) { - self.id = id - self.name = name - } - - public enum CodingKeys: String, CodingKey, CaseIterable { - case id - case name - } - - // Encodable protocol methods - - public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encodeIfPresent(id, forKey: .id) - try container.encodeIfPresent(name, forKey: .name) - } -} diff --git a/samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/Models/Order.swift b/samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/Models/Order.swift deleted file mode 100644 index a6ace8325248..000000000000 --- a/samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/Models/Order.swift +++ /dev/null @@ -1,55 +0,0 @@ -// -// Order.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech -// - -import Foundation - -/** An order for a pets from the pet store */ - -public struct Order: Codable, Hashable { - public enum Status: String, Hashable, Codable, CaseIterable { - case placed = "placed" - case approved = "approved" - case delivered = "delivered" - } - public var id: Int64? - public var petId: Int64? - public var quantity: Int? - public var shipDate: Date? - /** Order Status */ - public var status: Status? - public var complete: Bool? = false - - public init(id: Int64? = nil, petId: Int64? = nil, quantity: Int? = nil, shipDate: Date? = nil, status: Status? = nil, complete: Bool? = false) { - self.id = id - self.petId = petId - self.quantity = quantity - self.shipDate = shipDate - self.status = status - self.complete = complete - } - - public enum CodingKeys: String, CodingKey, CaseIterable { - case id - case petId - case quantity - case shipDate - case status - case complete - } - - // Encodable protocol methods - - public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encodeIfPresent(id, forKey: .id) - try container.encodeIfPresent(petId, forKey: .petId) - try container.encodeIfPresent(quantity, forKey: .quantity) - try container.encodeIfPresent(shipDate, forKey: .shipDate) - try container.encodeIfPresent(status, forKey: .status) - try container.encodeIfPresent(complete, forKey: .complete) - } -} diff --git a/samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/Models/Pet.swift b/samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/Models/Pet.swift deleted file mode 100644 index 0e8d2982cede..000000000000 --- a/samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/Models/Pet.swift +++ /dev/null @@ -1,55 +0,0 @@ -// -// Pet.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech -// - -import Foundation - -/** A pet for sale in the pet store */ - -public struct Pet: Codable, Hashable { - public enum Status: String, Hashable, Codable, CaseIterable { - case available = "available" - case pending = "pending" - case sold = "sold" - } - public var id: Int64? - public var category: Category? - public var name: String - public var photoUrls: [String] - public var tags: [Tag]? - /** pet status in the store */ - public var status: Status? - - public init(id: Int64? = nil, category: Category? = nil, name: String, photoUrls: [String], tags: [Tag]? = nil, status: Status? = nil) { - self.id = id - self.category = category - self.name = name - self.photoUrls = photoUrls - self.tags = tags - self.status = status - } - - public enum CodingKeys: String, CodingKey, CaseIterable { - case id - case category - case name - case photoUrls - case tags - case status - } - - // Encodable protocol methods - - public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encodeIfPresent(id, forKey: .id) - try container.encodeIfPresent(category, forKey: .category) - try container.encode(name, forKey: .name) - try container.encode(photoUrls, forKey: .photoUrls) - try container.encodeIfPresent(tags, forKey: .tags) - try container.encodeIfPresent(status, forKey: .status) - } -} diff --git a/samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/Models/Tag.swift b/samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/Models/Tag.swift deleted file mode 100644 index 978e87f83195..000000000000 --- a/samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/Models/Tag.swift +++ /dev/null @@ -1,33 +0,0 @@ -// -// Tag.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech -// - -import Foundation - -/** A tag for a pet */ - -public struct Tag: Codable, Hashable { - public var id: Int64? - public var name: String? - - public init(id: Int64? = nil, name: String? = nil) { - self.id = id - self.name = name - } - - public enum CodingKeys: String, CodingKey, CaseIterable { - case id - case name - } - - // Encodable protocol methods - - public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encodeIfPresent(id, forKey: .id) - try container.encodeIfPresent(name, forKey: .name) - } -} diff --git a/samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/Models/User.swift b/samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/Models/User.swift deleted file mode 100644 index 81b2ac916b2e..000000000000 --- a/samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/Models/User.swift +++ /dev/null @@ -1,58 +0,0 @@ -// -// User.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech -// - -import Foundation - -/** A User who is purchasing from the pet store */ - -public struct User: Codable, Hashable { - public var id: Int64? - public var username: String? - public var firstName: String? - public var lastName: String? - public var email: String? - public var password: String? - public var phone: String? - /** User Status */ - public var userStatus: Int? - - public init(id: Int64? = nil, username: String? = nil, firstName: String? = nil, lastName: String? = nil, email: String? = nil, password: String? = nil, phone: String? = nil, userStatus: Int? = nil) { - self.id = id - self.username = username - self.firstName = firstName - self.lastName = lastName - self.email = email - self.password = password - self.phone = phone - self.userStatus = userStatus - } - - public enum CodingKeys: String, CodingKey, CaseIterable { - case id - case username - case firstName - case lastName - case email - case password - case phone - case userStatus - } - - // Encodable protocol methods - - public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encodeIfPresent(id, forKey: .id) - try container.encodeIfPresent(username, forKey: .username) - try container.encodeIfPresent(firstName, forKey: .firstName) - try container.encodeIfPresent(lastName, forKey: .lastName) - try container.encodeIfPresent(email, forKey: .email) - try container.encodeIfPresent(password, forKey: .password) - try container.encodeIfPresent(phone, forKey: .phone) - try container.encodeIfPresent(userStatus, forKey: .userStatus) - } -} diff --git a/samples/client/petstore/swift-alt/.gitignore b/samples/client/petstore/swift-combine/.gitignore similarity index 100% rename from samples/client/petstore/swift-alt/.gitignore rename to samples/client/petstore/swift-combine/.gitignore diff --git a/samples/client/petstore/swift-alt/client/.openapi-generator-ignore b/samples/client/petstore/swift-combine/client/.openapi-generator-ignore similarity index 100% rename from samples/client/petstore/swift-alt/client/.openapi-generator-ignore rename to samples/client/petstore/swift-combine/client/.openapi-generator-ignore diff --git a/samples/client/petstore/swift-alt/client/.openapi-generator/FILES b/samples/client/petstore/swift-combine/client/.openapi-generator/FILES similarity index 100% rename from samples/client/petstore/swift-alt/client/.openapi-generator/FILES rename to samples/client/petstore/swift-combine/client/.openapi-generator/FILES diff --git a/samples/client/petstore/swift-combine/client/.openapi-generator/VERSION b/samples/client/petstore/swift-combine/client/.openapi-generator/VERSION new file mode 100644 index 000000000000..757e67400401 --- /dev/null +++ b/samples/client/petstore/swift-combine/client/.openapi-generator/VERSION @@ -0,0 +1 @@ +7.0.0-SNAPSHOT \ No newline at end of file diff --git a/samples/client/petstore/swift-alt/client/OpenAPITransport/Package.swift b/samples/client/petstore/swift-combine/client/OpenAPITransport/Package.swift similarity index 100% rename from samples/client/petstore/swift-alt/client/OpenAPITransport/Package.swift rename to samples/client/petstore/swift-combine/client/OpenAPITransport/Package.swift diff --git a/samples/client/petstore/swift-alt/client/OpenAPITransport/Sources/OpenAPITransport.swift b/samples/client/petstore/swift-combine/client/OpenAPITransport/Sources/OpenAPITransport.swift similarity index 65% rename from samples/client/petstore/swift-alt/client/OpenAPITransport/Sources/OpenAPITransport.swift rename to samples/client/petstore/swift-combine/client/OpenAPITransport/Sources/OpenAPITransport.swift index fcb10c10c592..99dc41cc125e 100644 --- a/samples/client/petstore/swift-alt/client/OpenAPITransport/Sources/OpenAPITransport.swift +++ b/samples/client/petstore/swift-combine/client/OpenAPITransport/Sources/OpenAPITransport.swift @@ -12,66 +12,43 @@ public enum SecurityScheme { // Security schemes not supported yet https://swagger.io/docs/specification/authentication/ } -// MARK: - Authenticator - -// Class which is able to add authentication headers and refresh authentication -public protocol Authenticator { - func authenticate(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher - func refresh(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher -} - -final class DefaultAuthenticator: Authenticator { - func authenticate(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher { - Just(request) - .setFailureType(to: OpenAPITransportError.self) - .eraseToAnyPublisher() - } - - func refresh(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher { - Fail(outputType: Void.self, failure: OpenAPITransportError.failedAuthenticationRefreshError()) - .eraseToAnyPublisher() - } - - init() { - } -} - // MARK: - Policy /// Policy to define whether response is successful or requires authentication public protocol URLResponsePolicy { - func defineState(for response: URLResponse) -> URLResponseState + func defineState(for request: URLRequest, output: URLSession.DataTaskPublisher.Output) -> AnyPublisher } public enum URLResponseState { + // Return success to client case success + // Return error to client case failure - case requiresAuthentication + // Repeat request + case retry } final class DefaultURLResponsePolicy: URLResponsePolicy { - func defineState(for response: URLResponse) -> URLResponseState { - switch (response as? HTTPURLResponse)?.statusCode { - case .some(200): - return .success - case .some(401): - return .requiresAuthentication - default: - return .failure + func defineState(for request: URLRequest, output: URLSession.DataTaskPublisher.Output) -> AnyPublisher { + let state: URLResponseState + switch (output.response as? HTTPURLResponse)?.statusCode { + case .some(200...299): state = .success + default: state = .failure } + return Just(state).eraseToAnyPublisher() } } /// Define how to customize URL request before network call public protocol URLRequestProcessor { /// Customize request before performing. Add headers or encrypt body for example. - func enrich(request: URLRequest) -> AnyPublisher + func enrich(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher /// Customize response before handling. Decrypt body for example. func decode(output: URLSession.DataTaskPublisher.Output) -> AnyPublisher } final class DefaultURLRequestProcessor: URLRequestProcessor { - func enrich(request: URLRequest) -> AnyPublisher { + func enrich(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher { Just(request) .setFailureType(to: OpenAPITransportError.self) .eraseToAnyPublisher() @@ -86,7 +63,7 @@ final class DefaultURLRequestProcessor: URLRequestProcessor { // MARK: - OpenAPITransport -public protocol OpenAPITransport { +public protocol OpenAPITransport: AnyObject { var baseURL: URL? { get } func send( @@ -205,16 +182,20 @@ public extension OpenAPITransportError { data: data ) } + + static let retryErrorCode = 606 + static let retryError = OpenAPITransportError(statusCode: OpenAPITransportError.retryErrorCode) } public protocol URLSessionOpenAPITransportDelegate: AnyObject { func willStart(request: URLRequest) - func didFinish(request: URLRequest, response: HTTPURLResponse?) + func didFinish(request: URLRequest, response: HTTPURLResponse?, data: Data) + func didFinish(request: URLRequest, error: Error) } open class URLSessionOpenAPITransport: OpenAPITransport { private var cancellable = Set() - private let config: Config + public var config: Config public var baseURL: URL? { config.baseURL } public init(config: Config = .init()) { @@ -227,48 +208,43 @@ open class URLSessionOpenAPITransport: OpenAPITransport { ) -> AnyPublisher { config.processor - // Add custom headers or if needed - .enrich(request: request) - // Add authentication headers if needed before request - .flatMap { request in - self.config.authenticator - .authenticate(request: request, securitySchemes: securitySchemes) - .eraseToAnyPublisher() - } + // Add custom headers or refresh token if needed + .enrich(request: request, securitySchemes: securitySchemes) .flatMap { request -> AnyPublisher in self.config.delegate?.willStart(request: request) // Perform network call - return URLSession.shared.dataTaskPublisher(for: request) - .mapError { OpenAPITransportError(statusCode: $0.code.rawValue, description: "Network call finished fails") } + return self.config.session.dataTaskPublisher(for: request) + .mapError { + self.config.delegate?.didFinish(request: request, error: $0) + return OpenAPITransportError(statusCode: $0.code.rawValue, description: "Network call finished fails") + } .flatMap { output in self.config.processor.decode(output: output) } .flatMap { output -> AnyPublisher in let response = output.response as? HTTPURLResponse - self.config.delegate?.didFinish(request: request, response: response) - switch self.config.policy.defineState(for: output.response) { - case .success: - let OpenAPITransportResponse = OpenAPITransportResponse(data: output.data, statusCode: 200) - return Result.success(OpenAPITransportResponse).publisher.eraseToAnyPublisher() - case .requiresAuthentication: - // Refresh authentication if possible - return self.config.authenticator - .refresh(request: request, securitySchemes: securitySchemes) - .flatMap { - // Try performing network call again - self.send(request: request, securitySchemes: securitySchemes) + self.config.delegate?.didFinish(request: request, response: response, data: output.data) + return self.config.policy.defineState(for: request, output: output) + .setFailureType(to: OpenAPITransportError.self) + .flatMap { state -> AnyPublisher in + switch state { + case .success: + let transportResponse = OpenAPITransportResponse(data: output.data, statusCode: 200) + return Result.success(transportResponse).publisher.eraseToAnyPublisher() + case .retry: + return Fail(error: OpenAPITransportError.retryError).eraseToAnyPublisher() + case .failure: + let code = response?.statusCode ?? OpenAPITransportError.noResponseCode + let transportError = OpenAPITransportError(statusCode: code, data: output.data) + return Fail(error: transportError).eraseToAnyPublisher() } - .eraseToAnyPublisher() - // TODO: Check too many attempts error - default: - let code = response?.statusCode ?? OpenAPITransportError.noResponseCode - let error = OpenAPITransportError(statusCode: code, data: output.data) - return Fail(error: error).eraseToAnyPublisher() - } + }.eraseToAnyPublisher() } .eraseToAnyPublisher() } - .eraseToAnyPublisher() + .retry(times: 2) { error -> Bool in + return error.statusCode == OpenAPITransportError.retryError.statusCode + }.eraseToAnyPublisher() } open func cancelAll() { @@ -280,7 +256,6 @@ public extension URLSessionOpenAPITransport { struct Config { public var baseURL: URL? = nil public var session: URLSession = .shared - public var authenticator: Authenticator = DefaultAuthenticator() public var processor: URLRequestProcessor = DefaultURLRequestProcessor() public var policy: URLResponsePolicy = DefaultURLResponsePolicy() public weak var delegate: URLSessionOpenAPITransportDelegate? @@ -292,3 +267,32 @@ public extension URLSessionOpenAPITransport { } } } + +fileprivate extension Publishers { + struct RetryIf: Publisher { + typealias Output = P.Output + typealias Failure = P.Failure + + let publisher: P + let times: Int + let condition: (P.Failure) -> Bool + + func receive(subscriber: S) where S : Subscriber, Failure == S.Failure, Output == S.Input { + guard times > 0 else { return publisher.receive(subscriber: subscriber) } + + publisher.catch { (error: P.Failure) -> AnyPublisher in + if condition(error) { + return RetryIf(publisher: publisher, times: times - 1, condition: condition).eraseToAnyPublisher() + } else { + return Fail(error: error).eraseToAnyPublisher() + } + }.receive(subscriber: subscriber) + } + } +} + +fileprivate extension Publisher { + func retry(times: Int, if condition: @escaping (Failure) -> Bool) -> Publishers.RetryIf { + Publishers.RetryIf(publisher: self, times: times, condition: condition) + } +} diff --git a/samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Package.swift b/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Package.swift similarity index 100% rename from samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Package.swift rename to samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Package.swift diff --git a/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/APIs/PetAPI.swift b/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/APIs/PetAPI.swift new file mode 100644 index 000000000000..1082363610b3 --- /dev/null +++ b/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/APIs/PetAPI.swift @@ -0,0 +1,512 @@ +// +// PetAPI.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech + +import Foundation +import Combine +import OpenAPITransport + + +open class PetAPI { + private let transport: OpenAPITransport + public var encoder: JSONEncoder = { + let encoder = JSONEncoder() + encoder.dateEncodingStrategy = .formatted(OpenISO8601DateFormatter()) + return encoder + }() + public var decoder: JSONDecoder = { + let decoder = JSONDecoder() + decoder.dateDecodingStrategy = .formatted(OpenISO8601DateFormatter()) + return decoder + }() + public var baseURL = URL(string: "http://petstore.swagger.io/v2") + + public init(_ transport: OpenAPITransport) { + self.transport = transport + } + + public enum AddPetError: Error, CustomStringConvertible { + // Invalid input + case code405Error + + public var description: String { + switch self { + case .code405Error: + return "AddPetError: Invalid input" + } + } + } + + /// Add a new pet to the store + /// - POST /pet + /// - + /// - OAuth: + /// - type: oauth2 + /// - name: petstore_auth + /// - parameter pet: (body) Pet object that needs to be added to the store + /// - returns: AnyPublisher + open func addPet(pet: Pet) -> AnyPublisher { + Deferred { + Result { + guard let baseURL = self.transport.baseURL ?? self.baseURL else { + throw OpenAPITransportError.badURLError() + } + let path = "/pet" + let url = baseURL.appendingPathComponent(path) + let components = URLComponents(url: url, resolvingAgainstBaseURL: false) + guard let requestURL = components?.url else { + throw OpenAPITransportError.badURLError() + } + var request = URLRequest(url: requestURL) + request.httpMethod = "POST" + request.httpBody = try self.encoder.encode(pet) + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + return request + }.publisher + }.flatMap { request -> AnyPublisher in + let securitySchemes: [SecurityScheme] = [] + return self.transport.send(request: request, securitySchemes: securitySchemes) + .mapError { transportError -> Error in + if transportError.statusCode == 405 { + return AddPetError.code405Error + } + return transportError + } + .tryMap { response in + try self.decoder.decode(Pet.self, from: response.data) + } + .eraseToAnyPublisher() + }.eraseToAnyPublisher() + } + + public enum DeletePetError: Error, CustomStringConvertible { + // Invalid pet value + case code400Error + + public var description: String { + switch self { + case .code400Error: + return "DeletePetError: Invalid pet value" + } + } + } + + /// Deletes a pet + /// - DELETE /pet/{petId} + /// - + /// - OAuth: + /// - type: oauth2 + /// - name: petstore_auth + /// - parameter petId: (path) Pet id to delete + /// - parameter apiKey: (header) (optional) + /// - returns: AnyPublisher + open func deletePet(petId: Int64, apiKey: String? = nil) -> AnyPublisher { + Deferred { + Result { + guard let baseURL = self.transport.baseURL ?? self.baseURL else { + throw OpenAPITransportError.badURLError() + } + var path = "/pet/{petId}" + path = path.replacingOccurrences(of: "{petId}", with: ) + let url = baseURL.appendingPathComponent(path) + let components = URLComponents(url: url, resolvingAgainstBaseURL: false) + guard let requestURL = components?.url else { + throw OpenAPITransportError.badURLError() + } + var request = URLRequest(url: requestURL) + request.httpMethod = "DELETE" + var headers = [String: String]() + if let apiKey = apiKey { headers["api_key"] = apiKey } + request.allHTTPHeaderFields = headers + return request + }.publisher + }.flatMap { request -> AnyPublisher in + let securitySchemes: [SecurityScheme] = [] + return self.transport.send(request: request, securitySchemes: securitySchemes) + .mapError { transportError -> Error in + if transportError.statusCode == 400 { + return DeletePetError.code400Error + } + return transportError + } + .tryMap { response in + return () + } + .eraseToAnyPublisher() + }.eraseToAnyPublisher() + } + + /// + /// Enum for parameter status + /// + public enum FindPetsByStatusStatus: String, Codable, CaseIterable { + case available = "available" + case pending = "pending" + case sold = "sold" + } + public enum FindPetsByStatusError: Error, CustomStringConvertible { + // Invalid status value + case code400Error + + public var description: String { + switch self { + case .code400Error: + return "FindPetsByStatusError: Invalid status value" + } + } + } + + /// Finds Pets by status + /// - GET /pet/findByStatus + /// - Multiple status values can be provided with comma separated strings + /// - OAuth: + /// - type: oauth2 + /// - name: petstore_auth + /// - parameter status: (query) Status values that need to be considered for filter + /// - returns: AnyPublisher<[Pet], Error> + open func findPetsByStatus(status: [FindPetsByStatusStatus]) -> AnyPublisher<[Pet], Error> { + Deferred { + Result { + guard let baseURL = self.transport.baseURL ?? self.baseURL else { + throw OpenAPITransportError.badURLError() + } + let path = "/pet/findByStatus" + let url = baseURL.appendingPathComponent(path) + var components = URLComponents(url: url, resolvingAgainstBaseURL: false) + var queryItems: [URLQueryItem] = [] + queryItems.append(URLQueryItem(name: "status", value: status.map { $0.rawValue }.joined(separator: ","))) + components?.queryItems = queryItems + guard let requestURL = components?.url else { + throw OpenAPITransportError.badURLError() + } + var request = URLRequest(url: requestURL) + request.httpMethod = "GET" + return request + }.publisher + }.flatMap { request -> AnyPublisher<[Pet], Error> in + let securitySchemes: [SecurityScheme] = [] + return self.transport.send(request: request, securitySchemes: securitySchemes) + .mapError { transportError -> Error in + if transportError.statusCode == 400 { + return FindPetsByStatusError.code400Error + } + return transportError + } + .tryMap { response in + try self.decoder.decode([Pet].self, from: response.data) + } + .eraseToAnyPublisher() + }.eraseToAnyPublisher() + } + + public enum FindPetsByTagsError: Error, CustomStringConvertible { + // Invalid tag value + case code400Error + + public var description: String { + switch self { + case .code400Error: + return "FindPetsByTagsError: Invalid tag value" + } + } + } + + /// Finds Pets by tags + /// - GET /pet/findByTags + /// - Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. + /// - OAuth: + /// - type: oauth2 + /// - name: petstore_auth + /// - parameter tags: (query) Tags to filter by + /// - returns: AnyPublisher<[Pet], Error> + @available(*, deprecated, message: "Deprecated API operation") + open func findPetsByTags(tags: [String]) -> AnyPublisher<[Pet], Error> { + Deferred { + Result { + guard let baseURL = self.transport.baseURL ?? self.baseURL else { + throw OpenAPITransportError.badURLError() + } + let path = "/pet/findByTags" + let url = baseURL.appendingPathComponent(path) + var components = URLComponents(url: url, resolvingAgainstBaseURL: false) + var queryItems: [URLQueryItem] = [] + queryItems.append(URLQueryItem(name: "tags", value: tags.joined(separator: ","))) + components?.queryItems = queryItems + guard let requestURL = components?.url else { + throw OpenAPITransportError.badURLError() + } + var request = URLRequest(url: requestURL) + request.httpMethod = "GET" + return request + }.publisher + }.flatMap { request -> AnyPublisher<[Pet], Error> in + let securitySchemes: [SecurityScheme] = [] + return self.transport.send(request: request, securitySchemes: securitySchemes) + .mapError { transportError -> Error in + if transportError.statusCode == 400 { + return FindPetsByTagsError.code400Error + } + return transportError + } + .tryMap { response in + try self.decoder.decode([Pet].self, from: response.data) + } + .eraseToAnyPublisher() + }.eraseToAnyPublisher() + } + + public enum GetPetByIdError: Error, CustomStringConvertible { + // Invalid ID supplied + case code400Error + // Pet not found + case code404Error + + public var description: String { + switch self { + case .code400Error: + return "GetPetByIdError: Invalid ID supplied" + case .code404Error: + return "GetPetByIdError: Pet not found" + } + } + } + + /// Find pet by ID + /// - GET /pet/{petId} + /// - Returns a single pet + /// - API Key: + /// - type: apiKey api_key + /// - name: api_key + /// - parameter petId: (path) ID of pet to return + /// - returns: AnyPublisher + open func getPetById(petId: Int64) -> AnyPublisher { + Deferred { + Result { + guard let baseURL = self.transport.baseURL ?? self.baseURL else { + throw OpenAPITransportError.badURLError() + } + var path = "/pet/{petId}" + path = path.replacingOccurrences(of: "{petId}", with: ) + let url = baseURL.appendingPathComponent(path) + let components = URLComponents(url: url, resolvingAgainstBaseURL: false) + guard let requestURL = components?.url else { + throw OpenAPITransportError.badURLError() + } + var request = URLRequest(url: requestURL) + request.httpMethod = "GET" + return request + }.publisher + }.flatMap { request -> AnyPublisher in + let securitySchemes: [SecurityScheme] = [] + return self.transport.send(request: request, securitySchemes: securitySchemes) + .mapError { transportError -> Error in + if transportError.statusCode == 400 { + return GetPetByIdError.code400Error + } + if transportError.statusCode == 404 { + return GetPetByIdError.code404Error + } + return transportError + } + .tryMap { response in + try self.decoder.decode(Pet.self, from: response.data) + } + .eraseToAnyPublisher() + }.eraseToAnyPublisher() + } + + public enum UpdatePetError: Error, CustomStringConvertible { + // Invalid ID supplied + case code400Error + // Pet not found + case code404Error + // Validation exception + case code405Error + + public var description: String { + switch self { + case .code400Error: + return "UpdatePetError: Invalid ID supplied" + case .code404Error: + return "UpdatePetError: Pet not found" + case .code405Error: + return "UpdatePetError: Validation exception" + } + } + } + + /// Update an existing pet + /// - PUT /pet + /// - + /// - OAuth: + /// - type: oauth2 + /// - name: petstore_auth + /// - externalDocs: class ExternalDocumentation { + description: API documentation for the updatePet operation + url: http://petstore.swagger.io/v2/doc/updatePet +} + /// - parameter pet: (body) Pet object that needs to be added to the store + /// - returns: AnyPublisher + open func updatePet(pet: Pet) -> AnyPublisher { + Deferred { + Result { + guard let baseURL = self.transport.baseURL ?? self.baseURL else { + throw OpenAPITransportError.badURLError() + } + let path = "/pet" + let url = baseURL.appendingPathComponent(path) + let components = URLComponents(url: url, resolvingAgainstBaseURL: false) + guard let requestURL = components?.url else { + throw OpenAPITransportError.badURLError() + } + var request = URLRequest(url: requestURL) + request.httpMethod = "PUT" + request.httpBody = try self.encoder.encode(pet) + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + return request + }.publisher + }.flatMap { request -> AnyPublisher in + let securitySchemes: [SecurityScheme] = [] + return self.transport.send(request: request, securitySchemes: securitySchemes) + .mapError { transportError -> Error in + if transportError.statusCode == 400 { + return UpdatePetError.code400Error + } + if transportError.statusCode == 404 { + return UpdatePetError.code404Error + } + if transportError.statusCode == 405 { + return UpdatePetError.code405Error + } + return transportError + } + .tryMap { response in + try self.decoder.decode(Pet.self, from: response.data) + } + .eraseToAnyPublisher() + }.eraseToAnyPublisher() + } + + public enum UpdatePetWithFormError: Error, CustomStringConvertible { + // Invalid input + case code405Error + + public var description: String { + switch self { + case .code405Error: + return "UpdatePetWithFormError: Invalid input" + } + } + } + + /// Updates a pet in the store with form data + /// - POST /pet/{petId} + /// - + /// - OAuth: + /// - type: oauth2 + /// - name: petstore_auth + /// - parameter petId: (path) ID of pet that needs to be updated + /// - parameter name: (form) Updated name of the pet (optional) + /// - parameter status: (form) Updated status of the pet (optional) + /// - returns: AnyPublisher + open func updatePetWithForm(petId: Int64, name: String? = nil, status: String? = nil) -> AnyPublisher { + Deferred { + Result { + guard let baseURL = self.transport.baseURL ?? self.baseURL else { + throw OpenAPITransportError.badURLError() + } + var path = "/pet/{petId}" + path = path.replacingOccurrences(of: "{petId}", with: ) + let url = baseURL.appendingPathComponent(path) + let components = URLComponents(url: url, resolvingAgainstBaseURL: false) + guard let requestURL = components?.url else { + throw OpenAPITransportError.badURLError() + } + var request = URLRequest(url: requestURL) + request.httpMethod = "POST" + var formEncodedItems: [String] = [] + if let name = name { formEncodedItems.append("name=\(name)") } + if let status = status { formEncodedItems.append("status=\(status)") } + request.httpBody = formEncodedItems.joined(separator: "&").data(using: .utf8) + request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type") + return request + }.publisher + }.flatMap { request -> AnyPublisher in + let securitySchemes: [SecurityScheme] = [] + return self.transport.send(request: request, securitySchemes: securitySchemes) + .mapError { transportError -> Error in + if transportError.statusCode == 405 { + return UpdatePetWithFormError.code405Error + } + return transportError + } + .tryMap { response in + return () + } + .eraseToAnyPublisher() + }.eraseToAnyPublisher() + } + + + /// uploads an image + /// - POST /pet/{petId}/uploadImage + /// - + /// - OAuth: + /// - type: oauth2 + /// - name: petstore_auth + /// - parameter petId: (path) ID of pet to update + /// - parameter additionalMetadata: (form) Additional data to pass to server (optional) + /// - parameter file: (form) file to upload (optional) + /// - returns: AnyPublisher + open func uploadFile(petId: Int64, additionalMetadata: String? = nil, file: Data? = nil) -> AnyPublisher { + Deferred { + Result { + guard let baseURL = self.transport.baseURL ?? self.baseURL else { + throw OpenAPITransportError.badURLError() + } + var path = "/pet/{petId}/uploadImage" + path = path.replacingOccurrences(of: "{petId}", with: ) + let url = baseURL.appendingPathComponent(path) + let components = URLComponents(url: url, resolvingAgainstBaseURL: false) + guard let requestURL = components?.url else { + throw OpenAPITransportError.badURLError() + } + var request = URLRequest(url: requestURL) + request.httpMethod = "POST" + let multipartBoundary = String(format: "Boundary+%08X%08X", arc4random(), arc4random()) + var multipartData = Data() + if let additionalMetadata = additionalMetadata { + let additionalMetadataHeader = "--\(multipartBoundary)\r\n" + .appending("Content-Disposition:form-data; name=\"additionalMetadata\"\r\n") + .appending("\r\n") + multipartData.append(additionalMetadataHeader.data(using: .utf8) ?? Data()) + multipartData.append(additionalMetadata.data(using: .utf8) ?? Data()) + multipartData.append("\r\n".data(using: .utf8) ?? Data()) + } + + if let file = file { + let fileHeader = "--\(multipartBoundary)\r\n" + .appending("Content-Disposition:form-data; name=\"file\"; filename=\"file\"\r\n") + .appending("\r\n") + multipartData.append(fileHeader.data(using: .utf8) ?? Data()) + multipartData.append(file) + } + + multipartData.append("\r\n--\(multipartBoundary)--\r\n".data(using: .utf8) ?? Data()) + request.httpBody = multipartData + request.setValue("\(multipartData.count)", forHTTPHeaderField: "Content-Length") + request.setValue("multipart/form-data; boundary=\(multipartBoundary)", forHTTPHeaderField: "Content-Type") + return request + }.publisher + }.flatMap { request -> AnyPublisher in + let securitySchemes: [SecurityScheme] = [] + return self.transport.send(request: request, securitySchemes: securitySchemes) + .tryMap { response in + try self.decoder.decode(ApiResponse.self, from: response.data) + } + .eraseToAnyPublisher() + }.eraseToAnyPublisher() + } +} diff --git a/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/APIs/StoreAPI.swift b/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/APIs/StoreAPI.swift new file mode 100644 index 000000000000..a3f6931b46ff --- /dev/null +++ b/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/APIs/StoreAPI.swift @@ -0,0 +1,228 @@ +// +// StoreAPI.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech + +import Foundation +import Combine +import OpenAPITransport + + +open class StoreAPI { + private let transport: OpenAPITransport + public var encoder: JSONEncoder = { + let encoder = JSONEncoder() + encoder.dateEncodingStrategy = .formatted(OpenISO8601DateFormatter()) + return encoder + }() + public var decoder: JSONDecoder = { + let decoder = JSONDecoder() + decoder.dateDecodingStrategy = .formatted(OpenISO8601DateFormatter()) + return decoder + }() + public var baseURL = URL(string: "http://petstore.swagger.io/v2") + + public init(_ transport: OpenAPITransport) { + self.transport = transport + } + + public enum DeleteOrderError: Error, CustomStringConvertible { + // Invalid ID supplied + case code400Error + // Order not found + case code404Error + + public var description: String { + switch self { + case .code400Error: + return "DeleteOrderError: Invalid ID supplied" + case .code404Error: + return "DeleteOrderError: Order not found" + } + } + } + + /// Delete purchase order by ID + /// - DELETE /store/order/{orderId} + /// - For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors + /// - parameter orderId: (path) ID of the order that needs to be deleted + /// - returns: AnyPublisher + open func deleteOrder(orderId: String) -> AnyPublisher { + Deferred { + Result { + guard let baseURL = self.transport.baseURL ?? self.baseURL else { + throw OpenAPITransportError.badURLError() + } + var path = "/store/order/{orderId}" + path = path.replacingOccurrences(of: "{orderId}", with: orderId) + let url = baseURL.appendingPathComponent(path) + let components = URLComponents(url: url, resolvingAgainstBaseURL: false) + guard let requestURL = components?.url else { + throw OpenAPITransportError.badURLError() + } + var request = URLRequest(url: requestURL) + request.httpMethod = "DELETE" + return request + }.publisher + }.flatMap { request -> AnyPublisher in + let securitySchemes: [SecurityScheme] = [] + return self.transport.send(request: request, securitySchemes: securitySchemes) + .mapError { transportError -> Error in + if transportError.statusCode == 400 { + return DeleteOrderError.code400Error + } + if transportError.statusCode == 404 { + return DeleteOrderError.code404Error + } + return transportError + } + .tryMap { response in + return () + } + .eraseToAnyPublisher() + }.eraseToAnyPublisher() + } + + + /// Returns pet inventories by status + /// - GET /store/inventory + /// - Returns a map of status codes to quantities + /// - API Key: + /// - type: apiKey api_key + /// - name: api_key + /// - returns: AnyPublisher<[String: Int], Error> + open func getInventory() -> AnyPublisher<[String: Int], Error> { + Deferred { + Result { + guard let baseURL = self.transport.baseURL ?? self.baseURL else { + throw OpenAPITransportError.badURLError() + } + let path = "/store/inventory" + let url = baseURL.appendingPathComponent(path) + let components = URLComponents(url: url, resolvingAgainstBaseURL: false) + guard let requestURL = components?.url else { + throw OpenAPITransportError.badURLError() + } + var request = URLRequest(url: requestURL) + request.httpMethod = "GET" + return request + }.publisher + }.flatMap { request -> AnyPublisher<[String: Int], Error> in + let securitySchemes: [SecurityScheme] = [] + return self.transport.send(request: request, securitySchemes: securitySchemes) + .tryMap { response in + try self.decoder.decode([String: Int].self, from: response.data) + } + .eraseToAnyPublisher() + }.eraseToAnyPublisher() + } + + public enum GetOrderByIdError: Error, CustomStringConvertible { + // Invalid ID supplied + case code400Error + // Order not found + case code404Error + + public var description: String { + switch self { + case .code400Error: + return "GetOrderByIdError: Invalid ID supplied" + case .code404Error: + return "GetOrderByIdError: Order not found" + } + } + } + + /// Find purchase order by ID + /// - GET /store/order/{orderId} + /// - For valid response try integer IDs with value <= 5 or > 10. Other values will generate exceptions + /// - parameter orderId: (path) ID of pet that needs to be fetched + /// - returns: AnyPublisher + open func getOrderById(orderId: Int64) -> AnyPublisher { + Deferred { + Result { + guard let baseURL = self.transport.baseURL ?? self.baseURL else { + throw OpenAPITransportError.badURLError() + } + var path = "/store/order/{orderId}" + path = path.replacingOccurrences(of: "{orderId}", with: ) + let url = baseURL.appendingPathComponent(path) + let components = URLComponents(url: url, resolvingAgainstBaseURL: false) + guard let requestURL = components?.url else { + throw OpenAPITransportError.badURLError() + } + var request = URLRequest(url: requestURL) + request.httpMethod = "GET" + return request + }.publisher + }.flatMap { request -> AnyPublisher in + let securitySchemes: [SecurityScheme] = [] + return self.transport.send(request: request, securitySchemes: securitySchemes) + .mapError { transportError -> Error in + if transportError.statusCode == 400 { + return GetOrderByIdError.code400Error + } + if transportError.statusCode == 404 { + return GetOrderByIdError.code404Error + } + return transportError + } + .tryMap { response in + try self.decoder.decode(Order.self, from: response.data) + } + .eraseToAnyPublisher() + }.eraseToAnyPublisher() + } + + public enum PlaceOrderError: Error, CustomStringConvertible { + // Invalid Order + case code400Error + + public var description: String { + switch self { + case .code400Error: + return "PlaceOrderError: Invalid Order" + } + } + } + + /// Place an order for a pet + /// - POST /store/order + /// - + /// - parameter order: (body) order placed for purchasing the pet + /// - returns: AnyPublisher + open func placeOrder(order: Order) -> AnyPublisher { + Deferred { + Result { + guard let baseURL = self.transport.baseURL ?? self.baseURL else { + throw OpenAPITransportError.badURLError() + } + let path = "/store/order" + let url = baseURL.appendingPathComponent(path) + let components = URLComponents(url: url, resolvingAgainstBaseURL: false) + guard let requestURL = components?.url else { + throw OpenAPITransportError.badURLError() + } + var request = URLRequest(url: requestURL) + request.httpMethod = "POST" + request.httpBody = try self.encoder.encode(order) + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + return request + }.publisher + }.flatMap { request -> AnyPublisher in + let securitySchemes: [SecurityScheme] = [] + return self.transport.send(request: request, securitySchemes: securitySchemes) + .mapError { transportError -> Error in + if transportError.statusCode == 400 { + return PlaceOrderError.code400Error + } + return transportError + } + .tryMap { response in + try self.decoder.decode(Order.self, from: response.data) + } + .eraseToAnyPublisher() + }.eraseToAnyPublisher() + } +} diff --git a/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/APIs/UserAPI.swift b/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/APIs/UserAPI.swift new file mode 100644 index 000000000000..c745d6d97d06 --- /dev/null +++ b/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/APIs/UserAPI.swift @@ -0,0 +1,409 @@ +// +// UserAPI.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech + +import Foundation +import Combine +import OpenAPITransport + + +open class UserAPI { + private let transport: OpenAPITransport + public var encoder: JSONEncoder = { + let encoder = JSONEncoder() + encoder.dateEncodingStrategy = .formatted(OpenISO8601DateFormatter()) + return encoder + }() + public var decoder: JSONDecoder = { + let decoder = JSONDecoder() + decoder.dateDecodingStrategy = .formatted(OpenISO8601DateFormatter()) + return decoder + }() + public var baseURL = URL(string: "http://petstore.swagger.io/v2") + + public init(_ transport: OpenAPITransport) { + self.transport = transport + } + + + /// Create user + /// - POST /user + /// - This can only be done by the logged in user. + /// - API Key: + /// - type: apiKey api_key + /// - name: api_key + /// - parameter user: (body) Created user object + /// - returns: AnyPublisher + open func createUser(user: User) -> AnyPublisher { + Deferred { + Result { + guard let baseURL = self.transport.baseURL ?? self.baseURL else { + throw OpenAPITransportError.badURLError() + } + let path = "/user" + let url = baseURL.appendingPathComponent(path) + let components = URLComponents(url: url, resolvingAgainstBaseURL: false) + guard let requestURL = components?.url else { + throw OpenAPITransportError.badURLError() + } + var request = URLRequest(url: requestURL) + request.httpMethod = "POST" + request.httpBody = try self.encoder.encode(user) + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + return request + }.publisher + }.flatMap { request -> AnyPublisher in + let securitySchemes: [SecurityScheme] = [] + return self.transport.send(request: request, securitySchemes: securitySchemes) + .tryMap { response in + return () + } + .eraseToAnyPublisher() + }.eraseToAnyPublisher() + } + + + /// Creates list of users with given input array + /// - POST /user/createWithArray + /// - + /// - API Key: + /// - type: apiKey api_key + /// - name: api_key + /// - parameter user: (body) List of user object + /// - returns: AnyPublisher + open func createUsersWithArrayInput(user: [User]) -> AnyPublisher { + Deferred { + Result { + guard let baseURL = self.transport.baseURL ?? self.baseURL else { + throw OpenAPITransportError.badURLError() + } + let path = "/user/createWithArray" + let url = baseURL.appendingPathComponent(path) + let components = URLComponents(url: url, resolvingAgainstBaseURL: false) + guard let requestURL = components?.url else { + throw OpenAPITransportError.badURLError() + } + var request = URLRequest(url: requestURL) + request.httpMethod = "POST" + request.httpBody = try self.encoder.encode(user) + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + return request + }.publisher + }.flatMap { request -> AnyPublisher in + let securitySchemes: [SecurityScheme] = [] + return self.transport.send(request: request, securitySchemes: securitySchemes) + .tryMap { response in + return () + } + .eraseToAnyPublisher() + }.eraseToAnyPublisher() + } + + + /// Creates list of users with given input array + /// - POST /user/createWithList + /// - + /// - API Key: + /// - type: apiKey api_key + /// - name: api_key + /// - parameter user: (body) List of user object + /// - returns: AnyPublisher + open func createUsersWithListInput(user: [User]) -> AnyPublisher { + Deferred { + Result { + guard let baseURL = self.transport.baseURL ?? self.baseURL else { + throw OpenAPITransportError.badURLError() + } + let path = "/user/createWithList" + let url = baseURL.appendingPathComponent(path) + let components = URLComponents(url: url, resolvingAgainstBaseURL: false) + guard let requestURL = components?.url else { + throw OpenAPITransportError.badURLError() + } + var request = URLRequest(url: requestURL) + request.httpMethod = "POST" + request.httpBody = try self.encoder.encode(user) + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + return request + }.publisher + }.flatMap { request -> AnyPublisher in + let securitySchemes: [SecurityScheme] = [] + return self.transport.send(request: request, securitySchemes: securitySchemes) + .tryMap { response in + return () + } + .eraseToAnyPublisher() + }.eraseToAnyPublisher() + } + + public enum DeleteUserError: Error, CustomStringConvertible { + // Invalid username supplied + case code400Error + // User not found + case code404Error + + public var description: String { + switch self { + case .code400Error: + return "DeleteUserError: Invalid username supplied" + case .code404Error: + return "DeleteUserError: User not found" + } + } + } + + /// Delete user + /// - DELETE /user/{username} + /// - This can only be done by the logged in user. + /// - API Key: + /// - type: apiKey api_key + /// - name: api_key + /// - parameter username: (path) The name that needs to be deleted + /// - returns: AnyPublisher + open func deleteUser(username: String) -> AnyPublisher { + Deferred { + Result { + guard let baseURL = self.transport.baseURL ?? self.baseURL else { + throw OpenAPITransportError.badURLError() + } + var path = "/user/{username}" + path = path.replacingOccurrences(of: "{username}", with: username) + let url = baseURL.appendingPathComponent(path) + let components = URLComponents(url: url, resolvingAgainstBaseURL: false) + guard let requestURL = components?.url else { + throw OpenAPITransportError.badURLError() + } + var request = URLRequest(url: requestURL) + request.httpMethod = "DELETE" + return request + }.publisher + }.flatMap { request -> AnyPublisher in + let securitySchemes: [SecurityScheme] = [] + return self.transport.send(request: request, securitySchemes: securitySchemes) + .mapError { transportError -> Error in + if transportError.statusCode == 400 { + return DeleteUserError.code400Error + } + if transportError.statusCode == 404 { + return DeleteUserError.code404Error + } + return transportError + } + .tryMap { response in + return () + } + .eraseToAnyPublisher() + }.eraseToAnyPublisher() + } + + public enum GetUserByNameError: Error, CustomStringConvertible { + // Invalid username supplied + case code400Error + // User not found + case code404Error + + public var description: String { + switch self { + case .code400Error: + return "GetUserByNameError: Invalid username supplied" + case .code404Error: + return "GetUserByNameError: User not found" + } + } + } + + /// Get user by user name + /// - GET /user/{username} + /// - + /// - parameter username: (path) The name that needs to be fetched. Use user1 for testing. + /// - returns: AnyPublisher + open func getUserByName(username: String) -> AnyPublisher { + Deferred { + Result { + guard let baseURL = self.transport.baseURL ?? self.baseURL else { + throw OpenAPITransportError.badURLError() + } + var path = "/user/{username}" + path = path.replacingOccurrences(of: "{username}", with: username) + let url = baseURL.appendingPathComponent(path) + let components = URLComponents(url: url, resolvingAgainstBaseURL: false) + guard let requestURL = components?.url else { + throw OpenAPITransportError.badURLError() + } + var request = URLRequest(url: requestURL) + request.httpMethod = "GET" + return request + }.publisher + }.flatMap { request -> AnyPublisher in + let securitySchemes: [SecurityScheme] = [] + return self.transport.send(request: request, securitySchemes: securitySchemes) + .mapError { transportError -> Error in + if transportError.statusCode == 400 { + return GetUserByNameError.code400Error + } + if transportError.statusCode == 404 { + return GetUserByNameError.code404Error + } + return transportError + } + .tryMap { response in + try self.decoder.decode(User.self, from: response.data) + } + .eraseToAnyPublisher() + }.eraseToAnyPublisher() + } + + public enum LoginUserError: Error, CustomStringConvertible { + // Invalid username/password supplied + case code400Error + + public var description: String { + switch self { + case .code400Error: + return "LoginUserError: Invalid username/password supplied" + } + } + } + + /// Logs user into the system + /// - GET /user/login + /// - + /// - responseHeaders: [Set-Cookie(String), X-Rate-Limit(Int), X-Expires-After(Date)] + /// - parameter username: (query) The user name for login + /// - parameter password: (query) The password for login in clear text + /// - returns: AnyPublisher + open func loginUser(username: String, password: String) -> AnyPublisher { + Deferred { + Result { + guard let baseURL = self.transport.baseURL ?? self.baseURL else { + throw OpenAPITransportError.badURLError() + } + let path = "/user/login" + let url = baseURL.appendingPathComponent(path) + var components = URLComponents(url: url, resolvingAgainstBaseURL: false) + var queryItems: [URLQueryItem] = [] + queryItems.append(URLQueryItem(name: "username", value: username)) + queryItems.append(URLQueryItem(name: "password", value: password)) + components?.queryItems = queryItems + guard let requestURL = components?.url else { + throw OpenAPITransportError.badURLError() + } + var request = URLRequest(url: requestURL) + request.httpMethod = "GET" + return request + }.publisher + }.flatMap { request -> AnyPublisher in + let securitySchemes: [SecurityScheme] = [] + return self.transport.send(request: request, securitySchemes: securitySchemes) + .mapError { transportError -> Error in + if transportError.statusCode == 400 { + return LoginUserError.code400Error + } + return transportError + } + .tryMap { response in + try self.decoder.decode(String.self, from: response.data) + } + .eraseToAnyPublisher() + }.eraseToAnyPublisher() + } + + + /// Logs out current logged in user session + /// - GET /user/logout + /// - + /// - API Key: + /// - type: apiKey api_key + /// - name: api_key + /// - returns: AnyPublisher + open func logoutUser() -> AnyPublisher { + Deferred { + Result { + guard let baseURL = self.transport.baseURL ?? self.baseURL else { + throw OpenAPITransportError.badURLError() + } + let path = "/user/logout" + let url = baseURL.appendingPathComponent(path) + let components = URLComponents(url: url, resolvingAgainstBaseURL: false) + guard let requestURL = components?.url else { + throw OpenAPITransportError.badURLError() + } + var request = URLRequest(url: requestURL) + request.httpMethod = "GET" + return request + }.publisher + }.flatMap { request -> AnyPublisher in + let securitySchemes: [SecurityScheme] = [] + return self.transport.send(request: request, securitySchemes: securitySchemes) + .tryMap { response in + return () + } + .eraseToAnyPublisher() + }.eraseToAnyPublisher() + } + + public enum UpdateUserError: Error, CustomStringConvertible { + // Invalid user supplied + case code400Error + // User not found + case code404Error + + public var description: String { + switch self { + case .code400Error: + return "UpdateUserError: Invalid user supplied" + case .code404Error: + return "UpdateUserError: User not found" + } + } + } + + /// Updated user + /// - PUT /user/{username} + /// - This can only be done by the logged in user. + /// - API Key: + /// - type: apiKey api_key + /// - name: api_key + /// - parameter username: (path) name that need to be deleted + /// - parameter user: (body) Updated user object + /// - returns: AnyPublisher + open func updateUser(username: String, user: User) -> AnyPublisher { + Deferred { + Result { + guard let baseURL = self.transport.baseURL ?? self.baseURL else { + throw OpenAPITransportError.badURLError() + } + var path = "/user/{username}" + path = path.replacingOccurrences(of: "{username}", with: username) + let url = baseURL.appendingPathComponent(path) + let components = URLComponents(url: url, resolvingAgainstBaseURL: false) + guard let requestURL = components?.url else { + throw OpenAPITransportError.badURLError() + } + var request = URLRequest(url: requestURL) + request.httpMethod = "PUT" + request.httpBody = try self.encoder.encode(user) + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + return request + }.publisher + }.flatMap { request -> AnyPublisher in + let securitySchemes: [SecurityScheme] = [] + return self.transport.send(request: request, securitySchemes: securitySchemes) + .mapError { transportError -> Error in + if transportError.statusCode == 400 { + return UpdateUserError.code400Error + } + if transportError.statusCode == 404 { + return UpdateUserError.code404Error + } + return transportError + } + .tryMap { response in + return () + } + .eraseToAnyPublisher() + }.eraseToAnyPublisher() + } +} diff --git a/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/Models/ApiResponse.swift b/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/Models/ApiResponse.swift new file mode 100644 index 000000000000..6aca7a2cca29 --- /dev/null +++ b/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/Models/ApiResponse.swift @@ -0,0 +1,21 @@ +// +// ApiResponse.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + +/// Describes the result of uploading an image resource +public struct ApiResponse: Codable { + public var code: Int? + public var type: String? + public var message: String? + + public init(code: Int? = nil, type: String? = nil, message: String? = nil) { + self.code = code + self.type = type + self.message = message + } +} diff --git a/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/Models/Category.swift b/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/Models/Category.swift new file mode 100644 index 000000000000..23177663e242 --- /dev/null +++ b/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/Models/Category.swift @@ -0,0 +1,19 @@ +// +// Category.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + +/// A category for a pet +public struct Category: Codable { + public var id: Int64? + public var name: String? + + public init(id: Int64? = nil, name: String? = nil) { + self.id = id + self.name = name + } +} diff --git a/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/Models/Order.swift b/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/Models/Order.swift new file mode 100644 index 000000000000..9a9b4e2bf3b1 --- /dev/null +++ b/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/Models/Order.swift @@ -0,0 +1,33 @@ +// +// Order.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + +/// An order for a pets from the pet store +public struct Order: Codable { + public enum Status: String, Codable, CaseIterable { + case placed = "placed" + case approved = "approved" + case delivered = "delivered" + } + public var id: Int64? + public var petId: Int64? + public var quantity: Int? + public var shipDate: Date? + /// Order Status + public var status: Status? + public var complete: Bool? = false + + public init(id: Int64? = nil, petId: Int64? = nil, quantity: Int? = nil, shipDate: Date? = nil, status: Status? = nil, complete: Bool? = false) { + self.id = id + self.petId = petId + self.quantity = quantity + self.shipDate = shipDate + self.status = status + self.complete = complete + } +} diff --git a/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/Models/Pet.swift b/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/Models/Pet.swift new file mode 100644 index 000000000000..3a3833c751e6 --- /dev/null +++ b/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/Models/Pet.swift @@ -0,0 +1,33 @@ +// +// Pet.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + +/// A pet for sale in the pet store +public struct Pet: Codable { + public enum Status: String, Codable, CaseIterable { + case available = "available" + case pending = "pending" + case sold = "sold" + } + public var id: Int64? + public var category: Category? + public var name: String + public var photoUrls: [String] + public var tags: [Tag]? + /// pet status in the store + public var status: Status? + + public init(id: Int64? = nil, category: Category? = nil, name: String, photoUrls: [String], tags: [Tag]? = nil, status: Status? = nil) { + self.id = id + self.category = category + self.name = name + self.photoUrls = photoUrls + self.tags = tags + self.status = status + } +} diff --git a/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/Models/Tag.swift b/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/Models/Tag.swift new file mode 100644 index 000000000000..e3e878a4f703 --- /dev/null +++ b/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/Models/Tag.swift @@ -0,0 +1,19 @@ +// +// Tag.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + +/// A tag for a pet +public struct Tag: Codable { + public var id: Int64? + public var name: String? + + public init(id: Int64? = nil, name: String? = nil) { + self.id = id + self.name = name + } +} diff --git a/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/Models/User.swift b/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/Models/User.swift new file mode 100644 index 000000000000..679ca0d472b2 --- /dev/null +++ b/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/Models/User.swift @@ -0,0 +1,32 @@ +// +// User.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + +/// A User who is purchasing from the pet store +public struct User: Codable { + public var id: Int64? + public var username: String? + public var firstName: String? + public var lastName: String? + public var email: String? + public var password: String? + public var phone: String? + /// User Status + public var userStatus: Int? + + public init(id: Int64? = nil, username: String? = nil, firstName: String? = nil, lastName: String? = nil, email: String? = nil, password: String? = nil, phone: String? = nil, userStatus: Int? = nil) { + self.id = id + self.username = username + self.firstName = firstName + self.lastName = lastName + self.email = email + self.password = password + self.phone = phone + self.userStatus = userStatus + } +} diff --git a/samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/Private/OpenISO8601DateFormatter.swift b/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/Private/OpenISO8601DateFormatter.swift similarity index 95% rename from samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/Private/OpenISO8601DateFormatter.swift rename to samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/Private/OpenISO8601DateFormatter.swift index aeb29f3767db..f6a6fc82b733 100644 --- a/samples/client/petstore/swift-alt/client/PetstoreOpenAPI/Sources/Private/OpenISO8601DateFormatter.swift +++ b/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/Private/OpenISO8601DateFormatter.swift @@ -25,6 +25,8 @@ class OpenISO8601DateFormatter: DateFormatter { dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ" } + static var shared = OpenISO8601DateFormatter() + override init() { super.init() setup() diff --git a/samples/client/petstore/swift-alt/tests/Package.swift b/samples/client/petstore/swift-combine/tests/Package.swift similarity index 100% rename from samples/client/petstore/swift-alt/tests/Package.swift rename to samples/client/petstore/swift-combine/tests/Package.swift diff --git a/samples/client/petstore/swift-alt/tests/Sources/TestClientTests/PetAPITests.swift b/samples/client/petstore/swift-combine/tests/Sources/TestClientTests/PetAPITests.swift similarity index 100% rename from samples/client/petstore/swift-alt/tests/Sources/TestClientTests/PetAPITests.swift rename to samples/client/petstore/swift-combine/tests/Sources/TestClientTests/PetAPITests.swift diff --git a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/model/dog.dart b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/model/dog.dart index 8d3d3e27a17f..484567e74d78 100644 --- a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/model/dog.dart +++ b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/model/dog.dart @@ -51,6 +51,11 @@ class _$DogSerializer implements PrimitiveSerializer { specifiedType: const FullType(String), ); } + yield r'className'; + yield serializers.serialize( + object.className, + specifiedType: const FullType(String), + ); if (object.breed != null) { yield r'breed'; yield serializers.serialize( @@ -93,6 +98,13 @@ class _$DogSerializer implements PrimitiveSerializer { ) as String; result.color = valueDes; break; + case r'className': + final valueDes = serializers.deserialize( + value, + specifiedType: const FullType(String), + ) as String; + result.className = valueDes; + break; case r'breed': final valueDes = serializers.deserialize( value, From 8ec749163a18c2caa36ec31cd15032aac4920efb Mon Sep 17 00:00:00 2001 From: Anton Davydov Date: Mon, 12 Jun 2023 20:20:02 +0300 Subject: [PATCH 30/33] swift-combine: updated transport --- docs/generators/swift-combine.md | 2 +- .../languages/SwiftCombineClientCodegen.java | 1 - .../swift-combine/OpenAPITransport.mustache | 296 +++++++++--------- .../main/resources/swift-combine/api.mustache | 3 +- .../resources/swift-combine/toData.mustache | 2 +- .../Sources/OpenAPITransport.swift | 296 +++++++++--------- .../PetstoreOpenAPI/Sources/APIs/PetAPI.swift | 24 +- .../Sources/APIs/StoreAPI.swift | 12 +- .../Sources/APIs/UserAPI.swift | 24 +- .../lib/src/model/dog.dart | 12 - 10 files changed, 327 insertions(+), 345 deletions(-) diff --git a/docs/generators/swift-combine.md b/docs/generators/swift-combine.md index 4b2a58f7ca75..69c993b8fc78 100644 --- a/docs/generators/swift-combine.md +++ b/docs/generators/swift-combine.md @@ -311,7 +311,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl | ---- | --------- | ---------- | |BasicAuth|✓|OAS2,OAS3 |ApiKey|✓|OAS2,OAS3 -|OpenIDConnect|✓|OAS3 +|OpenIDConnect|✗|OAS3 |BearerToken|✓|OAS3 |OAuth2_Implicit|✓|OAS2,OAS3 |OAuth2_Password|✓|OAS2,OAS3 diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftCombineClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftCombineClientCodegen.java index 3c25785c07d9..016498ede6b0 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftCombineClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SwiftCombineClientCodegen.java @@ -800,7 +800,6 @@ public void postProcess() { System.out.println("################################################################################"); System.out.println("# Thanks for using OpenAPI Generator. #"); System.out.println("# swift combine generator is contributed by @dydus0x14 and @ptiz. #"); - System.out.println("# swift combine generator v0.23.0 #"); System.out.println("################################################################################"); } diff --git a/modules/openapi-generator/src/main/resources/swift-combine/OpenAPITransport.mustache b/modules/openapi-generator/src/main/resources/swift-combine/OpenAPITransport.mustache index 99dc41cc125e..cd2e8195e944 100644 --- a/modules/openapi-generator/src/main/resources/swift-combine/OpenAPITransport.mustache +++ b/modules/openapi-generator/src/main/resources/swift-combine/OpenAPITransport.mustache @@ -6,70 +6,12 @@ import Foundation import Combine -// MARK: - Open API Scheme - -public enum SecurityScheme { - // Security schemes not supported yet https://swagger.io/docs/specification/authentication/ -} - -// MARK: - Policy - -/// Policy to define whether response is successful or requires authentication -public protocol URLResponsePolicy { - func defineState(for request: URLRequest, output: URLSession.DataTaskPublisher.Output) -> AnyPublisher -} - -public enum URLResponseState { - // Return success to client - case success - // Return error to client - case failure - // Repeat request - case retry -} - -final class DefaultURLResponsePolicy: URLResponsePolicy { - func defineState(for request: URLRequest, output: URLSession.DataTaskPublisher.Output) -> AnyPublisher { - let state: URLResponseState - switch (output.response as? HTTPURLResponse)?.statusCode { - case .some(200...299): state = .success - default: state = .failure - } - return Just(state).eraseToAnyPublisher() - } -} - -/// Define how to customize URL request before network call -public protocol URLRequestProcessor { - /// Customize request before performing. Add headers or encrypt body for example. - func enrich(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher - /// Customize response before handling. Decrypt body for example. - func decode(output: URLSession.DataTaskPublisher.Output) -> AnyPublisher -} - -final class DefaultURLRequestProcessor: URLRequestProcessor { - func enrich(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher { - Just(request) - .setFailureType(to: OpenAPITransportError.self) - .eraseToAnyPublisher() - } - - func decode(output: URLSession.DataTaskPublisher.Output) -> AnyPublisher { - Just(output) - .setFailureType(to: OpenAPITransportError.self) - .eraseToAnyPublisher() - } -} - // MARK: - OpenAPITransport public protocol OpenAPITransport: AnyObject { var baseURL: URL? { get } - func send( - request: URLRequest, - securitySchemes: [SecurityScheme] - ) -> AnyPublisher + func send(request: URLRequest) -> AnyPublisher func cancelAll() } @@ -88,9 +30,9 @@ public struct OpenAPITransportError: Error, CustomStringConvertible, LocalizedEr public let statusCode: Int public let description: String public let errorDescription: String? - // It might be source network error + /// It might be source network error public let nestedError: Error? - // Data may contain additional reason info (like json payload) + /// Data may contain additional reason info (like json payload) public let data: Data public init( @@ -116,7 +58,152 @@ public struct OpenAPITransportError: Error, CustomStringConvertible, LocalizedEr } } -// Custom transport errors. It begins with 6.. not to conflict with HTTP codes (it begins with 5..) +// MARK: - Policy + +/// Policy to define whether response is successful or requires authentication +public protocol ResponsePolicy { + func defineState(for request: URLRequest, output: URLSession.DataTaskPublisher.Output) -> AnyPublisher +} + +public enum ResponseState { + /// Return success to client + case success + /// Return error to client + case failure + /// Repeat request + case retry +} + +// MARK: - Interceptor + +/// Define how to customize URL request before network call +public protocol Interceptor { + /// Customize request before performing. Add headers or encrypt body for example. + func intercept(request: URLRequest) -> AnyPublisher + + /// Customize response before handling. Decrypt body for example. + func intercept(output: URLSession.DataTaskPublisher.Output) -> AnyPublisher +} + +// MARK: - Transport delegate + +public protocol OpenAPITransportDelegate: AnyObject { + func willStart(request: URLRequest) + + func didFinish(request: URLRequest, response: HTTPURLResponse?, data: Data) + + func didFinish(request: URLRequest, error: Error) +} + +// MARK: - Implementation + +open class URLSessionOpenAPITransport: OpenAPITransport { + public struct Config { + public var baseURL: URL? + public var session: URLSession + public var processor: Interceptor + public var policy: ResponsePolicy + public weak var delegate: OpenAPITransportDelegate? + + public init( + baseURL: URL? = nil, + session: URLSession = .shared, + processor: Interceptor = DefaultInterceptor(), + policy: ResponsePolicy = DefaultResponsePolicy(), + delegate: OpenAPITransportDelegate? = nil + ) { + self.baseURL = baseURL + self.session = session + self.processor = processor + self.policy = policy + self.delegate = delegate + } + } + + private var cancellable = Set() + public var config: Config + public var baseURL: URL? { config.baseURL } + + public init(config: Config = .init()) { + self.config = config + } + + open func send(request: URLRequest) -> AnyPublisher { + config.processor + // Add custom headers or refresh token if needed + .intercept(request: request) + .flatMap { request -> AnyPublisher in + self.config.delegate?.willStart(request: request) + // Perform network call + return self.config.session.dataTaskPublisher(for: request) + .mapError { + self.config.delegate?.didFinish(request: request, error: $0) + return OpenAPITransportError(statusCode: $0.code.rawValue, description: "Network call finished fails") + } + .flatMap { output in + self.config.processor.intercept(output: output) + } + .flatMap { output -> AnyPublisher in + let response = output.response as? HTTPURLResponse + self.config.delegate?.didFinish(request: request, response: response, data: output.data) + return self.config.policy.defineState(for: request, output: output) + .setFailureType(to: OpenAPITransportError.self) + .flatMap { state -> AnyPublisher in + switch state { + case .success: + let transportResponse = OpenAPITransportResponse(data: output.data, statusCode: 200) + return Result.success(transportResponse).publisher.eraseToAnyPublisher() + case .retry: + return Fail(error: OpenAPITransportError.retryError).eraseToAnyPublisher() + case .failure: + let code = response?.statusCode ?? OpenAPITransportError.noResponseCode + let transportError = OpenAPITransportError(statusCode: code, data: output.data) + return Fail(error: transportError).eraseToAnyPublisher() + } + }.eraseToAnyPublisher() + } + .eraseToAnyPublisher() + } + .retry(times: 2) { error -> Bool in + return error.statusCode == OpenAPITransportError.retryError.statusCode + }.eraseToAnyPublisher() + } + + open func cancelAll() { + cancellable.removeAll() + } +} + +public final class DefaultInterceptor: Interceptor { + public init() {} + + public func intercept(request: URLRequest) -> AnyPublisher { + Just(request) + .setFailureType(to: OpenAPITransportError.self) + .eraseToAnyPublisher() + } + + public func intercept(output: URLSession.DataTaskPublisher.Output) -> AnyPublisher { + Just(output) + .setFailureType(to: OpenAPITransportError.self) + .eraseToAnyPublisher() + } +} + +public final class DefaultResponsePolicy: ResponsePolicy { + public init() {} + + public func defineState(for request: URLRequest, output: URLSession.DataTaskPublisher.Output) -> AnyPublisher { + let state: ResponseState + switch (output.response as? HTTPURLResponse)?.statusCode { + case .some(200...299): state = .success + default: state = .failure + } + return Just(state).eraseToAnyPublisher() + } +} + +/// Custom transport errors. It begins with 6.. not to conflict with HTTP codes public extension OpenAPITransportError { static let incorrectAuthenticationCode = 600 static func incorrectAuthenticationError(_ nestedError: Error? = nil) -> OpenAPITransportError { @@ -187,88 +274,9 @@ public extension OpenAPITransportError { static let retryError = OpenAPITransportError(statusCode: OpenAPITransportError.retryErrorCode) } -public protocol URLSessionOpenAPITransportDelegate: AnyObject { - func willStart(request: URLRequest) - func didFinish(request: URLRequest, response: HTTPURLResponse?, data: Data) - func didFinish(request: URLRequest, error: Error) -} - -open class URLSessionOpenAPITransport: OpenAPITransport { - private var cancellable = Set() - public var config: Config - public var baseURL: URL? { config.baseURL } - - public init(config: Config = .init()) { - self.config = config - } - - open func send( - request: URLRequest, - securitySchemes: [SecurityScheme] - ) -> AnyPublisher { - - config.processor - // Add custom headers or refresh token if needed - .enrich(request: request, securitySchemes: securitySchemes) - .flatMap { request -> AnyPublisher in - self.config.delegate?.willStart(request: request) - // Perform network call - return self.config.session.dataTaskPublisher(for: request) - .mapError { - self.config.delegate?.didFinish(request: request, error: $0) - return OpenAPITransportError(statusCode: $0.code.rawValue, description: "Network call finished fails") - } - .flatMap { output in - self.config.processor.decode(output: output) - } - .flatMap { output -> AnyPublisher in - let response = output.response as? HTTPURLResponse - self.config.delegate?.didFinish(request: request, response: response, data: output.data) - return self.config.policy.defineState(for: request, output: output) - .setFailureType(to: OpenAPITransportError.self) - .flatMap { state -> AnyPublisher in - switch state { - case .success: - let transportResponse = OpenAPITransportResponse(data: output.data, statusCode: 200) - return Result.success(transportResponse).publisher.eraseToAnyPublisher() - case .retry: - return Fail(error: OpenAPITransportError.retryError).eraseToAnyPublisher() - case .failure: - let code = response?.statusCode ?? OpenAPITransportError.noResponseCode - let transportError = OpenAPITransportError(statusCode: code, data: output.data) - return Fail(error: transportError).eraseToAnyPublisher() - } - }.eraseToAnyPublisher() - } - .eraseToAnyPublisher() - } - .retry(times: 2) { error -> Bool in - return error.statusCode == OpenAPITransportError.retryError.statusCode - }.eraseToAnyPublisher() - } - - open func cancelAll() { - cancellable.removeAll() - } -} - -public extension URLSessionOpenAPITransport { - struct Config { - public var baseURL: URL? = nil - public var session: URLSession = .shared - public var processor: URLRequestProcessor = DefaultURLRequestProcessor() - public var policy: URLResponsePolicy = DefaultURLResponsePolicy() - public weak var delegate: URLSessionOpenAPITransportDelegate? - - public init() {} - - public init(baseURL: URL) { - self.baseURL = baseURL - } - } -} +// MARK: - Private -fileprivate extension Publishers { +private extension Publishers { struct RetryIf: Publisher { typealias Output = P.Output typealias Failure = P.Failure @@ -291,7 +299,7 @@ fileprivate extension Publishers { } } -fileprivate extension Publisher { +private extension Publisher { func retry(times: Int, if condition: @escaping (Failure) -> Bool) -> Publishers.RetryIf { Publishers.RetryIf(publisher: self, times: times, condition: condition) } diff --git a/modules/openapi-generator/src/main/resources/swift-combine/api.mustache b/modules/openapi-generator/src/main/resources/swift-combine/api.mustache index 1e1b981773f2..dc250bc594a2 100644 --- a/modules/openapi-generator/src/main/resources/swift-combine/api.mustache +++ b/modules/openapi-generator/src/main/resources/swift-combine/api.mustache @@ -161,8 +161,7 @@ open class {{classname}} { return request }.publisher }.flatMap { request -> AnyPublisher<{{{returnType}}}{{^returnType}}Void{{/returnType}}, Error> in - let securitySchemes: [SecurityScheme] = [{{#authMethods}}{{#isBasicBearer}}.bearer{{/isBasicBearer}}{{/authMethods}}] - return self.transport.send(request: request, securitySchemes: securitySchemes) + return self.transport.send(request: request) {{#vendorExtensions.x-swift-custom-error-type}} .mapError { transportError -> Error in {{#responses}} diff --git a/modules/openapi-generator/src/main/resources/swift-combine/toData.mustache b/modules/openapi-generator/src/main/resources/swift-combine/toData.mustache index 0456e7c0e352..a328dca35585 100644 --- a/modules/openapi-generator/src/main/resources/swift-combine/toData.mustache +++ b/modules/openapi-generator/src/main/resources/swift-combine/toData.mustache @@ -1 +1 @@ -{{#isBinary}}{{#mapFileBinaryToData}}{{{paramName}}}{{/mapFileBinaryToData}}{{^mapFileBinaryToData}}try Data(contentsOf: {{{paramName}}}){{/mapFileBinaryToData}}{{/isBinary}}{{#isModel}}try self.encoder.encode({{paramName}}){{/isModel}}{{#isByteArray}}{{paramName}}.base64EncodedData(){{/isByteArray}}{{#isString}}{{paramName}}.data(using: .utf8) ?? Data(){{/isString}} \ No newline at end of file +{{#isBinary}}{{#mapFileBinaryToData}}{{{paramName}}}{{/mapFileBinaryToData}}{{^mapFileBinaryToData}}try Data(contentsOf: {{{paramName}}}){{/mapFileBinaryToData}}{{/isBinary}}{{#isModel}}try self.encoder.encode({{paramName}}){{/isModel}}{{#isByteArray}}{{paramName}}.base64EncodedData(){{/isByteArray}}{{#isString}}{{paramName}}{{#isEnum}}.rawValue{{/isEnum}}.data(using: .utf8) ?? Data(){{/isString}} \ No newline at end of file diff --git a/samples/client/petstore/swift-combine/client/OpenAPITransport/Sources/OpenAPITransport.swift b/samples/client/petstore/swift-combine/client/OpenAPITransport/Sources/OpenAPITransport.swift index 99dc41cc125e..cd2e8195e944 100644 --- a/samples/client/petstore/swift-combine/client/OpenAPITransport/Sources/OpenAPITransport.swift +++ b/samples/client/petstore/swift-combine/client/OpenAPITransport/Sources/OpenAPITransport.swift @@ -6,70 +6,12 @@ import Foundation import Combine -// MARK: - Open API Scheme - -public enum SecurityScheme { - // Security schemes not supported yet https://swagger.io/docs/specification/authentication/ -} - -// MARK: - Policy - -/// Policy to define whether response is successful or requires authentication -public protocol URLResponsePolicy { - func defineState(for request: URLRequest, output: URLSession.DataTaskPublisher.Output) -> AnyPublisher -} - -public enum URLResponseState { - // Return success to client - case success - // Return error to client - case failure - // Repeat request - case retry -} - -final class DefaultURLResponsePolicy: URLResponsePolicy { - func defineState(for request: URLRequest, output: URLSession.DataTaskPublisher.Output) -> AnyPublisher { - let state: URLResponseState - switch (output.response as? HTTPURLResponse)?.statusCode { - case .some(200...299): state = .success - default: state = .failure - } - return Just(state).eraseToAnyPublisher() - } -} - -/// Define how to customize URL request before network call -public protocol URLRequestProcessor { - /// Customize request before performing. Add headers or encrypt body for example. - func enrich(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher - /// Customize response before handling. Decrypt body for example. - func decode(output: URLSession.DataTaskPublisher.Output) -> AnyPublisher -} - -final class DefaultURLRequestProcessor: URLRequestProcessor { - func enrich(request: URLRequest, securitySchemes: [SecurityScheme]) -> AnyPublisher { - Just(request) - .setFailureType(to: OpenAPITransportError.self) - .eraseToAnyPublisher() - } - - func decode(output: URLSession.DataTaskPublisher.Output) -> AnyPublisher { - Just(output) - .setFailureType(to: OpenAPITransportError.self) - .eraseToAnyPublisher() - } -} - // MARK: - OpenAPITransport public protocol OpenAPITransport: AnyObject { var baseURL: URL? { get } - func send( - request: URLRequest, - securitySchemes: [SecurityScheme] - ) -> AnyPublisher + func send(request: URLRequest) -> AnyPublisher func cancelAll() } @@ -88,9 +30,9 @@ public struct OpenAPITransportError: Error, CustomStringConvertible, LocalizedEr public let statusCode: Int public let description: String public let errorDescription: String? - // It might be source network error + /// It might be source network error public let nestedError: Error? - // Data may contain additional reason info (like json payload) + /// Data may contain additional reason info (like json payload) public let data: Data public init( @@ -116,7 +58,152 @@ public struct OpenAPITransportError: Error, CustomStringConvertible, LocalizedEr } } -// Custom transport errors. It begins with 6.. not to conflict with HTTP codes (it begins with 5..) +// MARK: - Policy + +/// Policy to define whether response is successful or requires authentication +public protocol ResponsePolicy { + func defineState(for request: URLRequest, output: URLSession.DataTaskPublisher.Output) -> AnyPublisher +} + +public enum ResponseState { + /// Return success to client + case success + /// Return error to client + case failure + /// Repeat request + case retry +} + +// MARK: - Interceptor + +/// Define how to customize URL request before network call +public protocol Interceptor { + /// Customize request before performing. Add headers or encrypt body for example. + func intercept(request: URLRequest) -> AnyPublisher + + /// Customize response before handling. Decrypt body for example. + func intercept(output: URLSession.DataTaskPublisher.Output) -> AnyPublisher +} + +// MARK: - Transport delegate + +public protocol OpenAPITransportDelegate: AnyObject { + func willStart(request: URLRequest) + + func didFinish(request: URLRequest, response: HTTPURLResponse?, data: Data) + + func didFinish(request: URLRequest, error: Error) +} + +// MARK: - Implementation + +open class URLSessionOpenAPITransport: OpenAPITransport { + public struct Config { + public var baseURL: URL? + public var session: URLSession + public var processor: Interceptor + public var policy: ResponsePolicy + public weak var delegate: OpenAPITransportDelegate? + + public init( + baseURL: URL? = nil, + session: URLSession = .shared, + processor: Interceptor = DefaultInterceptor(), + policy: ResponsePolicy = DefaultResponsePolicy(), + delegate: OpenAPITransportDelegate? = nil + ) { + self.baseURL = baseURL + self.session = session + self.processor = processor + self.policy = policy + self.delegate = delegate + } + } + + private var cancellable = Set() + public var config: Config + public var baseURL: URL? { config.baseURL } + + public init(config: Config = .init()) { + self.config = config + } + + open func send(request: URLRequest) -> AnyPublisher { + config.processor + // Add custom headers or refresh token if needed + .intercept(request: request) + .flatMap { request -> AnyPublisher in + self.config.delegate?.willStart(request: request) + // Perform network call + return self.config.session.dataTaskPublisher(for: request) + .mapError { + self.config.delegate?.didFinish(request: request, error: $0) + return OpenAPITransportError(statusCode: $0.code.rawValue, description: "Network call finished fails") + } + .flatMap { output in + self.config.processor.intercept(output: output) + } + .flatMap { output -> AnyPublisher in + let response = output.response as? HTTPURLResponse + self.config.delegate?.didFinish(request: request, response: response, data: output.data) + return self.config.policy.defineState(for: request, output: output) + .setFailureType(to: OpenAPITransportError.self) + .flatMap { state -> AnyPublisher in + switch state { + case .success: + let transportResponse = OpenAPITransportResponse(data: output.data, statusCode: 200) + return Result.success(transportResponse).publisher.eraseToAnyPublisher() + case .retry: + return Fail(error: OpenAPITransportError.retryError).eraseToAnyPublisher() + case .failure: + let code = response?.statusCode ?? OpenAPITransportError.noResponseCode + let transportError = OpenAPITransportError(statusCode: code, data: output.data) + return Fail(error: transportError).eraseToAnyPublisher() + } + }.eraseToAnyPublisher() + } + .eraseToAnyPublisher() + } + .retry(times: 2) { error -> Bool in + return error.statusCode == OpenAPITransportError.retryError.statusCode + }.eraseToAnyPublisher() + } + + open func cancelAll() { + cancellable.removeAll() + } +} + +public final class DefaultInterceptor: Interceptor { + public init() {} + + public func intercept(request: URLRequest) -> AnyPublisher { + Just(request) + .setFailureType(to: OpenAPITransportError.self) + .eraseToAnyPublisher() + } + + public func intercept(output: URLSession.DataTaskPublisher.Output) -> AnyPublisher { + Just(output) + .setFailureType(to: OpenAPITransportError.self) + .eraseToAnyPublisher() + } +} + +public final class DefaultResponsePolicy: ResponsePolicy { + public init() {} + + public func defineState(for request: URLRequest, output: URLSession.DataTaskPublisher.Output) -> AnyPublisher { + let state: ResponseState + switch (output.response as? HTTPURLResponse)?.statusCode { + case .some(200...299): state = .success + default: state = .failure + } + return Just(state).eraseToAnyPublisher() + } +} + +/// Custom transport errors. It begins with 6.. not to conflict with HTTP codes public extension OpenAPITransportError { static let incorrectAuthenticationCode = 600 static func incorrectAuthenticationError(_ nestedError: Error? = nil) -> OpenAPITransportError { @@ -187,88 +274,9 @@ public extension OpenAPITransportError { static let retryError = OpenAPITransportError(statusCode: OpenAPITransportError.retryErrorCode) } -public protocol URLSessionOpenAPITransportDelegate: AnyObject { - func willStart(request: URLRequest) - func didFinish(request: URLRequest, response: HTTPURLResponse?, data: Data) - func didFinish(request: URLRequest, error: Error) -} - -open class URLSessionOpenAPITransport: OpenAPITransport { - private var cancellable = Set() - public var config: Config - public var baseURL: URL? { config.baseURL } - - public init(config: Config = .init()) { - self.config = config - } - - open func send( - request: URLRequest, - securitySchemes: [SecurityScheme] - ) -> AnyPublisher { - - config.processor - // Add custom headers or refresh token if needed - .enrich(request: request, securitySchemes: securitySchemes) - .flatMap { request -> AnyPublisher in - self.config.delegate?.willStart(request: request) - // Perform network call - return self.config.session.dataTaskPublisher(for: request) - .mapError { - self.config.delegate?.didFinish(request: request, error: $0) - return OpenAPITransportError(statusCode: $0.code.rawValue, description: "Network call finished fails") - } - .flatMap { output in - self.config.processor.decode(output: output) - } - .flatMap { output -> AnyPublisher in - let response = output.response as? HTTPURLResponse - self.config.delegate?.didFinish(request: request, response: response, data: output.data) - return self.config.policy.defineState(for: request, output: output) - .setFailureType(to: OpenAPITransportError.self) - .flatMap { state -> AnyPublisher in - switch state { - case .success: - let transportResponse = OpenAPITransportResponse(data: output.data, statusCode: 200) - return Result.success(transportResponse).publisher.eraseToAnyPublisher() - case .retry: - return Fail(error: OpenAPITransportError.retryError).eraseToAnyPublisher() - case .failure: - let code = response?.statusCode ?? OpenAPITransportError.noResponseCode - let transportError = OpenAPITransportError(statusCode: code, data: output.data) - return Fail(error: transportError).eraseToAnyPublisher() - } - }.eraseToAnyPublisher() - } - .eraseToAnyPublisher() - } - .retry(times: 2) { error -> Bool in - return error.statusCode == OpenAPITransportError.retryError.statusCode - }.eraseToAnyPublisher() - } - - open func cancelAll() { - cancellable.removeAll() - } -} - -public extension URLSessionOpenAPITransport { - struct Config { - public var baseURL: URL? = nil - public var session: URLSession = .shared - public var processor: URLRequestProcessor = DefaultURLRequestProcessor() - public var policy: URLResponsePolicy = DefaultURLResponsePolicy() - public weak var delegate: URLSessionOpenAPITransportDelegate? - - public init() {} - - public init(baseURL: URL) { - self.baseURL = baseURL - } - } -} +// MARK: - Private -fileprivate extension Publishers { +private extension Publishers { struct RetryIf: Publisher { typealias Output = P.Output typealias Failure = P.Failure @@ -291,7 +299,7 @@ fileprivate extension Publishers { } } -fileprivate extension Publisher { +private extension Publisher { func retry(times: Int, if condition: @escaping (Failure) -> Bool) -> Publishers.RetryIf { Publishers.RetryIf(publisher: self, times: times, condition: condition) } diff --git a/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/APIs/PetAPI.swift b/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/APIs/PetAPI.swift index 1082363610b3..d7678e37be1d 100644 --- a/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/APIs/PetAPI.swift +++ b/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/APIs/PetAPI.swift @@ -66,8 +66,7 @@ open class PetAPI { return request }.publisher }.flatMap { request -> AnyPublisher in - let securitySchemes: [SecurityScheme] = [] - return self.transport.send(request: request, securitySchemes: securitySchemes) + return self.transport.send(request: request) .mapError { transportError -> Error in if transportError.statusCode == 405 { return AddPetError.code405Error @@ -123,8 +122,7 @@ open class PetAPI { return request }.publisher }.flatMap { request -> AnyPublisher in - let securitySchemes: [SecurityScheme] = [] - return self.transport.send(request: request, securitySchemes: securitySchemes) + return self.transport.send(request: request) .mapError { transportError -> Error in if transportError.statusCode == 400 { return DeletePetError.code400Error @@ -186,8 +184,7 @@ open class PetAPI { return request }.publisher }.flatMap { request -> AnyPublisher<[Pet], Error> in - let securitySchemes: [SecurityScheme] = [] - return self.transport.send(request: request, securitySchemes: securitySchemes) + return self.transport.send(request: request) .mapError { transportError -> Error in if transportError.statusCode == 400 { return FindPetsByStatusError.code400Error @@ -242,8 +239,7 @@ open class PetAPI { return request }.publisher }.flatMap { request -> AnyPublisher<[Pet], Error> in - let securitySchemes: [SecurityScheme] = [] - return self.transport.send(request: request, securitySchemes: securitySchemes) + return self.transport.send(request: request) .mapError { transportError -> Error in if transportError.statusCode == 400 { return FindPetsByTagsError.code400Error @@ -299,8 +295,7 @@ open class PetAPI { return request }.publisher }.flatMap { request -> AnyPublisher in - let securitySchemes: [SecurityScheme] = [] - return self.transport.send(request: request, securitySchemes: securitySchemes) + return self.transport.send(request: request) .mapError { transportError -> Error in if transportError.statusCode == 400 { return GetPetByIdError.code400Error @@ -368,8 +363,7 @@ open class PetAPI { return request }.publisher }.flatMap { request -> AnyPublisher in - let securitySchemes: [SecurityScheme] = [] - return self.transport.send(request: request, securitySchemes: securitySchemes) + return self.transport.send(request: request) .mapError { transportError -> Error in if transportError.statusCode == 400 { return UpdatePetError.code400Error @@ -434,8 +428,7 @@ open class PetAPI { return request }.publisher }.flatMap { request -> AnyPublisher in - let securitySchemes: [SecurityScheme] = [] - return self.transport.send(request: request, securitySchemes: securitySchemes) + return self.transport.send(request: request) .mapError { transportError -> Error in if transportError.statusCode == 405 { return UpdatePetWithFormError.code405Error @@ -501,8 +494,7 @@ open class PetAPI { return request }.publisher }.flatMap { request -> AnyPublisher in - let securitySchemes: [SecurityScheme] = [] - return self.transport.send(request: request, securitySchemes: securitySchemes) + return self.transport.send(request: request) .tryMap { response in try self.decoder.decode(ApiResponse.self, from: response.data) } diff --git a/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/APIs/StoreAPI.swift b/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/APIs/StoreAPI.swift index a3f6931b46ff..837151c9b5c3 100644 --- a/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/APIs/StoreAPI.swift +++ b/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/APIs/StoreAPI.swift @@ -66,8 +66,7 @@ open class StoreAPI { return request }.publisher }.flatMap { request -> AnyPublisher in - let securitySchemes: [SecurityScheme] = [] - return self.transport.send(request: request, securitySchemes: securitySchemes) + return self.transport.send(request: request) .mapError { transportError -> Error in if transportError.statusCode == 400 { return DeleteOrderError.code400Error @@ -109,8 +108,7 @@ open class StoreAPI { return request }.publisher }.flatMap { request -> AnyPublisher<[String: Int], Error> in - let securitySchemes: [SecurityScheme] = [] - return self.transport.send(request: request, securitySchemes: securitySchemes) + return self.transport.send(request: request) .tryMap { response in try self.decoder.decode([String: Int].self, from: response.data) } @@ -157,8 +155,7 @@ open class StoreAPI { return request }.publisher }.flatMap { request -> AnyPublisher in - let securitySchemes: [SecurityScheme] = [] - return self.transport.send(request: request, securitySchemes: securitySchemes) + return self.transport.send(request: request) .mapError { transportError -> Error in if transportError.statusCode == 400 { return GetOrderByIdError.code400Error @@ -211,8 +208,7 @@ open class StoreAPI { return request }.publisher }.flatMap { request -> AnyPublisher in - let securitySchemes: [SecurityScheme] = [] - return self.transport.send(request: request, securitySchemes: securitySchemes) + return self.transport.send(request: request) .mapError { transportError -> Error in if transportError.statusCode == 400 { return PlaceOrderError.code400Error diff --git a/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/APIs/UserAPI.swift b/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/APIs/UserAPI.swift index c745d6d97d06..f2e7504053c9 100644 --- a/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/APIs/UserAPI.swift +++ b/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/APIs/UserAPI.swift @@ -55,8 +55,7 @@ open class UserAPI { return request }.publisher }.flatMap { request -> AnyPublisher in - let securitySchemes: [SecurityScheme] = [] - return self.transport.send(request: request, securitySchemes: securitySchemes) + return self.transport.send(request: request) .tryMap { response in return () } @@ -92,8 +91,7 @@ open class UserAPI { return request }.publisher }.flatMap { request -> AnyPublisher in - let securitySchemes: [SecurityScheme] = [] - return self.transport.send(request: request, securitySchemes: securitySchemes) + return self.transport.send(request: request) .tryMap { response in return () } @@ -129,8 +127,7 @@ open class UserAPI { return request }.publisher }.flatMap { request -> AnyPublisher in - let securitySchemes: [SecurityScheme] = [] - return self.transport.send(request: request, securitySchemes: securitySchemes) + return self.transport.send(request: request) .tryMap { response in return () } @@ -180,8 +177,7 @@ open class UserAPI { return request }.publisher }.flatMap { request -> AnyPublisher in - let securitySchemes: [SecurityScheme] = [] - return self.transport.send(request: request, securitySchemes: securitySchemes) + return self.transport.send(request: request) .mapError { transportError -> Error in if transportError.statusCode == 400 { return DeleteUserError.code400Error @@ -237,8 +233,7 @@ open class UserAPI { return request }.publisher }.flatMap { request -> AnyPublisher in - let securitySchemes: [SecurityScheme] = [] - return self.transport.send(request: request, securitySchemes: securitySchemes) + return self.transport.send(request: request) .mapError { transportError -> Error in if transportError.statusCode == 400 { return GetUserByNameError.code400Error @@ -295,8 +290,7 @@ open class UserAPI { return request }.publisher }.flatMap { request -> AnyPublisher in - let securitySchemes: [SecurityScheme] = [] - return self.transport.send(request: request, securitySchemes: securitySchemes) + return self.transport.send(request: request) .mapError { transportError -> Error in if transportError.statusCode == 400 { return LoginUserError.code400Error @@ -335,8 +329,7 @@ open class UserAPI { return request }.publisher }.flatMap { request -> AnyPublisher in - let securitySchemes: [SecurityScheme] = [] - return self.transport.send(request: request, securitySchemes: securitySchemes) + return self.transport.send(request: request) .tryMap { response in return () } @@ -389,8 +382,7 @@ open class UserAPI { return request }.publisher }.flatMap { request -> AnyPublisher in - let securitySchemes: [SecurityScheme] = [] - return self.transport.send(request: request, securitySchemes: securitySchemes) + return self.transport.send(request: request) .mapError { transportError -> Error in if transportError.statusCode == 400 { return UpdateUserError.code400Error diff --git a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/model/dog.dart b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/model/dog.dart index 484567e74d78..8d3d3e27a17f 100644 --- a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/model/dog.dart +++ b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/model/dog.dart @@ -51,11 +51,6 @@ class _$DogSerializer implements PrimitiveSerializer { specifiedType: const FullType(String), ); } - yield r'className'; - yield serializers.serialize( - object.className, - specifiedType: const FullType(String), - ); if (object.breed != null) { yield r'breed'; yield serializers.serialize( @@ -98,13 +93,6 @@ class _$DogSerializer implements PrimitiveSerializer { ) as String; result.color = valueDes; break; - case r'className': - final valueDes = serializers.deserialize( - value, - specifiedType: const FullType(String), - ) as String; - result.className = valueDes; - break; case r'breed': final valueDes = serializers.deserialize( value, From d9831b9bd8b73faa5f4b4ee9c17e3894f9814bdf Mon Sep 17 00:00:00 2001 From: Anton Davydov Date: Wed, 14 Jun 2023 15:37:48 +0300 Subject: [PATCH 31/33] Updated bitrise.yml file --- bitrise.yml | 9 +++++++++ .../main/resources/swift-combine/api.mustache | 8 +++++++- .../resources/swift-combine/toString.mustache | 2 +- .../PetstoreOpenAPI/Sources/APIs/PetAPI.swift | 15 +++++++-------- .../Sources/APIs/StoreAPI.swift | 2 +- .../swift-combine/swift-combine_test_all.sh | 5 +++++ .../Sources/TestClientTests/PetAPITests.swift | 18 +++++++++++++++--- 7 files changed, 45 insertions(+), 14 deletions(-) create mode 100755 samples/client/petstore/swift-combine/swift-combine_test_all.sh diff --git a/bitrise.yml b/bitrise.yml index 0f8b81e2450d..290f77635082 100644 --- a/bitrise.yml +++ b/bitrise.yml @@ -27,6 +27,15 @@ workflows: set -e ./samples/client/petstore/swift5/swift5_test_all.sh + - script@1.2.0: + title: Run swift-combine tests + inputs: + - content: | + #!/usr/bin/env bash + + set -e + + ./samples/client/petstore/swift-combine/swift-combine_test_all.sh meta: bitrise.io: diff --git a/modules/openapi-generator/src/main/resources/swift-combine/api.mustache b/modules/openapi-generator/src/main/resources/swift-combine/api.mustache index dc250bc594a2..299e5078280d 100644 --- a/modules/openapi-generator/src/main/resources/swift-combine/api.mustache +++ b/modules/openapi-generator/src/main/resources/swift-combine/api.mustache @@ -81,7 +81,13 @@ open class {{classname}} { /// - responseHeaders: [{{#responseHeaders}}{{{baseName}}}({{{dataType}}}){{^-last}}, {{/-last}}{{/responseHeaders}}] {{/hasResponseHeaders}} {{#externalDocs}} - /// - externalDocs: {{.}} + /// - externalDocs: + {{#url}} + /// url: {{.}} + {{/url}} + {{#description}} + /// description: {{.}} + {{/description}} {{/externalDocs}} {{#allParams}} /// - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} diff --git a/modules/openapi-generator/src/main/resources/swift-combine/toString.mustache b/modules/openapi-generator/src/main/resources/swift-combine/toString.mustache index 8e9d14247d1f..5535cae98f1b 100644 --- a/modules/openapi-generator/src/main/resources/swift-combine/toString.mustache +++ b/modules/openapi-generator/src/main/resources/swift-combine/toString.mustache @@ -1 +1 @@ -{{#isDateTime}}OpenISO8601DateFormatter.shared.string(from: {{paramName}}){{/isDateTime}}{{#vendorExtensions.x-swift-use-encoder}}String(data: try self.encoder.encode({{paramName}}), encoding: .utf8) ?? ""{{/vendorExtensions.x-swift-use-encoder}}{{^vendorExtensions.x-swift-use-encoder}}{{#isArray}}{{paramName}}{{#vendorExtensions.x-swift-is-base-type-udid}}.map { $0.uuidString }{{/vendorExtensions.x-swift-is-base-type-udid}}{{#vendorExtensions.x-swift-is-base-type-enum}}.map { $0.rawValue }{{/vendorExtensions.x-swift-is-base-type-enum}}.joined(separator: ","){{/isArray}}{{^isArray}}{{#vendorExtensions.x-swift-is-enum-type}}{{paramName}}.rawValue{{/vendorExtensions.x-swift-is-enum-type}}{{^isEnum}}{{#isString}}{{#isUuid}}{{paramName}}.uuidString{{/isUuid}}{{^isUuid}}{{paramName}}{{/isUuid}}{{/isString}}{{#isInteger}}"\({{paramName}})"{{/isInteger}}{{#isDouble}}"\({{paramName}})"{{/isDouble}}{{#isFloat}}"\({{paramName}})"{{/isFloat}}{{#isNumber}}"\({{paramName}})"{{/isNumber}}{{#isBoolean}}{{paramName}} ? "true" : "false"{{/isBoolean}}{{/isEnum}}{{/isArray}}{{/vendorExtensions.x-swift-use-encoder}} \ No newline at end of file +{{#isDateTime}}OpenISO8601DateFormatter.shared.string(from: {{paramName}}){{/isDateTime}}{{#vendorExtensions.x-swift-use-encoder}}String(data: try self.encoder.encode({{paramName}}), encoding: .utf8) ?? ""{{/vendorExtensions.x-swift-use-encoder}}{{^vendorExtensions.x-swift-use-encoder}}{{#isArray}}{{paramName}}{{#vendorExtensions.x-swift-is-base-type-udid}}.map { $0.uuidString }{{/vendorExtensions.x-swift-is-base-type-udid}}{{#vendorExtensions.x-swift-is-base-type-enum}}.map { $0.rawValue }{{/vendorExtensions.x-swift-is-base-type-enum}}.joined(separator: ","){{/isArray}}{{^isArray}}{{#vendorExtensions.x-swift-is-enum-type}}{{paramName}}.rawValue{{/vendorExtensions.x-swift-is-enum-type}}{{^isEnum}}{{#isString}}{{#isUuid}}{{paramName}}.uuidString{{/isUuid}}{{^isUuid}}{{paramName}}{{/isUuid}}{{/isString}}{{#isInteger}}"\({{paramName}})"{{/isInteger}}{{#isDouble}}"\({{paramName}})"{{/isDouble}}{{#isFloat}}"\({{paramName}})"{{/isFloat}}{{#isNumber}}"\({{paramName}})"{{/isNumber}}{{#isLong}}"\({{paramName}})"{{/isLong}}{{#isBoolean}}{{paramName}} ? "true" : "false"{{/isBoolean}}{{/isEnum}}{{/isArray}}{{/vendorExtensions.x-swift-use-encoder}} \ No newline at end of file diff --git a/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/APIs/PetAPI.swift b/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/APIs/PetAPI.swift index d7678e37be1d..952c7313304f 100644 --- a/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/APIs/PetAPI.swift +++ b/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/APIs/PetAPI.swift @@ -108,7 +108,7 @@ open class PetAPI { throw OpenAPITransportError.badURLError() } var path = "/pet/{petId}" - path = path.replacingOccurrences(of: "{petId}", with: ) + path = path.replacingOccurrences(of: "{petId}", with: "\(petId)") let url = baseURL.appendingPathComponent(path) let components = URLComponents(url: url, resolvingAgainstBaseURL: false) guard let requestURL = components?.url else { @@ -284,7 +284,7 @@ open class PetAPI { throw OpenAPITransportError.badURLError() } var path = "/pet/{petId}" - path = path.replacingOccurrences(of: "{petId}", with: ) + path = path.replacingOccurrences(of: "{petId}", with: "\(petId)") let url = baseURL.appendingPathComponent(path) let components = URLComponents(url: url, resolvingAgainstBaseURL: false) guard let requestURL = components?.url else { @@ -338,10 +338,9 @@ open class PetAPI { /// - OAuth: /// - type: oauth2 /// - name: petstore_auth - /// - externalDocs: class ExternalDocumentation { - description: API documentation for the updatePet operation - url: http://petstore.swagger.io/v2/doc/updatePet -} + /// - externalDocs: + /// url: http://petstore.swagger.io/v2/doc/updatePet + /// description: API documentation for the updatePet operation /// - parameter pet: (body) Pet object that needs to be added to the store /// - returns: AnyPublisher open func updatePet(pet: Pet) -> AnyPublisher { @@ -412,7 +411,7 @@ open class PetAPI { throw OpenAPITransportError.badURLError() } var path = "/pet/{petId}" - path = path.replacingOccurrences(of: "{petId}", with: ) + path = path.replacingOccurrences(of: "{petId}", with: "\(petId)") let url = baseURL.appendingPathComponent(path) let components = URLComponents(url: url, resolvingAgainstBaseURL: false) guard let requestURL = components?.url else { @@ -460,7 +459,7 @@ open class PetAPI { throw OpenAPITransportError.badURLError() } var path = "/pet/{petId}/uploadImage" - path = path.replacingOccurrences(of: "{petId}", with: ) + path = path.replacingOccurrences(of: "{petId}", with: "\(petId)") let url = baseURL.appendingPathComponent(path) let components = URLComponents(url: url, resolvingAgainstBaseURL: false) guard let requestURL = components?.url else { diff --git a/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/APIs/StoreAPI.swift b/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/APIs/StoreAPI.swift index 837151c9b5c3..ffd6596b1479 100644 --- a/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/APIs/StoreAPI.swift +++ b/samples/client/petstore/swift-combine/client/PetstoreOpenAPI/Sources/APIs/StoreAPI.swift @@ -144,7 +144,7 @@ open class StoreAPI { throw OpenAPITransportError.badURLError() } var path = "/store/order/{orderId}" - path = path.replacingOccurrences(of: "{orderId}", with: ) + path = path.replacingOccurrences(of: "{orderId}", with: "\(orderId)") let url = baseURL.appendingPathComponent(path) let components = URLComponents(url: url, resolvingAgainstBaseURL: false) guard let requestURL = components?.url else { diff --git a/samples/client/petstore/swift-combine/swift-combine_test_all.sh b/samples/client/petstore/swift-combine/swift-combine_test_all.sh new file mode 100755 index 000000000000..02aaf4432e95 --- /dev/null +++ b/samples/client/petstore/swift-combine/swift-combine_test_all.sh @@ -0,0 +1,5 @@ +#!/bin/bash +set -e + +(cd tests ; xcodebuild -scheme TestClientTests-Package test -destination "platform=iOS Simulator,name=iPhone 14,OS=latest" | xcpretty && exit ${PIPESTATUS[0]}) + diff --git a/samples/client/petstore/swift-combine/tests/Sources/TestClientTests/PetAPITests.swift b/samples/client/petstore/swift-combine/tests/Sources/TestClientTests/PetAPITests.swift index c7d8ead2a392..3f1314a4dc9d 100644 --- a/samples/client/petstore/swift-combine/tests/Sources/TestClientTests/PetAPITests.swift +++ b/samples/client/petstore/swift-combine/tests/Sources/TestClientTests/PetAPITests.swift @@ -22,6 +22,7 @@ class PetAPITests: XCTestCase { func testAddPet() { // Given let transport = URLSessionOpenAPITransport(config: .init(baseURL: baseURL)) + let api = PetAPI(transport) let category = Category(id: 1, name: "CategoryName") let photoUrls = ["https://petstore.com/sample/photo1.jpg", "https://petstore.com/sample/photo2.jpg"] @@ -68,11 +69,10 @@ class PetAPITests: XCTestCase { switch completion { case .finished: XCTFail("Finding unknown pet operation should return 404 error") - expectation.fulfill() case let .failure(error): - XCTAssertTrue((error as? OpenAPITransportError)?.statusCode == 404, "Finding unknown pet operation should return 404 error") - expectation.fulfill() + XCTAssertTrue((error as? PetAPI.GetPetByIdError) == .code404Error, "Finding unknown pet operation should return 404 error") } + expectation.fulfill() } receiveValue: { _ in } .store(in: &cancellable) @@ -104,3 +104,15 @@ class PetAPITests: XCTestCase { wait(for: [expectation], timeout: timeout) } } + +extension Tag: Equatable { + public static func ==(l: Tag, r: Tag) -> Bool { + l.id == r.id && l.name == r.name + } +} + +extension Pet: Equatable { + public static func ==(l: Pet, r: Pet) -> Bool { + l.id == r.id && l.name == r.name && l.photoUrls == r.photoUrls && l.status == r.status && l.tags == r.tags + } +} From fe63f59b8fdd77ee9889ecc6ac46117b65672e33 Mon Sep 17 00:00:00 2001 From: Anton Davydov Date: Fri, 16 Jun 2023 17:52:44 +0300 Subject: [PATCH 32/33] Fixed bitrise pipeline for swift-combine --- .../src/main/resources/swift-combine/api.mustache | 2 +- .../client/petstore/swift-combine/swift-combine_test_all.sh | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/openapi-generator/src/main/resources/swift-combine/api.mustache b/modules/openapi-generator/src/main/resources/swift-combine/api.mustache index 299e5078280d..1ca68437d0cd 100644 --- a/modules/openapi-generator/src/main/resources/swift-combine/api.mustache +++ b/modules/openapi-generator/src/main/resources/swift-combine/api.mustache @@ -73,7 +73,7 @@ open class {{classname}} { /// - subresourceOperation: {{.}}{{/subresourceOperation}}{{#defaultResponse}} /// - defaultResponse: {{.}}{{/defaultResponse}} {{#authMethods}} - /// - {{#isBasic}}BASIC{{/isBasic}}{{#isOAuth}}OAuth{{/isOAuth}}{{#isApiKey}}API Key{{/isApiKey}}: + /// - {{#isBasicBasic}}BASIC{{/isBasicBasic}}{{#isOAuth}}OAuth{{/isOAuth}}{{#isApiKey}}API Key{{/isApiKey}}: /// - type: {{type}}{{#keyParamName}} {{keyParamName}} {{#isKeyInQuery}}(QUERY){{/isKeyInQuery}}{{#isKeyInHeaer}}(HEADER){{/isKeyInHeaer}}{{/keyParamName}} /// - name: {{name}} {{/authMethods}} diff --git a/samples/client/petstore/swift-combine/swift-combine_test_all.sh b/samples/client/petstore/swift-combine/swift-combine_test_all.sh index 02aaf4432e95..c3ff4ec160d6 100755 --- a/samples/client/petstore/swift-combine/swift-combine_test_all.sh +++ b/samples/client/petstore/swift-combine/swift-combine_test_all.sh @@ -1,5 +1,7 @@ #!/bin/bash set -e -(cd tests ; xcodebuild -scheme TestClientTests-Package test -destination "platform=iOS Simulator,name=iPhone 14,OS=latest" | xcpretty && exit ${PIPESTATUS[0]}) +DIRECTORY=`dirname $0` + +(cd $DIRECTORY/tests ; xcodebuild -scheme TestClientTests-Package test -destination "platform=iOS Simulator,name=iPhone 14,OS=latest" | xcpretty && exit ${PIPESTATUS[0]}) From 2a56ecef50b45c79c2298e3ab23b11bcc6ab1737 Mon Sep 17 00:00:00 2001 From: Anton Davydov Date: Fri, 16 Jun 2023 18:00:55 +0300 Subject: [PATCH 33/33] Fixed code review comment --- .../resources/swift-combine/README.mustache | 76 ------------------- 1 file changed, 76 deletions(-) delete mode 100644 modules/openapi-generator/src/main/resources/swift-combine/README.mustache diff --git a/modules/openapi-generator/src/main/resources/swift-combine/README.mustache b/modules/openapi-generator/src/main/resources/swift-combine/README.mustache deleted file mode 100644 index ad83e06abc80..000000000000 --- a/modules/openapi-generator/src/main/resources/swift-combine/README.mustache +++ /dev/null @@ -1,76 +0,0 @@ -# Swift5 API client for {{{projectName}}} - -{{#appDescriptionWithNewLines}} -{{{.}}} -{{/appDescriptionWithNewLines}} - -## Overview -This API client was generated by the [OpenAPI Generator](https://openapi-generator.tech) project. By using the [openapi-spec](https://github.com/OAI/OpenAPI-Specification) from a remote server, you can easily generate an API client. - -- API version: {{appVersion}} -- Package version: {{packageVersion}} -{{^hideGenerationTimestamp}} -- Build date: {{generatedDate}} -{{/hideGenerationTimestamp}} -- Build package: {{generatorClass}} -{{#infoUrl}} -For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}}) -{{/infoUrl}} - -## Installation - -{{#useVapor}} -Add the following entry in your Package.swift: - -> .package(path: "./{{{projectName}}}") - -{{/useVapor}} -{{^useVapor}} -### Carthage - -Run `carthage update` - -### CocoaPods - -Run `pod install` - -{{/useVapor}}## Documentation for API Endpoints - -All URIs are relative to *{{basePath}}* - -Class | Method | HTTP request | Description ------------- | ------------- | ------------- | ------------- -{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}*{{classname}}* | [**{{operationId}}**]({{apiDocPath}}{{classname}}.md#{{operationIdLowerCase}}) | **{{httpMethod}}** {{path}} | {{summary}} -{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} - -## Documentation For Models - -{{#models}}{{#model}} - [{{{classname}}}]({{modelDocPath}}{{{classname}}}.md) -{{/model}}{{/models}} - -## Documentation For Authorization - -{{^authMethods}} All endpoints do not require authorization. -{{/authMethods}}{{#authMethods}}{{#last}} Authentication schemes defined for the API:{{/last}}{{/authMethods}} -{{#authMethods}}## {{{name}}} - -{{#isApiKey}}- **Type**: API key -- **API key parameter name**: {{{keyParamName}}} -- **Location**: {{#isKeyInQuery}}URL query string{{/isKeyInQuery}}{{#isKeyInHeader}}HTTP header{{/isKeyInHeader}} -{{/isApiKey}} -{{#isBasic}}- **Type**: HTTP basic authentication -{{/isBasic}} -{{#isOAuth}}- **Type**: OAuth -- **Flow**: {{{flow}}} -- **Authorization URL**: {{{authorizationUrl}}} -- **Scopes**: {{^scopes}}N/A{{/scopes}} -{{#scopes}} - **{{{scope}}}**: {{{description}}} -{{/scopes}} -{{/isOAuth}} - -{{/authMethods}} - -## Author - -{{#apiInfo}}{{#apis}}{{#-last}}{{infoEmail}} -{{/-last}}{{/apis}}{{/apiInfo}}