From 5cd8d776219458fa2d6754536deeaad6f76b0e6b Mon Sep 17 00:00:00 2001 From: Andrew Montgomery Date: Fri, 4 Oct 2024 16:52:03 -0500 Subject: [PATCH 01/20] Reconfigure OpenAPI generation to output a Swift Package, simplify docker configuration --- Makefile | 28 +- openapi/GravatarOpenAPIClient/.gitignore | 100 +++ .../.openapi-generator-ignore | 28 + .../.openapi-generator/FILES | 45 ++ .../.openapi-generator/VERSION | 1 + .../OpenAPIClient.podspec | 15 + openapi/GravatarOpenAPIClient/Package.swift | 33 + openapi/GravatarOpenAPIClient/README.md | 76 ++ .../Sources/OpenAPIClient/APIHelper.swift | 119 ++++ .../Sources/OpenAPIClient/APIs.swift | 68 ++ .../Sources/OpenAPIClient/CodableHelper.swift | 49 ++ .../Sources/OpenAPIClient/Configuration.swift | 18 + .../Sources/OpenAPIClient/Extensions.swift | 233 +++++++ .../OpenAPIClient/JSONDataEncoding.swift | 56 ++ .../OpenAPIClient/JSONEncodingHelper.swift | 45 ++ .../Sources/OpenAPIClient/Models.swift | 129 ++++ .../Models/AssociatedResponse.swift | 55 ++ .../Sources/OpenAPIClient/Models/Avatar.swift | 98 +++ .../Models/CryptoWalletAddress.swift | 63 ++ .../OpenAPIClient/Models/GalleryImage.swift | 63 ++ .../OpenAPIClient/Models/Interest.swift | 63 ++ .../OpenAPIClient/Models/Language.swift | 77 +++ .../Sources/OpenAPIClient/Models/Link.swift | 63 ++ .../OpenAPIClient/Models/ModelError.swift | 63 ++ .../OpenAPIClient/Models/Profile.swift | 222 ++++++ .../Models/ProfileContactInfo.swift | 91 +++ .../Models/ProfilePayments.swift | 63 ++ .../Models/SetEmailAvatarRequest.swift | 55 ++ .../Models/VerifiedAccount.swift | 84 +++ .../OpenISO8601DateFormatter.swift | 56 ++ .../SynchronizedDictionary.swift | 36 + .../URLSessionImplementations.swift | 648 ++++++++++++++++++ .../Sources/OpenAPIClient/Validation.swift | 126 ++++ .../docs/AssociatedResponse.md | 10 + openapi/GravatarOpenAPIClient/docs/Avatar.md | 15 + .../GravatarOpenAPIClient/docs/AvatarsAPI.md | 163 +++++ .../docs/CryptoWalletAddress.md | 11 + .../docs/GalleryImage.md | 11 + .../GravatarOpenAPIClient/docs/Interest.md | 11 + .../GravatarOpenAPIClient/docs/Language.md | 13 + openapi/GravatarOpenAPIClient/docs/Link.md | 11 + .../GravatarOpenAPIClient/docs/ModelError.md | 11 + openapi/GravatarOpenAPIClient/docs/Profile.md | 34 + .../docs/ProfileContactInfo.md | 15 + .../docs/ProfilePayments.md | 11 + .../GravatarOpenAPIClient/docs/ProfilesAPI.md | 110 +++ .../docs/SetEmailAvatarRequest.md | 10 + .../docs/VerifiedAccount.md | 14 + openapi/GravatarOpenAPIClient/project.yml | 15 + openapi/{spec.yaml => openapi.yaml} | 0 openapi/{ => templates}/model.mustache | 0 .../modelInlineEnumDeclaration.mustache | 0 openapi/{ => templates}/modelObject.mustache | 0 53 files changed, 3421 insertions(+), 13 deletions(-) create mode 100644 openapi/GravatarOpenAPIClient/.gitignore create mode 100644 openapi/GravatarOpenAPIClient/.openapi-generator-ignore create mode 100644 openapi/GravatarOpenAPIClient/.openapi-generator/FILES create mode 100644 openapi/GravatarOpenAPIClient/.openapi-generator/VERSION create mode 100644 openapi/GravatarOpenAPIClient/OpenAPIClient.podspec create mode 100644 openapi/GravatarOpenAPIClient/Package.swift create mode 100644 openapi/GravatarOpenAPIClient/README.md create mode 100644 openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/APIHelper.swift create mode 100644 openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/APIs.swift create mode 100644 openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/CodableHelper.swift create mode 100644 openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Configuration.swift create mode 100644 openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Extensions.swift create mode 100644 openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/JSONDataEncoding.swift create mode 100644 openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/JSONEncodingHelper.swift create mode 100644 openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models.swift create mode 100644 openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/AssociatedResponse.swift create mode 100644 openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/Avatar.swift create mode 100644 openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/CryptoWalletAddress.swift create mode 100644 openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/GalleryImage.swift create mode 100644 openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/Interest.swift create mode 100644 openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/Language.swift create mode 100644 openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/Link.swift create mode 100644 openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/ModelError.swift create mode 100644 openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/Profile.swift create mode 100644 openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/ProfileContactInfo.swift create mode 100644 openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/ProfilePayments.swift create mode 100644 openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/SetEmailAvatarRequest.swift create mode 100644 openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/VerifiedAccount.swift create mode 100644 openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/OpenISO8601DateFormatter.swift create mode 100644 openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/SynchronizedDictionary.swift create mode 100644 openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/URLSessionImplementations.swift create mode 100644 openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Validation.swift create mode 100644 openapi/GravatarOpenAPIClient/docs/AssociatedResponse.md create mode 100644 openapi/GravatarOpenAPIClient/docs/Avatar.md create mode 100644 openapi/GravatarOpenAPIClient/docs/AvatarsAPI.md create mode 100644 openapi/GravatarOpenAPIClient/docs/CryptoWalletAddress.md create mode 100644 openapi/GravatarOpenAPIClient/docs/GalleryImage.md create mode 100644 openapi/GravatarOpenAPIClient/docs/Interest.md create mode 100644 openapi/GravatarOpenAPIClient/docs/Language.md create mode 100644 openapi/GravatarOpenAPIClient/docs/Link.md create mode 100644 openapi/GravatarOpenAPIClient/docs/ModelError.md create mode 100644 openapi/GravatarOpenAPIClient/docs/Profile.md create mode 100644 openapi/GravatarOpenAPIClient/docs/ProfileContactInfo.md create mode 100644 openapi/GravatarOpenAPIClient/docs/ProfilePayments.md create mode 100644 openapi/GravatarOpenAPIClient/docs/ProfilesAPI.md create mode 100644 openapi/GravatarOpenAPIClient/docs/SetEmailAvatarRequest.md create mode 100644 openapi/GravatarOpenAPIClient/docs/VerifiedAccount.md create mode 100644 openapi/GravatarOpenAPIClient/project.yml rename openapi/{spec.yaml => openapi.yaml} (100%) rename openapi/{ => templates}/model.mustache (100%) rename openapi/{ => templates}/modelInlineEnumDeclaration.mustache (100%) rename openapi/{ => templates}/modelObject.mustache (100%) diff --git a/Makefile b/Makefile index 4e7bafd2..3bb4fa70 100644 --- a/Makefile +++ b/Makefile @@ -12,9 +12,14 @@ SWIFTFORMAT_CACHE = ~/Library/Caches/com.charcoaldesign.swiftformat OPENAPI_GENERATOR_GIT_URL ?= https://github.com/openapitools/openapi-generator OPENAPI_GENERATOR_GIT_TAG ?= v7.5.0 OPENAPI_GENERATOR_CLONE_DIR ?= $(CURRENT_MAKEFILE_DIR)/openapi-generator + +OPENAPI_PROJECT_NAME ?= GravatarOpenAPIClient +OPENAPI_DIR ?= $(CURRENT_MAKEFILE_DIR)/openapi +OPENAPI_GENERATED_DIR ?= $(CURRENT_MAKEFILE_DIR)/openapi/$(OPENAPI_PROJECT_NAME) + OPENAPI_YAML_PATH ?= $(CURRENT_MAKEFILE_DIR)/openapi/spec.yaml MODEL_TEMPLATE_PATH ?= $(CURRENT_MAKEFILE_DIR)/openapi -OUTPUT_DIRECTORY ?= $(CURRENT_MAKEFILE_DIR)/Sources/Gravatar/OpenApi/Generated +OUTPUT_DIRECTORY ?= $(CURRENT_MAKEFILE_DIR)/OpenAPIClient # Derived values (don't change these). CURRENT_MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST))) @@ -109,18 +114,15 @@ install-and-generate: $(OPENAPI_GENERATOR_CLONE_DIR) # Clones and setup the open make generate generate: $(OUTPUT_DIRECTORY) # Generates the open-api model - cp "$(OPENAPI_YAML_PATH)" "$(OPENAPI_GENERATOR_CLONE_DIR)"/openapi.yaml - mkdir -p "$(OPENAPI_GENERATOR_CLONE_DIR)"/templates - cp "$(MODEL_TEMPLATE_PATH)"/*.mustache "$(OPENAPI_GENERATOR_CLONE_DIR)"/templates/ - rm -rf "$(OPENAPI_GENERATOR_CLONE_DIR)"/generated/OpenAPIClient/Classes/OpenAPIs/Models/* - "$(OPENAPI_GENERATOR_CLONE_DIR)"/run-in-docker.sh generate -i openapi.yaml \ - --global-property models \ - -t templates \ - -g swift5 \ - -o ./generated \ - -p packageName=Gravatar \ - --additional-properties=useJsonEncodable=false,readonlyProperties=true && \ - rsync -av --delete "$(OPENAPI_GENERATOR_CLONE_DIR)"/generated/OpenAPIClient/Classes/OpenAPIs/Models/ "$(OUTPUT_DIRECTORY)/" && \ + rm -rf "$(OPENAPI_GENERATED_DIR)/*" && \ + docker run --rm \ + -v ${OPENAPI_DIR}:/local openapitools/openapi-generator-cli:"$(OPENAPI_GENERATOR_GIT_TAG)" generate \ + -i /local/openapi.yaml \ + -o /local/GravatarOpenAPIClient \ + -t /local/templates \ + -g swift5 \ + -p packageName=Gravatar \ + --additional-properties=useJsonEncodable=false,readonlyProperties=true,projectName=OpenAPIClient,useSPMFileStructure=true && \ make swiftformat && \ echo "DONE! 🎉" diff --git a/openapi/GravatarOpenAPIClient/.gitignore b/openapi/GravatarOpenAPIClient/.gitignore new file mode 100644 index 00000000..316a8450 --- /dev/null +++ b/openapi/GravatarOpenAPIClient/.gitignore @@ -0,0 +1,100 @@ +# Created by https://www.toptal.com/developers/gitignore/api/xcode,swift +# Edit at https://www.toptal.com/developers/gitignore?templates=xcode,swift + +### Swift ### +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## User settings +xcuserdata/ + +## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) +*.xcscmblueprint +*.xccheckout + +## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) +build/ +DerivedData/ +*.moved-aside +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 + +## Obj-C/Swift specific +*.hmap + +## App packaging +*.ipa +*.dSYM.zip +*.dSYM + +## 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/ +# Package.pins +# Package.resolved +# *.xcodeproj +# Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata +# hence it is not needed unless you have added a package configuration file to your project +# .swiftpm + +.build/ + +# 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/ +# Add this line if you want to avoid checking in source code from the Xcode workspace +# *.xcworkspace + +# Carthage +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts + +Carthage/Build/ + +# Accio dependency management +Dependencies/ +.accio/ + +# 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://docs.fastlane.tools/best-practices/source-control/#source-control + +fastlane/report.xml +fastlane/Preview.html +fastlane/screenshots/**/*.png +fastlane/test_output + +# Code Injection +# After new code Injection tools there's a generated folder /iOSInjectionProject +# https://github.com/johnno1962/injectionforxcode + +iOSInjectionProject/ + +### Xcode ### + +## Xcode 8 and earlier + +### Xcode Patch ### +*.xcodeproj/* +!*.xcodeproj/project.pbxproj +!*.xcodeproj/xcshareddata/ +!*.xcworkspace/contents.xcworkspacedata +/*.gcno +**/xcshareddata/WorkspaceSettings.xcsettings + +# End of https://www.toptal.com/developers/gitignore/api/xcode,swift diff --git a/openapi/GravatarOpenAPIClient/.openapi-generator-ignore b/openapi/GravatarOpenAPIClient/.openapi-generator-ignore new file mode 100644 index 00000000..f20534fd --- /dev/null +++ b/openapi/GravatarOpenAPIClient/.openapi-generator-ignore @@ -0,0 +1,28 @@ +# 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 + +.swiftformat +Cartfile +git_push.sh +Sources/OpenAPIClient/APIs/ \ No newline at end of file diff --git a/openapi/GravatarOpenAPIClient/.openapi-generator/FILES b/openapi/GravatarOpenAPIClient/.openapi-generator/FILES new file mode 100644 index 00000000..cd579e69 --- /dev/null +++ b/openapi/GravatarOpenAPIClient/.openapi-generator/FILES @@ -0,0 +1,45 @@ +.gitignore +OpenAPIClient.podspec +Package.swift +README.md +Sources/OpenAPIClient/APIHelper.swift +Sources/OpenAPIClient/APIs.swift +Sources/OpenAPIClient/CodableHelper.swift +Sources/OpenAPIClient/Configuration.swift +Sources/OpenAPIClient/Extensions.swift +Sources/OpenAPIClient/JSONDataEncoding.swift +Sources/OpenAPIClient/JSONEncodingHelper.swift +Sources/OpenAPIClient/Models.swift +Sources/OpenAPIClient/Models/AssociatedResponse.swift +Sources/OpenAPIClient/Models/Avatar.swift +Sources/OpenAPIClient/Models/CryptoWalletAddress.swift +Sources/OpenAPIClient/Models/GalleryImage.swift +Sources/OpenAPIClient/Models/Interest.swift +Sources/OpenAPIClient/Models/Language.swift +Sources/OpenAPIClient/Models/Link.swift +Sources/OpenAPIClient/Models/ModelError.swift +Sources/OpenAPIClient/Models/Profile.swift +Sources/OpenAPIClient/Models/ProfileContactInfo.swift +Sources/OpenAPIClient/Models/ProfilePayments.swift +Sources/OpenAPIClient/Models/SetEmailAvatarRequest.swift +Sources/OpenAPIClient/Models/VerifiedAccount.swift +Sources/OpenAPIClient/OpenISO8601DateFormatter.swift +Sources/OpenAPIClient/SynchronizedDictionary.swift +Sources/OpenAPIClient/URLSessionImplementations.swift +Sources/OpenAPIClient/Validation.swift +docs/AssociatedResponse.md +docs/Avatar.md +docs/AvatarsAPI.md +docs/CryptoWalletAddress.md +docs/GalleryImage.md +docs/Interest.md +docs/Language.md +docs/Link.md +docs/ModelError.md +docs/Profile.md +docs/ProfileContactInfo.md +docs/ProfilePayments.md +docs/ProfilesAPI.md +docs/SetEmailAvatarRequest.md +docs/VerifiedAccount.md +project.yml diff --git a/openapi/GravatarOpenAPIClient/.openapi-generator/VERSION b/openapi/GravatarOpenAPIClient/.openapi-generator/VERSION new file mode 100644 index 00000000..18bb4182 --- /dev/null +++ b/openapi/GravatarOpenAPIClient/.openapi-generator/VERSION @@ -0,0 +1 @@ +7.5.0 diff --git a/openapi/GravatarOpenAPIClient/OpenAPIClient.podspec b/openapi/GravatarOpenAPIClient/OpenAPIClient.podspec new file mode 100644 index 00000000..0d10326e --- /dev/null +++ b/openapi/GravatarOpenAPIClient/OpenAPIClient.podspec @@ -0,0 +1,15 @@ +Pod::Spec.new do |s| + s.name = 'OpenAPIClient' + s.ios.deployment_target = '11.0' + s.osx.deployment_target = '10.13' + s.tvos.deployment_target = '11.0' + s.watchos.deployment_target = '4.0' + s.version = '3.0.0' + s.source = { :git => 'git@github.com:OpenAPITools/openapi-generator.git', :tag => 'v3.0.0' } + s.authors = 'OpenAPI Generator' + s.license = 'Proprietary' + s.homepage = 'https://github.com/OpenAPITools/openapi-generator' + s.summary = 'OpenAPIClient Swift SDK' + s.source_files = 'Sources/OpenAPIClient/**/*.swift' + s.dependency 'AnyCodable-FlightSchool', '~> 0.6' +end diff --git a/openapi/GravatarOpenAPIClient/Package.swift b/openapi/GravatarOpenAPIClient/Package.swift new file mode 100644 index 00000000..bfcd84c0 --- /dev/null +++ b/openapi/GravatarOpenAPIClient/Package.swift @@ -0,0 +1,33 @@ +// swift-tools-version:5.1 + +import PackageDescription + +let package = Package( + name: "OpenAPIClient", + platforms: [ + .iOS(.v11), + .macOS(.v10_13), + .tvOS(.v11), + .watchOS(.v4), + ], + 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", .upToNextMajor(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: "Sources/OpenAPIClient" + ), + ] +) diff --git a/openapi/GravatarOpenAPIClient/README.md b/openapi/GravatarOpenAPIClient/README.md new file mode 100644 index 00000000..a8e2ff3d --- /dev/null +++ b/openapi/GravatarOpenAPIClient/README.md @@ -0,0 +1,76 @@ +# Swift5 API client for OpenAPIClient + +Gravatar's public API endpoints + +## 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: 3.0.0 +- Package version: +- Generator version: 7.5.0 +- Build package: org.openapitools.codegen.languages.Swift5ClientCodegen +For more information, please visit [https://gravatar.com](https://gravatar.com) + +## Installation + +### Carthage + +Run `carthage update` + +### CocoaPods + +Run `pod install` + +## Documentation for API Endpoints + +All URIs are relative to *https://api.gravatar.com/v3* + +Class | Method | HTTP request | Description +------------ | ------------- | ------------- | ------------- +*AvatarsAPI* | [**getAvatars**](docs/AvatarsAPI.md#getavatars) | **GET** /me/avatars | List avatars +*AvatarsAPI* | [**setEmailAvatar**](docs/AvatarsAPI.md#setemailavatar) | **POST** /me/avatars/{imageId}/email | Set avatar for the hashed email +*AvatarsAPI* | [**uploadAvatar**](docs/AvatarsAPI.md#uploadavatar) | **POST** /me/avatars | Upload new avatar image +*ProfilesAPI* | [**associatedEmail**](docs/ProfilesAPI.md#associatedemail) | **GET** /me/associated-email | Check if the email is associated with the authenticated user +*ProfilesAPI* | [**getProfileById**](docs/ProfilesAPI.md#getprofilebyid) | **GET** /profiles/{profileIdentifier} | Get profile by identifier + + +## Documentation For Models + + - [AssociatedResponse](docs/AssociatedResponse.md) + - [Avatar](docs/Avatar.md) + - [CryptoWalletAddress](docs/CryptoWalletAddress.md) + - [GalleryImage](docs/GalleryImage.md) + - [Interest](docs/Interest.md) + - [Language](docs/Language.md) + - [Link](docs/Link.md) + - [ModelError](docs/ModelError.md) + - [Profile](docs/Profile.md) + - [ProfileContactInfo](docs/ProfileContactInfo.md) + - [ProfilePayments](docs/ProfilePayments.md) + - [SetEmailAvatarRequest](docs/SetEmailAvatarRequest.md) + - [VerifiedAccount](docs/VerifiedAccount.md) + + + +## Documentation For Authorization + + +Authentication schemes defined for the API: + +### apiKey + +- **Type**: HTTP Bearer Token authentication + + +### oauth + +- **Type**: OAuth +- **Flow**: implicit +- **Authorization URL**: https://public-api.wordpress.com/oauth2/authorize +- **Scopes**: N/A + + +## Author + + + diff --git a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/APIHelper.swift b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/APIHelper.swift new file mode 100644 index 00000000..6dd1b44c --- /dev/null +++ b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/APIHelper.swift @@ -0,0 +1,119 @@ +// APIHelper.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + +public struct APIHelper { + public 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 + } + + public 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 + .compactMap { value in convertAnyToString(value) } + .joined(separator: ",") + } else if let value: Any = item.value { + result[item.key] = convertAnyToString(value) + } + } + } + + public 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 + } + } + } + + public static func convertAnyToString(_ value: Any?) -> String? { + guard let value = value else { return nil } + if let value = value as? any RawRepresentable { + return "\(value.rawValue)" + } else { + return "\(value)" + } + } + + public static func mapValueToPathItem(_ source: Any) -> Any { + if let collection = source as? [Any?] { + return collection + .compactMap { value in convertAnyToString(value) } + .joined(separator: ",") + } + return source + } + + /// maps all values from source to query parameters + /// + /// explode attribute is respected: collection values might be either joined or split up into separate key value pairs + public static func mapValuesToQueryItems(_ source: [String: (wrappedValue: Any?, isExplode: Bool)]) -> [URLQueryItem]? { + let destination = source.filter { $0.value.wrappedValue != nil }.reduce(into: [URLQueryItem]()) { result, item in + if let collection = item.value.wrappedValue as? [Any?] { + + let collectionValues: [String] = collection.compactMap { value in convertAnyToString(value) } + + if !item.value.isExplode { + result.append(URLQueryItem(name: item.key, value: collectionValues.joined(separator: ","))) + } else { + collectionValues + .forEach { value in + result.append(URLQueryItem(name: item.key, value: value)) + } + } + + } else if let value = item.value.wrappedValue { + result.append(URLQueryItem(name: item.key, value: convertAnyToString(value))) + } + } + + if destination.isEmpty { + return nil + } + return destination.sorted { $0.name < $1.name } + } + + /// maps all values from source to query parameters + /// + /// collection values are always exploded + public 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 + .compactMap { value in convertAnyToString(value) } + .forEach { value in + result.append(URLQueryItem(name: item.key, value: value)) + } + + } else if let value = item.value { + result.append(URLQueryItem(name: item.key, value: convertAnyToString(value))) + } + } + + if destination.isEmpty { + return nil + } + return destination.sorted { $0.name < $1.name } + } +} diff --git a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/APIs.swift b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/APIs.swift new file mode 100644 index 00000000..fa2ea4a0 --- /dev/null +++ b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/APIs.swift @@ -0,0 +1,68 @@ +// APIs.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif +open class OpenAPIClientAPI { + public static var basePath = "https://api.gravatar.com/v3" + public static var customHeaders: [String: String] = [:] + public static var credential: URLCredential? + public static var requestBuilderFactory: RequestBuilderFactory = URLSessionRequestBuilderFactory() + public static var apiResponseQueue: DispatchQueue = .main +} + +open class RequestBuilder { + var credential: URLCredential? + var headers: [String: String] + public let parameters: [String: Any]? + public let method: String + public let URLString: String + public let requestTask: RequestTask = RequestTask() + public let requiresAuthentication: Bool + + /// Optional block to obtain a reference to the request's progress instance when available. + public var onProgressReady: ((Progress) -> Void)? + + required public init(method: String, URLString: String, parameters: [String: Any]?, headers: [String: String] = [:], requiresAuthentication: Bool) { + self.method = method + self.URLString = URLString + self.parameters = parameters + self.headers = headers + self.requiresAuthentication = requiresAuthentication + + addHeaders(OpenAPIClientAPI.customHeaders) + } + + open func addHeaders(_ aHeaders: [String: String]) { + for (header, value) in aHeaders { + headers[header] = value + } + } + + @discardableResult + open func execute(_ apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, _ completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) -> RequestTask { + return requestTask + } + + public func addHeader(name: String, value: String) -> Self { + if !value.isEmpty { + headers[name] = value + } + return self + } + + open func addCredential() -> Self { + credential = OpenAPIClientAPI.credential + return self + } +} + +public protocol RequestBuilderFactory { + func getNonDecodableBuilder() -> RequestBuilder.Type + func getBuilder() -> RequestBuilder.Type +} diff --git a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/CodableHelper.swift b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/CodableHelper.swift new file mode 100644 index 00000000..09c82e53 --- /dev/null +++ b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/CodableHelper.swift @@ -0,0 +1,49 @@ +// +// CodableHelper.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + +open 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 + }() + + public static var dateFormatter: DateFormatter { + get { return customDateFormatter ?? defaultDateFormatter } + set { customDateFormatter = newValue } + } + public static var jsonDecoder: JSONDecoder { + get { return customJSONDecoder ?? defaultJSONDecoder } + set { customJSONDecoder = newValue } + } + public static var jsonEncoder: JSONEncoder { + get { return customJSONEncoder ?? defaultJSONEncoder } + set { customJSONEncoder = newValue } + } + + open class func decode(_ type: T.Type, from data: Data) -> Swift.Result where T: Decodable { + return Swift.Result { try jsonDecoder.decode(type, from: data) } + } + + open class func encode(_ value: T) -> Swift.Result where T: Encodable { + return Swift.Result { try jsonEncoder.encode(value) } + } +} diff --git a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Configuration.swift b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Configuration.swift new file mode 100644 index 00000000..0457d990 --- /dev/null +++ b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Configuration.swift @@ -0,0 +1,18 @@ +// Configuration.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + +open class Configuration { + + /// Configures the range of HTTP status codes that will result in a successful response + /// + /// If a HTTP status code is outside of this range the response will be interpreted as failed. + public static var successfulStatusCodeRange: Range = 200..<300 +} diff --git a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Extensions.swift b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Extensions.swift new file mode 100644 index 00000000..ac04dba5 --- /dev/null +++ b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Extensions.swift @@ -0,0 +1,233 @@ +// Extensions.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif +#if canImport(AnyCodable) +import AnyCodable +#endif + +extension Bool: JSONEncodable { + func encodeToJSON() -> Any { self } +} + +extension Float: JSONEncodable { + func encodeToJSON() -> Any { self } +} + +extension Int: JSONEncodable { + func encodeToJSON() -> Any { self } +} + +extension Int32: JSONEncodable { + func encodeToJSON() -> Any { self } +} + +extension Int64: JSONEncodable { + func encodeToJSON() -> Any { self } +} + +extension Double: JSONEncodable { + func encodeToJSON() -> Any { self } +} + +extension Decimal: JSONEncodable { + func encodeToJSON() -> Any { self } +} + +extension String: JSONEncodable { + func encodeToJSON() -> Any { self } +} + +extension URL: JSONEncodable { + func encodeToJSON() -> Any { self } +} + +extension UUID: JSONEncodable { + func encodeToJSON() -> Any { self } +} + +extension RawRepresentable where RawValue: JSONEncodable { + func encodeToJSON() -> Any { return self.rawValue } +} + +private func encodeIfPossible(_ object: T) -> Any { + if let encodableObject = object as? JSONEncodable { + return encodableObject.encodeToJSON() + } else { + return object + } +} + +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 + } +} + +extension Data: JSONEncodable { + func encodeToJSON() -> Any { + return self.base64EncodedString(options: Data.Base64EncodingOptions()) + } +} + +extension Date: JSONEncodable { + func encodeToJSON() -> Any { + return CodableHelper.dateFormatter.string(from: self) + } +} + +extension JSONEncodable where Self: Encodable { + func encodeToJSON() -> Any { + guard let data = try? CodableHelper.jsonEncoder.encode(self) else { + fatalError("Could not encode to json: \(self)") + } + return data.encodeToJSON() + } +} + +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 { + + public mutating func encodeArray(_ values: [T], forKey key: Self.Key) throws where T: Encodable { + var arrayContainer = nestedUnkeyedContainer(forKey: key) + try arrayContainer.encode(contentsOf: values) + } + + public mutating func encodeArrayIfPresent(_ values: [T]?, forKey key: Self.Key) throws where T: Encodable { + if let values = values { + try encodeArray(values, forKey: key) + } + } + + public mutating func encodeMap(_ pairs: [Self.Key: T]) throws where T: Encodable { + for (key, value) in pairs { + try encode(value, forKey: key) + } + } + + public mutating func encodeMapIfPresent(_ pairs: [Self.Key: T]?) throws where T: Encodable { + if let pairs = pairs { + try encodeMap(pairs) + } + } + + public mutating func encode(_ value: Decimal, forKey key: Self.Key) throws { + var mutableValue = value + let stringValue = NSDecimalString(&mutableValue, Locale(identifier: "en_US")) + try encode(stringValue, forKey: key) + } + + public mutating func encodeIfPresent(_ value: Decimal?, forKey key: Self.Key) throws { + if let value = value { + try encode(value, forKey: key) + } + } +} + +extension KeyedDecodingContainerProtocol { + + public 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 + } + + public 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 + } + + public 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 + } + + public func decode(_ type: Decimal.Type, forKey key: Self.Key) throws -> Decimal { + let stringValue = try decode(String.self, forKey: key) + guard let decimalValue = Decimal(string: stringValue) else { + let context = DecodingError.Context(codingPath: [key], debugDescription: "The key \(key) couldn't be converted to a Decimal value") + throw DecodingError.typeMismatch(type, context) + } + + return decimalValue + } + + public func decodeIfPresent(_ type: Decimal.Type, forKey key: Self.Key) throws -> Decimal? { + guard let stringValue = try decodeIfPresent(String.self, forKey: key) else { + return nil + } + guard let decimalValue = Decimal(string: stringValue) else { + let context = DecodingError.Context(codingPath: [key], debugDescription: "The key \(key) couldn't be converted to a Decimal value") + throw DecodingError.typeMismatch(type, context) + } + + return decimalValue + } + +} + +extension HTTPURLResponse { + var isStatusCodeSuccessful: Bool { + return Configuration.successfulStatusCodeRange.contains(statusCode) + } +} diff --git a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/JSONDataEncoding.swift b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/JSONDataEncoding.swift new file mode 100644 index 00000000..cb3121a4 --- /dev/null +++ b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/JSONDataEncoding.swift @@ -0,0 +1,56 @@ +// +// JSONDataEncoding.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + +public 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. + public 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 + } + + public 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/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/JSONEncodingHelper.swift b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/JSONEncodingHelper.swift new file mode 100644 index 00000000..02f78ffb --- /dev/null +++ b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/JSONEncodingHelper.swift @@ -0,0 +1,45 @@ +// +// JSONEncodingHelper.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + +open class JSONEncodingHelper { + + open 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 + } + + open 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/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models.swift b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models.swift new file mode 100644 index 00000000..7094040c --- /dev/null +++ b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models.swift @@ -0,0 +1,129 @@ +// Models.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + +protocol JSONEncodable { + func encodeToJSON() -> Any +} + +/// An enum where the last case value can be used as a default catch-all. +protocol CaseIterableDefaultsLast: Decodable & CaseIterable & RawRepresentable +where RawValue: Decodable, AllCases: BidirectionalCollection {} + +extension CaseIterableDefaultsLast { + /// Initializes an enum such that if a known raw value is found, then it is decoded. + /// Otherwise the last case is used. + /// - Parameter decoder: A decoder. + public init(from decoder: Decoder) throws { + if let value = try Self(rawValue: decoder.singleValueContainer().decode(RawValue.self)) { + self = value + } else if let lastValue = Self.allCases.last { + self = lastValue + } else { + throw DecodingError.valueNotFound( + Self.Type.self, + .init(codingPath: decoder.codingPath, debugDescription: "CaseIterableDefaultsLast") + ) + } + } +} + +/// A flexible type that can be encoded (`.encodeNull` or `.encodeValue`) +/// or not encoded (`.encodeNothing`). Intended for request payloads. +public enum NullEncodable: Hashable { + case encodeNothing + case encodeNull + case encodeValue(Wrapped) +} + +extension NullEncodable: Codable where Wrapped: Codable { + public init(from decoder: Decoder) throws { + let container = try decoder.singleValueContainer() + if let value = try? container.decode(Wrapped.self) { + self = .encodeValue(value) + } else if container.decodeNil() { + self = .encodeNull + } else { + self = .encodeNothing + } + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.singleValueContainer() + switch self { + case .encodeNothing: return + case .encodeNull: try container.encodeNil() + case .encodeValue(let wrapped): try container.encode(wrapped) + } + } +} + +public enum ErrorResponse: Error { + case error(Int, Data?, URLResponse?, Error) +} + +public enum DownloadException: Error { + case responseDataMissing + case responseFailed + case requestMissing + case requestMissingPath + case requestMissingURL +} + +public enum DecodableRequestBuilderError: Error { + case emptyDataResponse + case nilHTTPResponse + case unsuccessfulHTTPStatusCode + case jsonDecoding(DecodingError) + case generalError(Error) +} + +open class Response { + public let statusCode: Int + public let header: [String: String] + public let body: T + public let bodyData: Data? + + public init(statusCode: Int, header: [String: String], body: T, bodyData: Data?) { + self.statusCode = statusCode + self.header = header + self.body = body + self.bodyData = bodyData + } + + public convenience init(response: HTTPURLResponse, body: T, bodyData: Data?) { + let rawHeader = response.allHeaderFields + var responseHeader = [String: String]() + for (key, value) in rawHeader { + if let key = key.base as? String, let value = value as? String { + responseHeader[key] = value + } + } + self.init(statusCode: response.statusCode, header: responseHeader, body: body, bodyData: bodyData) + } +} + +public final class RequestTask { + private var lock = NSRecursiveLock() + private var task: URLSessionTask? + + internal func set(task: URLSessionTask) { + lock.lock() + defer { lock.unlock() } + self.task = task + } + + public func cancel() { + lock.lock() + defer { lock.unlock() } + task?.cancel() + task = nil + } +} diff --git a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/AssociatedResponse.swift b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/AssociatedResponse.swift new file mode 100644 index 00000000..5c530c59 --- /dev/null +++ b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/AssociatedResponse.swift @@ -0,0 +1,55 @@ +// +// AssociatedResponse.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + + +public struct AssociatedResponse: Codable, Hashable, Sendable { + + /// Whether the entity is associated with the account. + public private(set) var associated: Bool + + @available(*, deprecated, message: "init will become internal on the next release") + public init(associated: Bool) { + self.associated = associated + } + + @available(*, deprecated, message: "CodingKeys will become internal on the next release.") + public enum CodingKeys: String, CodingKey, CaseIterable { + case associated + } + + + + + internal enum InternalCodingKeys: String, CodingKey, CaseIterable { + case associated + } + + + + + // Encodable protocol methods + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: InternalCodingKeys.self) + try container.encode(associated, forKey: .associated) + } + + + // Decodable protocol methods + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: InternalCodingKeys.self) + + associated = try container.decode(Bool.self, forKey: .associated) + } + + + +} + diff --git a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/Avatar.swift b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/Avatar.swift new file mode 100644 index 00000000..fb55cacb --- /dev/null +++ b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/Avatar.swift @@ -0,0 +1,98 @@ +// +// Avatar.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + +/// An avatar that the user has already uploaded to their Gravatar account. +/// +public struct Avatar: Codable, Hashable, Sendable { + + public enum Rating: String, Codable, CaseIterable, Sendable { + case g = "G" + case pg = "PG" + case r = "R" + case x = "X" + } + + /// Unique identifier for the image. + public private(set) var imageId: String + /// Image URL + public private(set) var imageUrl: String + /// Rating associated with the image. + public private(set) var rating: Rating + /// Date and time when the image was last updated. + public private(set) var updatedDate: Date + /// Alternative text description of the image. + public private(set) var altText: String + /// Whether the image is currently selected as the provided selected email's avatar. + public private(set) var selected: Bool? + + @available(*, deprecated, message: "init will become internal on the next release") + public init(imageId: String, imageUrl: String, rating: Rating, updatedDate: Date, altText: String, selected: Bool? = nil) { + self.imageId = imageId + self.imageUrl = imageUrl + self.rating = rating + self.updatedDate = updatedDate + self.altText = altText + self.selected = selected + } + + @available(*, deprecated, message: "CodingKeys will become internal on the next release.") + public enum CodingKeys: String, CodingKey, CaseIterable { + case imageId = "image_id" + case imageUrl = "image_url" + case rating + case updatedDate = "updated_date" + case altText = "alt_text" + case selected + } + + + + + internal enum InternalCodingKeys: String, CodingKey, CaseIterable { + case imageId = "image_id" + case imageUrl = "image_url" + case rating + case updatedDate = "updated_date" + case altText = "alt_text" + case selected + } + + + + + // Encodable protocol methods + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: InternalCodingKeys.self) + try container.encode(imageId, forKey: .imageId) + try container.encode(imageUrl, forKey: .imageUrl) + try container.encode(rating, forKey: .rating) + try container.encode(updatedDate, forKey: .updatedDate) + try container.encode(altText, forKey: .altText) + try container.encodeIfPresent(selected, forKey: .selected) + } + + + // Decodable protocol methods + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: InternalCodingKeys.self) + + imageId = try container.decode(String.self, forKey: .imageId) + imageUrl = try container.decode(String.self, forKey: .imageUrl) + rating = try container.decode(Rating.self, forKey: .rating) + updatedDate = try container.decode(Date.self, forKey: .updatedDate) + altText = try container.decode(String.self, forKey: .altText) + selected = try container.decodeIfPresent(Bool.self, forKey: .selected) + } + + + +} + diff --git a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/CryptoWalletAddress.swift b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/CryptoWalletAddress.swift new file mode 100644 index 00000000..20896a7a --- /dev/null +++ b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/CryptoWalletAddress.swift @@ -0,0 +1,63 @@ +// +// CryptoWalletAddress.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + +/// A crypto currency wallet address the user accepts. +/// +public struct CryptoWalletAddress: Codable, Hashable, Sendable { + + /// The label for the crypto currency. + public private(set) var label: String + /// The wallet address for the crypto currency. + public private(set) var address: String + + @available(*, deprecated, message: "init will become internal on the next release") + public init(label: String, address: String) { + self.label = label + self.address = address + } + + @available(*, deprecated, message: "CodingKeys will become internal on the next release.") + public enum CodingKeys: String, CodingKey, CaseIterable { + case label + case address + } + + + + + internal enum InternalCodingKeys: String, CodingKey, CaseIterable { + case label + case address + } + + + + + // Encodable protocol methods + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: InternalCodingKeys.self) + try container.encode(label, forKey: .label) + try container.encode(address, forKey: .address) + } + + + // Decodable protocol methods + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: InternalCodingKeys.self) + + label = try container.decode(String.self, forKey: .label) + address = try container.decode(String.self, forKey: .address) + } + + + +} + diff --git a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/GalleryImage.swift b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/GalleryImage.swift new file mode 100644 index 00000000..739c5ec5 --- /dev/null +++ b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/GalleryImage.swift @@ -0,0 +1,63 @@ +// +// GalleryImage.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + +/// A gallery image a user has uploaded. +/// +public struct GalleryImage: Codable, Hashable, Sendable { + + /// The URL to the image. + public private(set) var url: String + /// The image alt text. + public private(set) var altText: String? + + @available(*, deprecated, message: "init will become internal on the next release") + public init(url: String, altText: String? = nil) { + self.url = url + self.altText = altText + } + + @available(*, deprecated, message: "CodingKeys will become internal on the next release.") + public enum CodingKeys: String, CodingKey, CaseIterable { + case url + case altText = "alt_text" + } + + + + + internal enum InternalCodingKeys: String, CodingKey, CaseIterable { + case url + case altText = "alt_text" + } + + + + + // Encodable protocol methods + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: InternalCodingKeys.self) + try container.encode(url, forKey: .url) + try container.encodeIfPresent(altText, forKey: .altText) + } + + + // Decodable protocol methods + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: InternalCodingKeys.self) + + url = try container.decode(String.self, forKey: .url) + altText = try container.decodeIfPresent(String.self, forKey: .altText) + } + + + +} + diff --git a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/Interest.swift b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/Interest.swift new file mode 100644 index 00000000..7fefad0d --- /dev/null +++ b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/Interest.swift @@ -0,0 +1,63 @@ +// +// Interest.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + +/// An interest the user has added to their profile. +/// +public struct Interest: Codable, Hashable, Sendable { + + /// The unique identifier for the interest. + public private(set) var id: Int + /// The name of the interest. + public private(set) var name: String + + @available(*, deprecated, message: "init will become internal on the next release") + public init(id: Int, name: String) { + self.id = id + self.name = name + } + + @available(*, deprecated, message: "CodingKeys will become internal on the next release.") + public enum CodingKeys: String, CodingKey, CaseIterable { + case id + case name + } + + + + + internal enum InternalCodingKeys: String, CodingKey, CaseIterable { + case id + case name + } + + + + + // Encodable protocol methods + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: InternalCodingKeys.self) + try container.encode(id, forKey: .id) + try container.encode(name, forKey: .name) + } + + + // Decodable protocol methods + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: InternalCodingKeys.self) + + id = try container.decode(Int.self, forKey: .id) + name = try container.decode(String.self, forKey: .name) + } + + + +} + diff --git a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/Language.swift b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/Language.swift new file mode 100644 index 00000000..ac357bf3 --- /dev/null +++ b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/Language.swift @@ -0,0 +1,77 @@ +// +// Language.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + +/// The languages the user knows. This is only provided in authenticated API requests. +/// +public struct Language: Codable, Hashable, Sendable { + + /// The language code. + public private(set) var code: String + /// The language name. + public private(set) var name: String + /// Whether the language is the user's primary language. + public private(set) var isPrimary: Bool + /// The order of the language in the user's profile. + public private(set) var order: Int + + @available(*, deprecated, message: "init will become internal on the next release") + public init(code: String, name: String, isPrimary: Bool, order: Int) { + self.code = code + self.name = name + self.isPrimary = isPrimary + self.order = order + } + + @available(*, deprecated, message: "CodingKeys will become internal on the next release.") + public enum CodingKeys: String, CodingKey, CaseIterable { + case code + case name + case isPrimary = "is_primary" + case order + } + + + + + internal enum InternalCodingKeys: String, CodingKey, CaseIterable { + case code + case name + case isPrimary = "is_primary" + case order + } + + + + + // Encodable protocol methods + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: InternalCodingKeys.self) + try container.encode(code, forKey: .code) + try container.encode(name, forKey: .name) + try container.encode(isPrimary, forKey: .isPrimary) + try container.encode(order, forKey: .order) + } + + + // Decodable protocol methods + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: InternalCodingKeys.self) + + code = try container.decode(String.self, forKey: .code) + name = try container.decode(String.self, forKey: .name) + isPrimary = try container.decode(Bool.self, forKey: .isPrimary) + order = try container.decode(Int.self, forKey: .order) + } + + + +} + diff --git a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/Link.swift b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/Link.swift new file mode 100644 index 00000000..813c72b1 --- /dev/null +++ b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/Link.swift @@ -0,0 +1,63 @@ +// +// Link.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + +/// A link the user has added to their profile. +/// +public struct Link: Codable, Hashable, Sendable { + + /// The label for the link. + public private(set) var label: String + /// The URL to the link. + public private(set) var url: String + + @available(*, deprecated, message: "init will become internal on the next release") + public init(label: String, url: String) { + self.label = label + self.url = url + } + + @available(*, deprecated, message: "CodingKeys will become internal on the next release.") + public enum CodingKeys: String, CodingKey, CaseIterable { + case label + case url + } + + + + + internal enum InternalCodingKeys: String, CodingKey, CaseIterable { + case label + case url + } + + + + + // Encodable protocol methods + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: InternalCodingKeys.self) + try container.encode(label, forKey: .label) + try container.encode(url, forKey: .url) + } + + + // Decodable protocol methods + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: InternalCodingKeys.self) + + label = try container.decode(String.self, forKey: .label) + url = try container.decode(String.self, forKey: .url) + } + + + +} + diff --git a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/ModelError.swift b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/ModelError.swift new file mode 100644 index 00000000..4f5be692 --- /dev/null +++ b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/ModelError.swift @@ -0,0 +1,63 @@ +// +// ModelError.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + +/// An error response from the API. +/// +public struct ModelError: Codable, Hashable, Sendable { + + /// The error message + public private(set) var error: String + /// The error code for the error message + public private(set) var code: String? + + @available(*, deprecated, message: "init will become internal on the next release") + public init(error: String, code: String? = nil) { + self.error = error + self.code = code + } + + @available(*, deprecated, message: "CodingKeys will become internal on the next release.") + public enum CodingKeys: String, CodingKey, CaseIterable { + case error + case code + } + + + + + internal enum InternalCodingKeys: String, CodingKey, CaseIterable { + case error + case code + } + + + + + // Encodable protocol methods + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: InternalCodingKeys.self) + try container.encode(error, forKey: .error) + try container.encodeIfPresent(code, forKey: .code) + } + + + // Decodable protocol methods + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: InternalCodingKeys.self) + + error = try container.decode(String.self, forKey: .error) + code = try container.decodeIfPresent(String.self, forKey: .code) + } + + + +} + diff --git a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/Profile.swift b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/Profile.swift new file mode 100644 index 00000000..7d0b0c05 --- /dev/null +++ b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/Profile.swift @@ -0,0 +1,222 @@ +// +// Profile.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + +/// A user's profile information. +/// +public struct Profile: Codable, Hashable, Sendable { + + /// The SHA256 hash of the user's primary email address. + public private(set) var hash: String + /// The user's display name. This is the name that is displayed on their profile. + public private(set) var displayName: String + /// The full URL for the user's profile. + public private(set) var profileUrl: String + /// The URL for the user's avatar image if it has been set. + public private(set) var avatarUrl: String + /// The alt text for the user's avatar image if it has been set. + public private(set) var avatarAltText: String + /// The user's location. + public private(set) var location: String + /// The about section on a user's profile. + public private(set) var description: String + /// The user's job title. + public private(set) var jobTitle: String + /// The user's current company's name. + public private(set) var company: String + /// A list of verified accounts the user has added to their profile. This is limited to a max of 4 in unauthenticated requests. + public private(set) var verifiedAccounts: [VerifiedAccount] + /// The phonetic pronunciation of the user's name. + public private(set) var pronunciation: String + /// The pronouns the user uses. + public private(set) var pronouns: String + /// The timezone the user has. This is only provided in authenticated API requests. + public private(set) var timezone: String? + /// The languages the user knows. This is only provided in authenticated API requests. + public private(set) var languages: [Language]? + /// User's first name. This is only provided in authenticated API requests. + public private(set) var firstName: String? + /// User's last name. This is only provided in authenticated API requests. + public private(set) var lastName: String? + /// Whether user is an organization. This is only provided in authenticated API requests. + public private(set) var isOrganization: Bool? + /// A list of links the user has added to their profile. This is only provided in authenticated API requests. + public private(set) var links: [Link]? + /// A list of interests the user has added to their profile. This is only provided in authenticated API requests. + public private(set) var interests: [Interest]? + public private(set) var payments: ProfilePayments? + public private(set) var contactInfo: ProfileContactInfo? + /// Additional images a user has uploaded. This is only provided in authenticated API requests. + public private(set) var gallery: [GalleryImage]? + /// The number of verified accounts the user has added to their profile. This count includes verified accounts the user is hiding from their profile. This is only provided in authenticated API requests. + public private(set) var numberVerifiedAccounts: Int? + /// The date and time (UTC) the user last edited their profile. This is only provided in authenticated API requests. + public private(set) var lastProfileEdit: Date? + /// The date the user registered their account. This is only provided in authenticated API requests. + public private(set) var registrationDate: Date? + + @available(*, deprecated, message: "init will become internal on the next release") + public init(hash: String, displayName: String, profileUrl: String, avatarUrl: String, avatarAltText: String, location: String, description: String, jobTitle: String, company: String, verifiedAccounts: [VerifiedAccount], pronunciation: String, pronouns: String, timezone: String? = nil, languages: [Language]? = nil, firstName: String? = nil, lastName: String? = nil, isOrganization: Bool? = nil, links: [Link]? = nil, interests: [Interest]? = nil, payments: ProfilePayments? = nil, contactInfo: ProfileContactInfo? = nil, gallery: [GalleryImage]? = nil, numberVerifiedAccounts: Int? = nil, lastProfileEdit: Date? = nil, registrationDate: Date? = nil) { + self.hash = hash + self.displayName = displayName + self.profileUrl = profileUrl + self.avatarUrl = avatarUrl + self.avatarAltText = avatarAltText + self.location = location + self.description = description + self.jobTitle = jobTitle + self.company = company + self.verifiedAccounts = verifiedAccounts + self.pronunciation = pronunciation + self.pronouns = pronouns + self.timezone = timezone + self.languages = languages + self.firstName = firstName + self.lastName = lastName + self.isOrganization = isOrganization + self.links = links + self.interests = interests + self.payments = payments + self.contactInfo = contactInfo + self.gallery = gallery + self.numberVerifiedAccounts = numberVerifiedAccounts + self.lastProfileEdit = lastProfileEdit + self.registrationDate = registrationDate + } + + @available(*, deprecated, message: "CodingKeys will become internal on the next release.") + public enum CodingKeys: String, CodingKey, CaseIterable { + case hash + case displayName = "display_name" + case profileUrl = "profile_url" + case avatarUrl = "avatar_url" + case avatarAltText = "avatar_alt_text" + case location + case description + case jobTitle = "job_title" + case company + case verifiedAccounts = "verified_accounts" + case pronunciation + case pronouns + case timezone + case languages + case firstName = "first_name" + case lastName = "last_name" + case isOrganization = "is_organization" + case links + case interests + case payments + case contactInfo = "contact_info" + case gallery + case numberVerifiedAccounts = "number_verified_accounts" + case lastProfileEdit = "last_profile_edit" + case registrationDate = "registration_date" + } + + + + + internal enum InternalCodingKeys: String, CodingKey, CaseIterable { + case hash + case displayName = "display_name" + case profileUrl = "profile_url" + case avatarUrl = "avatar_url" + case avatarAltText = "avatar_alt_text" + case location + case description + case jobTitle = "job_title" + case company + case verifiedAccounts = "verified_accounts" + case pronunciation + case pronouns + case timezone + case languages + case firstName = "first_name" + case lastName = "last_name" + case isOrganization = "is_organization" + case links + case interests + case payments + case contactInfo = "contact_info" + case gallery + case numberVerifiedAccounts = "number_verified_accounts" + case lastProfileEdit = "last_profile_edit" + case registrationDate = "registration_date" + } + + + + + // Encodable protocol methods + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: InternalCodingKeys.self) + try container.encode(hash, forKey: .hash) + try container.encode(displayName, forKey: .displayName) + try container.encode(profileUrl, forKey: .profileUrl) + try container.encode(avatarUrl, forKey: .avatarUrl) + try container.encode(avatarAltText, forKey: .avatarAltText) + try container.encode(location, forKey: .location) + try container.encode(description, forKey: .description) + try container.encode(jobTitle, forKey: .jobTitle) + try container.encode(company, forKey: .company) + try container.encode(verifiedAccounts, forKey: .verifiedAccounts) + try container.encode(pronunciation, forKey: .pronunciation) + try container.encode(pronouns, forKey: .pronouns) + try container.encodeIfPresent(timezone, forKey: .timezone) + try container.encodeIfPresent(languages, forKey: .languages) + try container.encodeIfPresent(firstName, forKey: .firstName) + try container.encodeIfPresent(lastName, forKey: .lastName) + try container.encodeIfPresent(isOrganization, forKey: .isOrganization) + try container.encodeIfPresent(links, forKey: .links) + try container.encodeIfPresent(interests, forKey: .interests) + try container.encodeIfPresent(payments, forKey: .payments) + try container.encodeIfPresent(contactInfo, forKey: .contactInfo) + try container.encodeIfPresent(gallery, forKey: .gallery) + try container.encodeIfPresent(numberVerifiedAccounts, forKey: .numberVerifiedAccounts) + try container.encodeIfPresent(lastProfileEdit, forKey: .lastProfileEdit) + try container.encodeIfPresent(registrationDate, forKey: .registrationDate) + } + + + // Decodable protocol methods + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: InternalCodingKeys.self) + + hash = try container.decode(String.self, forKey: .hash) + displayName = try container.decode(String.self, forKey: .displayName) + profileUrl = try container.decode(String.self, forKey: .profileUrl) + avatarUrl = try container.decode(String.self, forKey: .avatarUrl) + avatarAltText = try container.decode(String.self, forKey: .avatarAltText) + location = try container.decode(String.self, forKey: .location) + description = try container.decode(String.self, forKey: .description) + jobTitle = try container.decode(String.self, forKey: .jobTitle) + company = try container.decode(String.self, forKey: .company) + verifiedAccounts = try container.decode([VerifiedAccount].self, forKey: .verifiedAccounts) + pronunciation = try container.decode(String.self, forKey: .pronunciation) + pronouns = try container.decode(String.self, forKey: .pronouns) + timezone = try container.decodeIfPresent(String.self, forKey: .timezone) + languages = try container.decodeIfPresent([Language].self, forKey: .languages) + firstName = try container.decodeIfPresent(String.self, forKey: .firstName) + lastName = try container.decodeIfPresent(String.self, forKey: .lastName) + isOrganization = try container.decodeIfPresent(Bool.self, forKey: .isOrganization) + links = try container.decodeIfPresent([Link].self, forKey: .links) + interests = try container.decodeIfPresent([Interest].self, forKey: .interests) + payments = try container.decodeIfPresent(ProfilePayments.self, forKey: .payments) + contactInfo = try container.decodeIfPresent(ProfileContactInfo.self, forKey: .contactInfo) + gallery = try container.decodeIfPresent([GalleryImage].self, forKey: .gallery) + numberVerifiedAccounts = try container.decodeIfPresent(Int.self, forKey: .numberVerifiedAccounts) + lastProfileEdit = try container.decodeIfPresent(Date.self, forKey: .lastProfileEdit) + registrationDate = try container.decodeIfPresent(Date.self, forKey: .registrationDate) + } + + + +} + diff --git a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/ProfileContactInfo.swift b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/ProfileContactInfo.swift new file mode 100644 index 00000000..16aaf252 --- /dev/null +++ b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/ProfileContactInfo.swift @@ -0,0 +1,91 @@ +// +// ProfileContactInfo.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + +/// The user's contact information. This is only available if the user has chosen to make it public. This is only provided in authenticated API requests. +/// +public struct ProfileContactInfo: Codable, Hashable, Sendable { + + /// The user's home phone number. + public private(set) var homePhone: String? + /// The user's work phone number. + public private(set) var workPhone: String? + /// The user's cell phone number. + public private(set) var cellPhone: String? + /// The user's email address as provided on the contact section of the profile. Might differ from their account emails. + public private(set) var email: String? + /// The URL to the user's contact form. + public private(set) var contactForm: String? + /// The URL to the user's calendar. + public private(set) var calendar: String? + + @available(*, deprecated, message: "init will become internal on the next release") + public init(homePhone: String? = nil, workPhone: String? = nil, cellPhone: String? = nil, email: String? = nil, contactForm: String? = nil, calendar: String? = nil) { + self.homePhone = homePhone + self.workPhone = workPhone + self.cellPhone = cellPhone + self.email = email + self.contactForm = contactForm + self.calendar = calendar + } + + @available(*, deprecated, message: "CodingKeys will become internal on the next release.") + public enum CodingKeys: String, CodingKey, CaseIterable { + case homePhone = "home_phone" + case workPhone = "work_phone" + case cellPhone = "cell_phone" + case email + case contactForm = "contact_form" + case calendar + } + + + + + internal enum InternalCodingKeys: String, CodingKey, CaseIterable { + case homePhone = "home_phone" + case workPhone = "work_phone" + case cellPhone = "cell_phone" + case email + case contactForm = "contact_form" + case calendar + } + + + + + // Encodable protocol methods + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: InternalCodingKeys.self) + try container.encodeIfPresent(homePhone, forKey: .homePhone) + try container.encodeIfPresent(workPhone, forKey: .workPhone) + try container.encodeIfPresent(cellPhone, forKey: .cellPhone) + try container.encodeIfPresent(email, forKey: .email) + try container.encodeIfPresent(contactForm, forKey: .contactForm) + try container.encodeIfPresent(calendar, forKey: .calendar) + } + + + // Decodable protocol methods + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: InternalCodingKeys.self) + + homePhone = try container.decodeIfPresent(String.self, forKey: .homePhone) + workPhone = try container.decodeIfPresent(String.self, forKey: .workPhone) + cellPhone = try container.decodeIfPresent(String.self, forKey: .cellPhone) + email = try container.decodeIfPresent(String.self, forKey: .email) + contactForm = try container.decodeIfPresent(String.self, forKey: .contactForm) + calendar = try container.decodeIfPresent(String.self, forKey: .calendar) + } + + + +} + diff --git a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/ProfilePayments.swift b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/ProfilePayments.swift new file mode 100644 index 00000000..0ef1ecce --- /dev/null +++ b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/ProfilePayments.swift @@ -0,0 +1,63 @@ +// +// ProfilePayments.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + +/// The user's public payment information. This is only provided in authenticated API requests. +/// +public struct ProfilePayments: Codable, Hashable, Sendable { + + /// A list of payment URLs the user has added to their profile. + public private(set) var links: [Link] + /// A list of crypto currencies the user accepts. + public private(set) var cryptoWallets: [CryptoWalletAddress] + + @available(*, deprecated, message: "init will become internal on the next release") + public init(links: [Link], cryptoWallets: [CryptoWalletAddress]) { + self.links = links + self.cryptoWallets = cryptoWallets + } + + @available(*, deprecated, message: "CodingKeys will become internal on the next release.") + public enum CodingKeys: String, CodingKey, CaseIterable { + case links + case cryptoWallets = "crypto_wallets" + } + + + + + internal enum InternalCodingKeys: String, CodingKey, CaseIterable { + case links + case cryptoWallets = "crypto_wallets" + } + + + + + // Encodable protocol methods + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: InternalCodingKeys.self) + try container.encode(links, forKey: .links) + try container.encode(cryptoWallets, forKey: .cryptoWallets) + } + + + // Decodable protocol methods + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: InternalCodingKeys.self) + + links = try container.decode([Link].self, forKey: .links) + cryptoWallets = try container.decode([CryptoWalletAddress].self, forKey: .cryptoWallets) + } + + + +} + diff --git a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/SetEmailAvatarRequest.swift b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/SetEmailAvatarRequest.swift new file mode 100644 index 00000000..51e5c8ff --- /dev/null +++ b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/SetEmailAvatarRequest.swift @@ -0,0 +1,55 @@ +// +// SetEmailAvatarRequest.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + + +public struct SetEmailAvatarRequest: Codable, Hashable, Sendable { + + /// The email SHA256 hash to set the avatar for. + public private(set) var emailHash: String + + @available(*, deprecated, message: "init will become internal on the next release") + public init(emailHash: String) { + self.emailHash = emailHash + } + + @available(*, deprecated, message: "CodingKeys will become internal on the next release.") + public enum CodingKeys: String, CodingKey, CaseIterable { + case emailHash = "email_hash" + } + + + + + internal enum InternalCodingKeys: String, CodingKey, CaseIterable { + case emailHash = "email_hash" + } + + + + + // Encodable protocol methods + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: InternalCodingKeys.self) + try container.encode(emailHash, forKey: .emailHash) + } + + + // Decodable protocol methods + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: InternalCodingKeys.self) + + emailHash = try container.decode(String.self, forKey: .emailHash) + } + + + +} + diff --git a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/VerifiedAccount.swift b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/VerifiedAccount.swift new file mode 100644 index 00000000..4fcf74de --- /dev/null +++ b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/VerifiedAccount.swift @@ -0,0 +1,84 @@ +// +// VerifiedAccount.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + +/// A verified account on a user's profile. +/// +public struct VerifiedAccount: Codable, Hashable, Sendable { + + /// The type of the service. + public private(set) var serviceType: String + /// The name of the service. + public private(set) var serviceLabel: String + /// The URL to the service's icon. + public private(set) var serviceIcon: String + /// The URL to the user's profile on the service. + public private(set) var url: String + /// Whether the verified account is hidden from the user's profile. + public private(set) var isHidden: Bool + + @available(*, deprecated, message: "init will become internal on the next release") + public init(serviceType: String, serviceLabel: String, serviceIcon: String, url: String, isHidden: Bool) { + self.serviceType = serviceType + self.serviceLabel = serviceLabel + self.serviceIcon = serviceIcon + self.url = url + self.isHidden = isHidden + } + + @available(*, deprecated, message: "CodingKeys will become internal on the next release.") + public enum CodingKeys: String, CodingKey, CaseIterable { + case serviceType = "service_type" + case serviceLabel = "service_label" + case serviceIcon = "service_icon" + case url + case isHidden = "is_hidden" + } + + + + + internal enum InternalCodingKeys: String, CodingKey, CaseIterable { + case serviceType = "service_type" + case serviceLabel = "service_label" + case serviceIcon = "service_icon" + case url + case isHidden = "is_hidden" + } + + + + + // Encodable protocol methods + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: InternalCodingKeys.self) + try container.encode(serviceType, forKey: .serviceType) + try container.encode(serviceLabel, forKey: .serviceLabel) + try container.encode(serviceIcon, forKey: .serviceIcon) + try container.encode(url, forKey: .url) + try container.encode(isHidden, forKey: .isHidden) + } + + + // Decodable protocol methods + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: InternalCodingKeys.self) + + serviceType = try container.decode(String.self, forKey: .serviceType) + serviceLabel = try container.decode(String.self, forKey: .serviceLabel) + serviceIcon = try container.decode(String.self, forKey: .serviceIcon) + url = try container.decode(String.self, forKey: .url) + isHidden = try container.decode(Bool.self, forKey: .isHidden) + } + + + +} + diff --git a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/OpenISO8601DateFormatter.swift b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/OpenISO8601DateFormatter.swift new file mode 100644 index 00000000..cc328880 --- /dev/null +++ b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/OpenISO8601DateFormatter.swift @@ -0,0 +1,56 @@ +// +// OpenISO8601DateFormatter.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + +// https://stackoverflow.com/a/50281094/976628 +public 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 + }() + + static let withoutTime: 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" + 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 public func date(from string: String) -> Date? { + if let result = super.date(from: string) { + return result + } else if let result = OpenISO8601DateFormatter.withoutSeconds.date(from: string) { + return result + } + + return OpenISO8601DateFormatter.withoutTime.date(from: string) + } +} diff --git a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/SynchronizedDictionary.swift b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/SynchronizedDictionary.swift new file mode 100644 index 00000000..acf7ff40 --- /dev/null +++ b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/SynchronizedDictionary.swift @@ -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/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/URLSessionImplementations.swift b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/URLSessionImplementations.swift new file mode 100644 index 00000000..3813d86c --- /dev/null +++ b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/URLSessionImplementations.swift @@ -0,0 +1,648 @@ +// URLSessionImplementations.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation +#if !os(macOS) +import MobileCoreServices +#endif +#if canImport(UniformTypeIdentifiers) +import UniformTypeIdentifiers +#endif + +public protocol URLSessionProtocol { + func dataTask(with request: URLRequest, completionHandler: @escaping @Sendable (Data?, URLResponse?, Error?) -> Void) -> URLSessionDataTask +} + +extension URLSession: URLSessionProtocol {} + +class URLSessionRequestBuilderFactory: RequestBuilderFactory { + func getNonDecodableBuilder() -> RequestBuilder.Type { + return URLSessionRequestBuilder.self + } + + func getBuilder() -> RequestBuilder.Type { + return URLSessionDecodableRequestBuilder.self + } +} + +public typealias OpenAPIClientAPIChallengeHandler = ((URLSession, URLSessionTask, URLAuthenticationChallenge) -> (URLSession.AuthChallengeDisposition, URLCredential?)) + +// Store the URLSession's delegate to retain its reference +private let sessionDelegate = SessionDelegate() + +// Store the URLSession to retain its reference +private let defaultURLSession = URLSession(configuration: .default, delegate: sessionDelegate, delegateQueue: nil) + +// Store current taskDidReceiveChallenge for every URLSessionTask +private var challengeHandlerStore = SynchronizedDictionary() + +// Store current URLCredential for every URLSessionTask +private var credentialStore = SynchronizedDictionary() + +open class URLSessionRequestBuilder: RequestBuilder { + + /** + May be assigned if you want to control the authentication challenges. + */ + public var taskDidReceiveChallenge: OpenAPIClientAPIChallengeHandler? + + required public init(method: String, URLString: String, parameters: [String: Any]?, headers: [String: String] = [:], requiresAuthentication: Bool) { + super.init(method: method, URLString: URLString, parameters: parameters, headers: headers, requiresAuthentication: requiresAuthentication) + } + + /** + May be overridden by a subclass if you want to control the URLSession + configuration. + */ + open func createURLSession() -> URLSessionProtocol { + return defaultURLSession + } + + /** + May be overridden by a subclass if you want to control the Content-Type + that is given to an uploaded form part. + + Return nil to use the default behavior (inferring the Content-Type from + the file extension). Return the desired Content-Type otherwise. + */ + open func contentTypeForFormPart(fileURL: URL) -> String? { + return nil + } + + /** + May be overridden by a subclass if you want to control the URLRequest + configuration (e.g. to override the cache policy). + */ + open func createURLRequest(urlSession: URLSessionProtocol, method: HTTPMethod, encoding: ParameterEncoding, headers: [String: String]) throws -> URLRequest { + + guard let url = URL(string: URLString) else { + throw DownloadException.requestMissingURL + } + + var originalRequest = URLRequest(url: url) + + originalRequest.httpMethod = method.rawValue + + buildHeaders().forEach { key, value in + originalRequest.setValue(value, forHTTPHeaderField: key) + } + + let modifiedRequest = try encoding.encode(originalRequest, with: parameters) + + return modifiedRequest + } + + @discardableResult + override open func execute(_ apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, _ completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) -> RequestTask { + let urlSession = createURLSession() + + guard let xMethod = HTTPMethod(rawValue: method) else { + fatalError("Unsupported Http method - \(method)") + } + + let encoding: ParameterEncoding + + switch xMethod { + case .get, .head: + encoding = URLEncoding() + + case .options, .post, .put, .patch, .delete, .trace, .connect: + let contentType = headers["Content-Type"] ?? "application/json" + + if contentType.hasPrefix("application/json") { + encoding = JSONDataEncoding() + } else if contentType.hasPrefix("multipart/form-data") { + encoding = FormDataEncoding(contentTypeForFormPart: contentTypeForFormPart(fileURL:)) + } else if contentType.hasPrefix("application/x-www-form-urlencoded") { + encoding = FormURLEncoding() + } else if contentType.hasPrefix("application/octet-stream"){ + encoding = OctetStreamEncoding() + } else { + fatalError("Unsupported Media Type - \(contentType)") + } + } + + do { + let request = try createURLRequest(urlSession: urlSession, method: xMethod, encoding: encoding, headers: headers) + + var taskIdentifier: Int? + let cleanupRequest = { + if let taskIdentifier = taskIdentifier { + challengeHandlerStore[taskIdentifier] = nil + credentialStore[taskIdentifier] = nil + } + } + + let dataTask = urlSession.dataTask(with: request) { data, response, error in + apiResponseQueue.async { + self.processRequestResponse(urlRequest: request, data: data, response: response, error: error, completion: completion) + cleanupRequest() + } + } + + onProgressReady?(dataTask.progress) + + taskIdentifier = dataTask.taskIdentifier + challengeHandlerStore[dataTask.taskIdentifier] = taskDidReceiveChallenge + credentialStore[dataTask.taskIdentifier] = credential + + dataTask.resume() + + requestTask.set(task: dataTask) + } catch { + apiResponseQueue.async { + completion(.failure(ErrorResponse.error(415, nil, nil, error))) + } + } + + return requestTask + } + + fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, response: URLResponse?, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { + + if let error = error { + completion(.failure(ErrorResponse.error(-1, data, response, error))) + return + } + + guard let httpResponse = response as? HTTPURLResponse else { + completion(.failure(ErrorResponse.error(-2, data, response, DecodableRequestBuilderError.nilHTTPResponse))) + return + } + + guard httpResponse.isStatusCodeSuccessful else { + completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, response, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode))) + return + } + + switch T.self { + case is Void.Type: + + completion(.success(Response(response: httpResponse, body: () as! T, bodyData: data))) + + default: + fatalError("Unsupported Response Body Type - \(String(describing: T.self))") + } + + } + + open func buildHeaders() -> [String: String] { + var httpHeaders: [String: String] = [:] + for (key, value) in OpenAPIClientAPI.customHeaders { + httpHeaders[key] = value + } + for (key, value) in headers { + httpHeaders[key] = value + } + return httpHeaders + } + + fileprivate func getFileName(fromContentDisposition contentDisposition: String?) -> String? { + + guard let contentDisposition = contentDisposition else { + return nil + } + + let items = contentDisposition.components(separatedBy: ";") + + var filename: String? + + for contentItem in items { + + let filenameKey = "filename=" + guard let range = contentItem.range(of: filenameKey) else { + continue + } + + filename = contentItem + return filename? + .replacingCharacters(in: range, with: "") + .replacingOccurrences(of: "\"", with: "") + .trimmingCharacters(in: .whitespacesAndNewlines) + } + + return filename + + } + + fileprivate func getPath(from url: URL) throws -> String { + + guard var path = URLComponents(url: url, resolvingAgainstBaseURL: true)?.path else { + throw DownloadException.requestMissingPath + } + + if path.hasPrefix("/") { + path.remove(at: path.startIndex) + } + + return path + + } + + fileprivate func getURL(from urlRequest: URLRequest) throws -> URL { + + guard let url = urlRequest.url else { + throw DownloadException.requestMissingURL + } + + return url + } + +} + +open class URLSessionDecodableRequestBuilder: URLSessionRequestBuilder { + override fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, response: URLResponse?, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { + + if let error = error { + completion(.failure(ErrorResponse.error(-1, data, response, error))) + return + } + + guard let httpResponse = response as? HTTPURLResponse else { + completion(.failure(ErrorResponse.error(-2, data, response, DecodableRequestBuilderError.nilHTTPResponse))) + return + } + + guard httpResponse.isStatusCodeSuccessful else { + completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, response, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode))) + return + } + + switch T.self { + case is String.Type: + + let body = data.flatMap { String(data: $0, encoding: .utf8) } ?? "" + + completion(.success(Response(response: httpResponse, body: body as! T, bodyData: data))) + + case is URL.Type: + do { + + guard error == nil else { + throw DownloadException.responseFailed + } + + guard let data = data else { + throw DownloadException.responseDataMissing + } + + let fileManager = FileManager.default + let cachesDirectory = fileManager.urls(for: .cachesDirectory, in: .userDomainMask)[0] + let requestURL = try getURL(from: urlRequest) + + var requestPath = try getPath(from: requestURL) + + if let headerFileName = getFileName(fromContentDisposition: httpResponse.allHeaderFields["Content-Disposition"] as? String) { + requestPath = requestPath.appending("/\(headerFileName)") + } else { + requestPath = requestPath.appending("/tmp.OpenAPIClient.\(UUID().uuidString)") + } + + let filePath = cachesDirectory.appendingPathComponent(requestPath) + let directoryPath = filePath.deletingLastPathComponent().path + + try fileManager.createDirectory(atPath: directoryPath, withIntermediateDirectories: true, attributes: nil) + try data.write(to: filePath, options: .atomic) + + completion(.success(Response(response: httpResponse, body: filePath as! T, bodyData: data))) + + } catch let requestParserError as DownloadException { + completion(.failure(ErrorResponse.error(400, data, response, requestParserError))) + } catch { + completion(.failure(ErrorResponse.error(400, data, response, error))) + } + + case is Void.Type: + + completion(.success(Response(response: httpResponse, body: () as! T, bodyData: data))) + + case is Data.Type: + + completion(.success(Response(response: httpResponse, body: data as! T, bodyData: data))) + + default: + + guard let unwrappedData = data, !unwrappedData.isEmpty else { + if let expressibleByNilLiteralType = T.self as? ExpressibleByNilLiteral.Type { + completion(.success(Response(response: httpResponse, body: expressibleByNilLiteralType.init(nilLiteral: ()) as! T, bodyData: data))) + } else { + completion(.failure(ErrorResponse.error(httpResponse.statusCode, nil, response, DecodableRequestBuilderError.emptyDataResponse))) + } + return + } + + let decodeResult = CodableHelper.decode(T.self, from: unwrappedData) + + switch decodeResult { + case let .success(decodableObj): + completion(.success(Response(response: httpResponse, body: decodableObj, bodyData: unwrappedData))) + case let .failure(error): + completion(.failure(ErrorResponse.error(httpResponse.statusCode, unwrappedData, response, error))) + } + } + } +} + +private class SessionDelegate: NSObject, URLSessionTaskDelegate { + func urlSession(_ session: URLSession, task: URLSessionTask, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { + + var disposition: URLSession.AuthChallengeDisposition = .performDefaultHandling + + var credential: URLCredential? + + if let taskDidReceiveChallenge = challengeHandlerStore[task.taskIdentifier] { + (disposition, credential) = taskDidReceiveChallenge(session, task, challenge) + } else { + if challenge.previousFailureCount > 0 { + disposition = .rejectProtectionSpace + } else { + credential = credentialStore[task.taskIdentifier] ?? session.configuration.urlCredentialStorage?.defaultCredential(for: challenge.protectionSpace) + + if credential != nil { + disposition = .useCredential + } + } + } + + completionHandler(disposition, credential) + } +} + +public enum HTTPMethod: String { + case options = "OPTIONS" + case get = "GET" + case head = "HEAD" + case post = "POST" + case put = "PUT" + case patch = "PATCH" + case delete = "DELETE" + case trace = "TRACE" + case connect = "CONNECT" +} + +public protocol ParameterEncoding { + func encode(_ urlRequest: URLRequest, with parameters: [String: Any]?) throws -> URLRequest +} + +private class URLEncoding: ParameterEncoding { + func encode(_ urlRequest: URLRequest, with parameters: [String: Any]?) throws -> URLRequest { + + var urlRequest = urlRequest + + guard let parameters = parameters else { return urlRequest } + + guard let url = urlRequest.url else { + throw DownloadException.requestMissingURL + } + + if var urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: false), !parameters.isEmpty { + urlComponents.queryItems = APIHelper.mapValuesToQueryItems(parameters) + urlRequest.url = urlComponents.url + } + + return urlRequest + } +} + +private class FormDataEncoding: ParameterEncoding { + + let contentTypeForFormPart: (_ fileURL: URL) -> String? + + init(contentTypeForFormPart: @escaping (_ fileURL: URL) -> String?) { + self.contentTypeForFormPart = contentTypeForFormPart + } + + func encode(_ urlRequest: URLRequest, with parameters: [String: Any]?) throws -> URLRequest { + + var urlRequest = urlRequest + + guard let parameters = parameters, !parameters.isEmpty else { + return urlRequest + } + + let boundary = "Boundary-\(UUID().uuidString)" + + urlRequest.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type") + + for (key, value) in parameters { + for value in (value as? Array ?? [value]) { + switch value { + case let fileURL as URL: + + urlRequest = try configureFileUploadRequest( + urlRequest: urlRequest, + boundary: boundary, + name: key, + fileURL: fileURL + ) + + case let string as String: + + if let data = string.data(using: .utf8) { + urlRequest = configureDataUploadRequest( + urlRequest: urlRequest, + boundary: boundary, + name: key, + data: data + ) + } + + case let number as NSNumber: + + if let data = number.stringValue.data(using: .utf8) { + urlRequest = configureDataUploadRequest( + urlRequest: urlRequest, + boundary: boundary, + name: key, + data: data + ) + } + + case let data as Data: + + urlRequest = configureDataUploadRequest( + urlRequest: urlRequest, + boundary: boundary, + name: key, + data: data + ) + + case let uuid as UUID: + + if let data = uuid.uuidString.data(using: .utf8) { + urlRequest = configureDataUploadRequest( + urlRequest: urlRequest, + boundary: boundary, + name: key, + data: data + ) + } + + default: + fatalError("Unprocessable value \(value) with key \(key)") + } + } + } + + var body = urlRequest.httpBody.orEmpty + + body.append("\r\n--\(boundary)--\r\n") + + urlRequest.httpBody = body + + return urlRequest + } + + private func configureFileUploadRequest(urlRequest: URLRequest, boundary: String, name: String, fileURL: URL) throws -> URLRequest { + + var urlRequest = urlRequest + + var body = urlRequest.httpBody.orEmpty + + let fileData = try Data(contentsOf: fileURL) + + let mimetype = contentTypeForFormPart(fileURL) ?? mimeType(for: fileURL) + + let fileName = fileURL.lastPathComponent + + // If we already added something then we need an additional newline. + if body.count > 0 { + body.append("\r\n") + } + + // Value boundary. + body.append("--\(boundary)\r\n") + + // Value headers. + body.append("Content-Disposition: form-data; name=\"\(name)\"; filename=\"\(fileName)\"\r\n") + body.append("Content-Type: \(mimetype)\r\n") + + // Separate headers and body. + body.append("\r\n") + + // The value data. + body.append(fileData) + + urlRequest.httpBody = body + + return urlRequest + } + + private func configureDataUploadRequest(urlRequest: URLRequest, boundary: String, name: String, data: Data) -> URLRequest { + + var urlRequest = urlRequest + + var body = urlRequest.httpBody.orEmpty + + // If we already added something then we need an additional newline. + if body.count > 0 { + body.append("\r\n") + } + + // Value boundary. + body.append("--\(boundary)\r\n") + + // Value headers. + body.append("Content-Disposition: form-data; name=\"\(name)\"\r\n") + + // Separate headers and body. + body.append("\r\n") + + // The value data. + body.append(data) + + urlRequest.httpBody = body + + return urlRequest + + } + + func mimeType(for url: URL) -> String { + let pathExtension = url.pathExtension + + if #available(iOS 15, macOS 11, *) { + #if canImport(UniformTypeIdentifiers) + if let utType = UTType(filenameExtension: pathExtension) { + return utType.preferredMIMEType ?? "application/octet-stream" + } + #else + return "application/octet-stream" + #endif + } else { + if let uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, pathExtension as NSString, nil)?.takeRetainedValue(), + let mimetype = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType)?.takeRetainedValue() { + return mimetype as String + } + return "application/octet-stream" + } + return "application/octet-stream" + } + +} + +private class FormURLEncoding: ParameterEncoding { + func encode(_ urlRequest: URLRequest, with parameters: [String: Any]?) throws -> URLRequest { + + var urlRequest = urlRequest + + var requestBodyComponents = URLComponents() + requestBodyComponents.queryItems = APIHelper.mapValuesToQueryItems(parameters ?? [:]) + + if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil { + urlRequest.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type") + } + + urlRequest.httpBody = requestBodyComponents.query?.data(using: .utf8) + + return urlRequest + } +} + +private class OctetStreamEncoding: ParameterEncoding { + func encode(_ urlRequest: URLRequest, with parameters: [String: Any]?) throws -> URLRequest { + + var urlRequest = urlRequest + + guard let body = parameters?["body"] else { return urlRequest } + + if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil { + urlRequest.setValue("application/octet-stream", forHTTPHeaderField: "Content-Type") + } + + switch body { + case let fileURL as URL: + urlRequest.httpBody = try Data(contentsOf: fileURL) + case let data as Data: + urlRequest.httpBody = data + default: + fatalError("Unprocessable body \(body)") + } + + return urlRequest + } +} + +private extension Data { + /// Append string to Data + /// + /// Rather than littering my code with calls to `dataUsingEncoding` to convert strings to Data, and then add that data to the Data, this wraps it in a nice convenient little extension to Data. This converts using UTF-8. + /// + /// - parameter string: The string to be added to the `Data`. + + mutating func append(_ string: String) { + if let data = string.data(using: .utf8) { + append(data) + } + } +} + +private extension Optional where Wrapped == Data { + var orEmpty: Data { + self ?? Data() + } +} + +extension JSONDataEncoding: ParameterEncoding {} diff --git a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Validation.swift b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Validation.swift new file mode 100644 index 00000000..b520bd7e --- /dev/null +++ b/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Validation.swift @@ -0,0 +1,126 @@ +// Validation.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + +public struct StringRule { + public var minLength: Int? + public var maxLength: Int? + public var pattern: String? +} + +public struct NumericRule { + public var minimum: T? + public var exclusiveMinimum = false + public var maximum: T? + public var exclusiveMaximum = false + public var multipleOf: T? +} + +public enum StringValidationErrorKind: Error { + case minLength, maxLength, pattern +} + +public enum NumericValidationErrorKind: Error { + case minimum, maximum, multipleOf +} + +public struct ValidationError: Error { + public fileprivate(set) var kinds: Set +} + +public struct Validator { + /// Validate a string against a rule. + /// - Parameter string: The String you wish to validate. + /// - Parameter rule: The StringRule you wish to use for validation. + /// - Returns: A validated string. + /// - Throws: `ValidationError` if the string is invalid against the rule, + /// `NSError` if the rule.pattern is invalid. + public static func validate(_ string: String, against rule: StringRule) throws -> String { + var error = ValidationError(kinds: []) + if let minLength = rule.minLength, !(minLength <= string.count) { + error.kinds.insert(.minLength) + } + if let maxLength = rule.maxLength, !(string.count <= maxLength) { + error.kinds.insert(.maxLength) + } + if let pattern = rule.pattern { + let matches = try NSRegularExpression(pattern: pattern, options: .caseInsensitive) + .matches(in: string, range: .init(location: 0, length: string.utf16.count)) + if matches.isEmpty { + error.kinds.insert(.pattern) + } + } + guard error.kinds.isEmpty else { + throw error + } + return string + } + + /// Validate a integer against a rule. + /// - Parameter numeric: The integer you wish to validate. + /// - Parameter rule: The NumericRule you wish to use for validation. + /// - Returns: A validated integer. + /// - Throws: `ValidationError` if the numeric is invalid against the rule. + public static func validate(_ numeric: T, against rule: NumericRule) throws -> T { + var error = ValidationError(kinds: []) + if let minium = rule.minimum { + if !rule.exclusiveMinimum, minium > numeric { + error.kinds.insert(.minimum) + } + if rule.exclusiveMinimum, minium >= numeric { + error.kinds.insert(.minimum) + } + } + if let maximum = rule.maximum { + if !rule.exclusiveMaximum, numeric > maximum { + error.kinds.insert(.maximum) + } + if rule.exclusiveMaximum, numeric >= maximum { + error.kinds.insert(.maximum) + } + } + if let multipleOf = rule.multipleOf, !numeric.isMultiple(of: multipleOf) { + error.kinds.insert(.multipleOf) + } + guard error.kinds.isEmpty else { + throw error + } + return numeric + } + + /// Validate a fractional number against a rule. + /// - Parameter numeric: The fractional number you wish to validate. + /// - Parameter rule: The NumericRule you wish to use for validation. + /// - Returns: A validated fractional number. + /// - Throws: `ValidationError` if the numeric is invalid against the rule. + public static func validate(_ numeric: T, against rule: NumericRule) throws -> T { + var error = ValidationError(kinds: []) + if let minium = rule.minimum { + if !rule.exclusiveMinimum, minium > numeric { + error.kinds.insert(.minimum) + } + if rule.exclusiveMinimum, minium >= numeric { + error.kinds.insert(.minimum) + } + } + if let maximum = rule.maximum { + if !rule.exclusiveMaximum, numeric > maximum { + error.kinds.insert(.maximum) + } + if rule.exclusiveMaximum, numeric >= maximum { + error.kinds.insert(.maximum) + } + } + if let multipleOf = rule.multipleOf, numeric.remainder(dividingBy: multipleOf) != 0 { + error.kinds.insert(.multipleOf) + } + guard error.kinds.isEmpty else { + throw error + } + return numeric + } +} diff --git a/openapi/GravatarOpenAPIClient/docs/AssociatedResponse.md b/openapi/GravatarOpenAPIClient/docs/AssociatedResponse.md new file mode 100644 index 00000000..8c31021b --- /dev/null +++ b/openapi/GravatarOpenAPIClient/docs/AssociatedResponse.md @@ -0,0 +1,10 @@ +# AssociatedResponse + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**associated** | **Bool** | Whether the entity is associated with the account. | + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/openapi/GravatarOpenAPIClient/docs/Avatar.md b/openapi/GravatarOpenAPIClient/docs/Avatar.md new file mode 100644 index 00000000..65827a4d --- /dev/null +++ b/openapi/GravatarOpenAPIClient/docs/Avatar.md @@ -0,0 +1,15 @@ +# Avatar + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**imageId** | **String** | Unique identifier for the image. | +**imageUrl** | **String** | Image URL | +**rating** | **String** | Rating associated with the image. | +**updatedDate** | **Date** | Date and time when the image was last updated. | +**altText** | **String** | Alternative text description of the image. | +**selected** | **Bool** | Whether the image is currently selected as the provided selected email's avatar. | [optional] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/openapi/GravatarOpenAPIClient/docs/AvatarsAPI.md b/openapi/GravatarOpenAPIClient/docs/AvatarsAPI.md new file mode 100644 index 00000000..b630d636 --- /dev/null +++ b/openapi/GravatarOpenAPIClient/docs/AvatarsAPI.md @@ -0,0 +1,163 @@ +# AvatarsAPI + +All URIs are relative to *https://api.gravatar.com/v3* + +Method | HTTP request | Description +------------- | ------------- | ------------- +[**getAvatars**](AvatarsAPI.md#getavatars) | **GET** /me/avatars | List avatars +[**setEmailAvatar**](AvatarsAPI.md#setemailavatar) | **POST** /me/avatars/{imageId}/email | Set avatar for the hashed email +[**uploadAvatar**](AvatarsAPI.md#uploadavatar) | **POST** /me/avatars | Upload new avatar image + + +# **getAvatars** +```swift + open class func getAvatars(selectedEmailHash: String? = nil, completion: @escaping (_ data: [Avatar]?, _ error: Error?) -> Void) +``` + +List avatars + +Retrieves a list of available avatars for the authenticated user. + +### Example +```swift +// The following code samples are still beta. For any issue, please report via http://github.com/OpenAPITools/openapi-generator/issues/new +import OpenAPIClient + +let selectedEmailHash = "selectedEmailHash_example" // String | The sha256 hash of the email address used to determine which avatar is selected. The 'selected' attribute in the avatar list will be set to 'true' for the avatar associated with this email. (optional) (default to "null") + +// List avatars +AvatarsAPI.getAvatars(selectedEmailHash: selectedEmailHash) { (response, error) in + guard error == nil else { + print(error) + return + } + + if (response) { + dump(response) + } +} +``` + +### Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **selectedEmailHash** | **String** | The sha256 hash of the email address used to determine which avatar is selected. The 'selected' attribute in the avatar list will be set to 'true' for the avatar associated with this email. | [optional] [default to "null"] + +### Return type + +[**[Avatar]**](Avatar.md) + +### Authorization + +[oauth](../README.md#oauth) + +### HTTP request headers + + - **Content-Type**: Not defined + - **Accept**: application/json + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + +# **setEmailAvatar** +```swift + open class func setEmailAvatar(imageId: String, setEmailAvatarRequest: SetEmailAvatarRequest, completion: @escaping (_ data: Void?, _ error: Error?) -> Void) +``` + +Set avatar for the hashed email + +Sets the avatar for the provided email hash. + +### Example +```swift +// The following code samples are still beta. For any issue, please report via http://github.com/OpenAPITools/openapi-generator/issues/new +import OpenAPIClient + +let imageId = "imageId_example" // String | Image ID of the avatar to set as the provided hashed email avatar. +let setEmailAvatarRequest = setEmailAvatar_request(emailHash: "emailHash_example") // SetEmailAvatarRequest | Avatar selection details + +// Set avatar for the hashed email +AvatarsAPI.setEmailAvatar(imageId: imageId, setEmailAvatarRequest: setEmailAvatarRequest) { (response, error) in + guard error == nil else { + print(error) + return + } + + if (response) { + dump(response) + } +} +``` + +### Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **imageId** | **String** | Image ID of the avatar to set as the provided hashed email avatar. | + **setEmailAvatarRequest** | [**SetEmailAvatarRequest**](SetEmailAvatarRequest.md) | Avatar selection details | + +### Return type + +Void (empty response body) + +### Authorization + +[oauth](../README.md#oauth) + +### HTTP request headers + + - **Content-Type**: application/json + - **Accept**: application/json + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + +# **uploadAvatar** +```swift + open class func uploadAvatar(data: URL, completion: @escaping (_ data: Avatar?, _ error: Error?) -> Void) +``` + +Upload new avatar image + +Uploads a new avatar image for the authenticated user. + +### Example +```swift +// The following code samples are still beta. For any issue, please report via http://github.com/OpenAPITools/openapi-generator/issues/new +import OpenAPIClient + +let data = URL(string: "https://example.com")! // URL | The avatar image file + +// Upload new avatar image +AvatarsAPI.uploadAvatar(data: data) { (response, error) in + guard error == nil else { + print(error) + return + } + + if (response) { + dump(response) + } +} +``` + +### Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **data** | **URL** | The avatar image file | + +### Return type + +[**Avatar**](Avatar.md) + +### Authorization + +[oauth](../README.md#oauth) + +### HTTP request headers + + - **Content-Type**: multipart/form-data + - **Accept**: application/json + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + diff --git a/openapi/GravatarOpenAPIClient/docs/CryptoWalletAddress.md b/openapi/GravatarOpenAPIClient/docs/CryptoWalletAddress.md new file mode 100644 index 00000000..b295c2e1 --- /dev/null +++ b/openapi/GravatarOpenAPIClient/docs/CryptoWalletAddress.md @@ -0,0 +1,11 @@ +# CryptoWalletAddress + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**label** | **String** | The label for the crypto currency. | +**address** | **String** | The wallet address for the crypto currency. | + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/openapi/GravatarOpenAPIClient/docs/GalleryImage.md b/openapi/GravatarOpenAPIClient/docs/GalleryImage.md new file mode 100644 index 00000000..c3055dd5 --- /dev/null +++ b/openapi/GravatarOpenAPIClient/docs/GalleryImage.md @@ -0,0 +1,11 @@ +# GalleryImage + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**url** | **String** | The URL to the image. | +**altText** | **String** | The image alt text. | [optional] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/openapi/GravatarOpenAPIClient/docs/Interest.md b/openapi/GravatarOpenAPIClient/docs/Interest.md new file mode 100644 index 00000000..fb2ec879 --- /dev/null +++ b/openapi/GravatarOpenAPIClient/docs/Interest.md @@ -0,0 +1,11 @@ +# Interest + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**id** | **Int** | The unique identifier for the interest. | +**name** | **String** | The name of the interest. | + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/openapi/GravatarOpenAPIClient/docs/Language.md b/openapi/GravatarOpenAPIClient/docs/Language.md new file mode 100644 index 00000000..66fe7bd2 --- /dev/null +++ b/openapi/GravatarOpenAPIClient/docs/Language.md @@ -0,0 +1,13 @@ +# Language + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**code** | **String** | The language code. | +**name** | **String** | The language name. | +**isPrimary** | **Bool** | Whether the language is the user's primary language. | +**order** | **Int** | The order of the language in the user's profile. | + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/openapi/GravatarOpenAPIClient/docs/Link.md b/openapi/GravatarOpenAPIClient/docs/Link.md new file mode 100644 index 00000000..6284ba35 --- /dev/null +++ b/openapi/GravatarOpenAPIClient/docs/Link.md @@ -0,0 +1,11 @@ +# Link + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**label** | **String** | The label for the link. | +**url** | **String** | The URL to the link. | + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/openapi/GravatarOpenAPIClient/docs/ModelError.md b/openapi/GravatarOpenAPIClient/docs/ModelError.md new file mode 100644 index 00000000..4eb1b7d0 --- /dev/null +++ b/openapi/GravatarOpenAPIClient/docs/ModelError.md @@ -0,0 +1,11 @@ +# ModelError + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**error** | **String** | The error message | +**code** | **String** | The error code for the error message | [optional] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/openapi/GravatarOpenAPIClient/docs/Profile.md b/openapi/GravatarOpenAPIClient/docs/Profile.md new file mode 100644 index 00000000..e546597f --- /dev/null +++ b/openapi/GravatarOpenAPIClient/docs/Profile.md @@ -0,0 +1,34 @@ +# Profile + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**hash** | **String** | The SHA256 hash of the user's primary email address. | +**displayName** | **String** | The user's display name. This is the name that is displayed on their profile. | +**profileUrl** | **String** | The full URL for the user's profile. | +**avatarUrl** | **String** | The URL for the user's avatar image if it has been set. | +**avatarAltText** | **String** | The alt text for the user's avatar image if it has been set. | +**location** | **String** | The user's location. | +**description** | **String** | The about section on a user's profile. | +**jobTitle** | **String** | The user's job title. | +**company** | **String** | The user's current company's name. | +**verifiedAccounts** | [VerifiedAccount] | A list of verified accounts the user has added to their profile. This is limited to a max of 4 in unauthenticated requests. | +**pronunciation** | **String** | The phonetic pronunciation of the user's name. | +**pronouns** | **String** | The pronouns the user uses. | +**timezone** | **String** | The timezone the user has. This is only provided in authenticated API requests. | [optional] +**languages** | [Language] | The languages the user knows. This is only provided in authenticated API requests. | [optional] +**firstName** | **String** | User's first name. This is only provided in authenticated API requests. | [optional] +**lastName** | **String** | User's last name. This is only provided in authenticated API requests. | [optional] +**isOrganization** | **Bool** | Whether user is an organization. This is only provided in authenticated API requests. | [optional] +**links** | [Link] | A list of links the user has added to their profile. This is only provided in authenticated API requests. | [optional] +**interests** | [Interest] | A list of interests the user has added to their profile. This is only provided in authenticated API requests. | [optional] +**payments** | [**ProfilePayments**](ProfilePayments.md) | | [optional] +**contactInfo** | [**ProfileContactInfo**](ProfileContactInfo.md) | | [optional] +**gallery** | [GalleryImage] | Additional images a user has uploaded. This is only provided in authenticated API requests. | [optional] +**numberVerifiedAccounts** | **Int** | The number of verified accounts the user has added to their profile. This count includes verified accounts the user is hiding from their profile. This is only provided in authenticated API requests. | [optional] +**lastProfileEdit** | **Date** | The date and time (UTC) the user last edited their profile. This is only provided in authenticated API requests. | [optional] +**registrationDate** | **Date** | The date the user registered their account. This is only provided in authenticated API requests. | [optional] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/openapi/GravatarOpenAPIClient/docs/ProfileContactInfo.md b/openapi/GravatarOpenAPIClient/docs/ProfileContactInfo.md new file mode 100644 index 00000000..9345950b --- /dev/null +++ b/openapi/GravatarOpenAPIClient/docs/ProfileContactInfo.md @@ -0,0 +1,15 @@ +# ProfileContactInfo + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**homePhone** | **String** | The user's home phone number. | [optional] +**workPhone** | **String** | The user's work phone number. | [optional] +**cellPhone** | **String** | The user's cell phone number. | [optional] +**email** | **String** | The user's email address as provided on the contact section of the profile. Might differ from their account emails. | [optional] +**contactForm** | **String** | The URL to the user's contact form. | [optional] +**calendar** | **String** | The URL to the user's calendar. | [optional] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/openapi/GravatarOpenAPIClient/docs/ProfilePayments.md b/openapi/GravatarOpenAPIClient/docs/ProfilePayments.md new file mode 100644 index 00000000..880cf4fa --- /dev/null +++ b/openapi/GravatarOpenAPIClient/docs/ProfilePayments.md @@ -0,0 +1,11 @@ +# ProfilePayments + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**links** | [Link] | A list of payment URLs the user has added to their profile. | +**cryptoWallets** | [CryptoWalletAddress] | A list of crypto currencies the user accepts. | + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/openapi/GravatarOpenAPIClient/docs/ProfilesAPI.md b/openapi/GravatarOpenAPIClient/docs/ProfilesAPI.md new file mode 100644 index 00000000..210504f1 --- /dev/null +++ b/openapi/GravatarOpenAPIClient/docs/ProfilesAPI.md @@ -0,0 +1,110 @@ +# ProfilesAPI + +All URIs are relative to *https://api.gravatar.com/v3* + +Method | HTTP request | Description +------------- | ------------- | ------------- +[**associatedEmail**](ProfilesAPI.md#associatedemail) | **GET** /me/associated-email | Check if the email is associated with the authenticated user +[**getProfileById**](ProfilesAPI.md#getprofilebyid) | **GET** /profiles/{profileIdentifier} | Get profile by identifier + + +# **associatedEmail** +```swift + open class func associatedEmail(emailHash: String, completion: @escaping (_ data: AssociatedResponse?, _ error: Error?) -> Void) +``` + +Check if the email is associated with the authenticated user + +Checks if the provided email address is associated with the authenticated user. + +### Example +```swift +// The following code samples are still beta. For any issue, please report via http://github.com/OpenAPITools/openapi-generator/issues/new +import OpenAPIClient + +let emailHash = "emailHash_example" // String | The hash of the email address to check. + +// Check if the email is associated with the authenticated user +ProfilesAPI.associatedEmail(emailHash: emailHash) { (response, error) in + guard error == nil else { + print(error) + return + } + + if (response) { + dump(response) + } +} +``` + +### Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **emailHash** | **String** | The hash of the email address to check. | + +### Return type + +[**AssociatedResponse**](AssociatedResponse.md) + +### Authorization + +[oauth](../README.md#oauth) + +### HTTP request headers + + - **Content-Type**: Not defined + - **Accept**: application/json + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + +# **getProfileById** +```swift + open class func getProfileById(profileIdentifier: String, completion: @escaping (_ data: Profile?, _ error: Error?) -> Void) +``` + +Get profile by identifier + +Returns a profile by the given identifier. + +### Example +```swift +// The following code samples are still beta. For any issue, please report via http://github.com/OpenAPITools/openapi-generator/issues/new +import OpenAPIClient + +let profileIdentifier = "profileIdentifier_example" // String | This can either be an SHA256 hash of an email address or profile URL slug. + +// Get profile by identifier +ProfilesAPI.getProfileById(profileIdentifier: profileIdentifier) { (response, error) in + guard error == nil else { + print(error) + return + } + + if (response) { + dump(response) + } +} +``` + +### Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **profileIdentifier** | **String** | This can either be an SHA256 hash of an email address or profile URL slug. | + +### Return type + +[**Profile**](Profile.md) + +### Authorization + +[apiKey](../README.md#apiKey) + +### HTTP request headers + + - **Content-Type**: Not defined + - **Accept**: application/json + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + diff --git a/openapi/GravatarOpenAPIClient/docs/SetEmailAvatarRequest.md b/openapi/GravatarOpenAPIClient/docs/SetEmailAvatarRequest.md new file mode 100644 index 00000000..a8f4f0ae --- /dev/null +++ b/openapi/GravatarOpenAPIClient/docs/SetEmailAvatarRequest.md @@ -0,0 +1,10 @@ +# SetEmailAvatarRequest + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**emailHash** | **String** | The email SHA256 hash to set the avatar for. | + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/openapi/GravatarOpenAPIClient/docs/VerifiedAccount.md b/openapi/GravatarOpenAPIClient/docs/VerifiedAccount.md new file mode 100644 index 00000000..d3fb6545 --- /dev/null +++ b/openapi/GravatarOpenAPIClient/docs/VerifiedAccount.md @@ -0,0 +1,14 @@ +# VerifiedAccount + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**serviceType** | **String** | The type of the service. | +**serviceLabel** | **String** | The name of the service. | +**serviceIcon** | **String** | The URL to the service's icon. | +**url** | **String** | The URL to the user's profile on the service. | +**isHidden** | **Bool** | Whether the verified account is hidden from the user's profile. | + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/openapi/GravatarOpenAPIClient/project.yml b/openapi/GravatarOpenAPIClient/project.yml new file mode 100644 index 00000000..69390791 --- /dev/null +++ b/openapi/GravatarOpenAPIClient/project.yml @@ -0,0 +1,15 @@ +name: OpenAPIClient +targets: + OpenAPIClient: + type: framework + platform: iOS + deploymentTarget: "11.0" + sources: [Sources] + info: + path: ./Info.plist + version: 3.0.0 + settings: + APPLICATION_EXTENSION_API_ONLY: true + scheme: {} + dependencies: + - carthage: AnyCodable diff --git a/openapi/spec.yaml b/openapi/openapi.yaml similarity index 100% rename from openapi/spec.yaml rename to openapi/openapi.yaml diff --git a/openapi/model.mustache b/openapi/templates/model.mustache similarity index 100% rename from openapi/model.mustache rename to openapi/templates/model.mustache diff --git a/openapi/modelInlineEnumDeclaration.mustache b/openapi/templates/modelInlineEnumDeclaration.mustache similarity index 100% rename from openapi/modelInlineEnumDeclaration.mustache rename to openapi/templates/modelInlineEnumDeclaration.mustache diff --git a/openapi/modelObject.mustache b/openapi/templates/modelObject.mustache similarity index 100% rename from openapi/modelObject.mustache rename to openapi/templates/modelObject.mustache From 110ebc2b7e754f1ca865969829dc786cb6a0f50f Mon Sep 17 00:00:00 2001 From: Andrew Montgomery Date: Fri, 4 Oct 2024 17:08:20 -0500 Subject: [PATCH 02/20] Setup local package dependency --- Package.resolved | 11 +- Package.swift | 2 + .../Generated/AssociatedResponse.swift | 35 --- .../Gravatar/OpenApi/Generated/Avatar.swift | 79 ----- .../Generated/CryptoWalletAddress.swift | 44 --- .../OpenApi/Generated/GalleryImage.swift | 49 ---- .../Gravatar/OpenApi/Generated/Interest.swift | 44 --- .../Gravatar/OpenApi/Generated/Language.swift | 58 ---- Sources/Gravatar/OpenApi/Generated/Link.swift | 44 --- .../OpenApi/Generated/ModelError.swift | 44 --- .../Gravatar/OpenApi/Generated/Profile.swift | 274 ------------------ .../Generated/ProfileContactInfo.swift | 79 ----- .../OpenApi/Generated/ProfilePayments.swift | 44 --- .../Generated/SetEmailAvatarRequest.swift | 25 -- .../OpenApi/Generated/VerifiedAccount.swift | 75 ----- 15 files changed, 12 insertions(+), 895 deletions(-) delete mode 100644 Sources/Gravatar/OpenApi/Generated/AssociatedResponse.swift delete mode 100644 Sources/Gravatar/OpenApi/Generated/Avatar.swift delete mode 100644 Sources/Gravatar/OpenApi/Generated/CryptoWalletAddress.swift delete mode 100644 Sources/Gravatar/OpenApi/Generated/GalleryImage.swift delete mode 100644 Sources/Gravatar/OpenApi/Generated/Interest.swift delete mode 100644 Sources/Gravatar/OpenApi/Generated/Language.swift delete mode 100644 Sources/Gravatar/OpenApi/Generated/Link.swift delete mode 100644 Sources/Gravatar/OpenApi/Generated/ModelError.swift delete mode 100644 Sources/Gravatar/OpenApi/Generated/Profile.swift delete mode 100644 Sources/Gravatar/OpenApi/Generated/ProfileContactInfo.swift delete mode 100644 Sources/Gravatar/OpenApi/Generated/ProfilePayments.swift delete mode 100644 Sources/Gravatar/OpenApi/Generated/SetEmailAvatarRequest.swift delete mode 100644 Sources/Gravatar/OpenApi/Generated/VerifiedAccount.swift diff --git a/Package.resolved b/Package.resolved index f1e5bd25..2529a2aa 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,6 +1,15 @@ { - "originHash" : "2d82ed06a27431c1da79790f8b215b8abf6d2a7397f42f02e364c7a92f86a5ab", + "originHash" : "f286c874d53f4f63ae9bc379fe0d0c9b6d434ca00525d0b39b97876e1db9fbbd", "pins" : [ + { + "identity" : "anycodable", + "kind" : "remoteSourceControl", + "location" : "https://github.com/Flight-School/AnyCodable", + "state" : { + "revision" : "862808b2070cd908cb04f9aafe7de83d35f81b05", + "version" : "0.6.7" + } + }, { "identity" : "swift-snapshot-testing", "kind" : "remoteSourceControl", diff --git a/Package.swift b/Package.swift index 375317e6..a59590aa 100644 --- a/Package.swift +++ b/Package.swift @@ -26,12 +26,14 @@ let package = Package( .package(url: "https://github.com/nicklockwood/SwiftFormat", from: "0.54.0"), .package(url: "https://github.com/pointfreeco/swift-snapshot-testing", from: "1.8.1"), .package(url: "https://github.com/SimplyDanny/SwiftLintPlugins", exact: "0.56.2"), + .package(path: "openapi/GravatarOpenAPIClient") ], targets: [ // Targets are the basic building blocks of a package, defining a module or a test suite. // Targets can depend on other targets in this package and products from dependencies. .target( name: "Gravatar", + dependencies: [.product(name: "OpenAPIClient", package: "GravatarOpenAPIClient")], resources: [.process("Resources")], swiftSettings: [ .enableExperimentalFeature("StrictConcurrency") diff --git a/Sources/Gravatar/OpenApi/Generated/AssociatedResponse.swift b/Sources/Gravatar/OpenApi/Generated/AssociatedResponse.swift deleted file mode 100644 index 720277a3..00000000 --- a/Sources/Gravatar/OpenApi/Generated/AssociatedResponse.swift +++ /dev/null @@ -1,35 +0,0 @@ -import Foundation - -struct AssociatedResponse: Codable, Hashable, Sendable { - /// Whether the entity is associated with the account. - private(set) var associated: Bool - - @available(*, deprecated, message: "init will become internal on the next release") - init(associated: Bool) { - self.associated = associated - } - - @available(*, deprecated, message: "CodingKeys will become internal on the next release.") - enum CodingKeys: String, CodingKey, CaseIterable { - case associated - } - - enum InternalCodingKeys: String, CodingKey, CaseIterable { - case associated - } - - // Encodable protocol methods - - func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: InternalCodingKeys.self) - try container.encode(associated, forKey: .associated) - } - - // Decodable protocol methods - - init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: InternalCodingKeys.self) - - associated = try container.decode(Bool.self, forKey: .associated) - } -} diff --git a/Sources/Gravatar/OpenApi/Generated/Avatar.swift b/Sources/Gravatar/OpenApi/Generated/Avatar.swift deleted file mode 100644 index 9441b531..00000000 --- a/Sources/Gravatar/OpenApi/Generated/Avatar.swift +++ /dev/null @@ -1,79 +0,0 @@ -import Foundation - -/// An avatar that the user has already uploaded to their Gravatar account. -/// -package struct Avatar: Codable, Hashable, Sendable { - package enum Rating: String, Codable, CaseIterable, Sendable { - case g = "G" - case pg = "PG" - case r = "R" - case x = "X" - } - - /// Unique identifier for the image. - package private(set) var imageId: String - /// Image URL - package private(set) var imageUrl: String - /// Rating associated with the image. - package private(set) var rating: Rating - /// Date and time when the image was last updated. - package private(set) var updatedDate: Date - /// Alternative text description of the image. - package private(set) var altText: String - /// Whether the image is currently selected as the provided selected email's avatar. - package private(set) var selected: Bool? - - @available(*, deprecated, message: "init will become internal on the next release") - package init(imageId: String, imageUrl: String, rating: Rating, updatedDate: Date, altText: String, selected: Bool? = nil) { - self.imageId = imageId - self.imageUrl = imageUrl - self.rating = rating - self.updatedDate = updatedDate - self.altText = altText - self.selected = selected - } - - @available(*, deprecated, message: "CodingKeys will become internal on the next release.") - package enum CodingKeys: String, CodingKey, CaseIterable { - case imageId = "image_id" - case imageUrl = "image_url" - case rating - case updatedDate = "updated_date" - case altText = "alt_text" - case selected - } - - enum InternalCodingKeys: String, CodingKey, CaseIterable { - case imageId = "image_id" - case imageUrl = "image_url" - case rating - case updatedDate = "updated_date" - case altText = "alt_text" - case selected - } - - // Encodable protocol methods - - package func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: InternalCodingKeys.self) - try container.encode(imageId, forKey: .imageId) - try container.encode(imageUrl, forKey: .imageUrl) - try container.encode(rating, forKey: .rating) - try container.encode(updatedDate, forKey: .updatedDate) - try container.encode(altText, forKey: .altText) - try container.encodeIfPresent(selected, forKey: .selected) - } - - // Decodable protocol methods - - package init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: InternalCodingKeys.self) - - imageId = try container.decode(String.self, forKey: .imageId) - imageUrl = try container.decode(String.self, forKey: .imageUrl) - rating = try container.decode(Rating.self, forKey: .rating) - updatedDate = try container.decode(Date.self, forKey: .updatedDate) - altText = try container.decode(String.self, forKey: .altText) - selected = try container.decodeIfPresent(Bool.self, forKey: .selected) - } -} diff --git a/Sources/Gravatar/OpenApi/Generated/CryptoWalletAddress.swift b/Sources/Gravatar/OpenApi/Generated/CryptoWalletAddress.swift deleted file mode 100644 index ddafe110..00000000 --- a/Sources/Gravatar/OpenApi/Generated/CryptoWalletAddress.swift +++ /dev/null @@ -1,44 +0,0 @@ -import Foundation - -/// A crypto currency wallet address the user accepts. -/// -public struct CryptoWalletAddress: Codable, Hashable, Sendable { - /// The label for the crypto currency. - public private(set) var label: String - /// The wallet address for the crypto currency. - public private(set) var address: String - - @available(*, deprecated, message: "init will become internal on the next release") - public init(label: String, address: String) { - self.label = label - self.address = address - } - - @available(*, deprecated, message: "CodingKeys will become internal on the next release.") - public enum CodingKeys: String, CodingKey, CaseIterable { - case label - case address - } - - enum InternalCodingKeys: String, CodingKey, CaseIterable { - case label - case address - } - - // Encodable protocol methods - - public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: InternalCodingKeys.self) - try container.encode(label, forKey: .label) - try container.encode(address, forKey: .address) - } - - // Decodable protocol methods - - public init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: InternalCodingKeys.self) - - label = try container.decode(String.self, forKey: .label) - address = try container.decode(String.self, forKey: .address) - } -} diff --git a/Sources/Gravatar/OpenApi/Generated/GalleryImage.swift b/Sources/Gravatar/OpenApi/Generated/GalleryImage.swift deleted file mode 100644 index 104ff05c..00000000 --- a/Sources/Gravatar/OpenApi/Generated/GalleryImage.swift +++ /dev/null @@ -1,49 +0,0 @@ -import Foundation - -/// A gallery image a user has uploaded. -/// -public struct GalleryImage: Codable, Hashable, Sendable { - /// The URL to the image. - public private(set) var url: String - /// The image alt text. - public private(set) var altText: String? - - @available(*, deprecated, message: "init will become internal on the next release") - public init(url: String) { - self.url = url - } - - // NOTE: This init is maintained manually. - // Avoid deleting this init until the deprecation of is applied. - init(url: String, altText: String? = nil) { - self.url = url - self.altText = altText - } - - @available(*, deprecated, message: "CodingKeys will become internal on the next release.") - public enum CodingKeys: String, CodingKey, CaseIterable { - case url - } - - enum InternalCodingKeys: String, CodingKey, CaseIterable { - case url - case altText = "alt_text" - } - - // Encodable protocol methods - - public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: InternalCodingKeys.self) - try container.encode(url, forKey: .url) - try container.encodeIfPresent(altText, forKey: .altText) - } - - // Decodable protocol methods - - public init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: InternalCodingKeys.self) - - url = try container.decode(String.self, forKey: .url) - altText = try container.decodeIfPresent(String.self, forKey: .altText) - } -} diff --git a/Sources/Gravatar/OpenApi/Generated/Interest.swift b/Sources/Gravatar/OpenApi/Generated/Interest.swift deleted file mode 100644 index 2ce8cef5..00000000 --- a/Sources/Gravatar/OpenApi/Generated/Interest.swift +++ /dev/null @@ -1,44 +0,0 @@ -import Foundation - -/// An interest the user has added to their profile. -/// -public struct Interest: Codable, Hashable, Sendable { - /// The unique identifier for the interest. - public private(set) var id: Int - /// The name of the interest. - public private(set) var name: String - - @available(*, deprecated, message: "init will become internal on the next release") - public init(id: Int, name: String) { - self.id = id - self.name = name - } - - @available(*, deprecated, message: "CodingKeys will become internal on the next release.") - public enum CodingKeys: String, CodingKey, CaseIterable { - case id - case name - } - - enum InternalCodingKeys: String, CodingKey, CaseIterable { - case id - case name - } - - // Encodable protocol methods - - public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: InternalCodingKeys.self) - try container.encode(id, forKey: .id) - try container.encode(name, forKey: .name) - } - - // Decodable protocol methods - - public init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: InternalCodingKeys.self) - - id = try container.decode(Int.self, forKey: .id) - name = try container.decode(String.self, forKey: .name) - } -} diff --git a/Sources/Gravatar/OpenApi/Generated/Language.swift b/Sources/Gravatar/OpenApi/Generated/Language.swift deleted file mode 100644 index 95f70c9f..00000000 --- a/Sources/Gravatar/OpenApi/Generated/Language.swift +++ /dev/null @@ -1,58 +0,0 @@ -import Foundation - -/// The languages the user knows. This is only provided in authenticated API requests. -/// -public struct Language: Codable, Hashable, Sendable { - /// The language code. - public private(set) var code: String - /// The language name. - public private(set) var name: String - /// Whether the language is the user's primary language. - public private(set) var isPrimary: Bool - /// The order of the language in the user's profile. - public private(set) var order: Int - - @available(*, deprecated, message: "init will become internal on the next release") - public init(code: String, name: String, isPrimary: Bool, order: Int) { - self.code = code - self.name = name - self.isPrimary = isPrimary - self.order = order - } - - @available(*, deprecated, message: "CodingKeys will become internal on the next release.") - public enum CodingKeys: String, CodingKey, CaseIterable { - case code - case name - case isPrimary = "is_primary" - case order - } - - enum InternalCodingKeys: String, CodingKey, CaseIterable { - case code - case name - case isPrimary = "is_primary" - case order - } - - // Encodable protocol methods - - public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: InternalCodingKeys.self) - try container.encode(code, forKey: .code) - try container.encode(name, forKey: .name) - try container.encode(isPrimary, forKey: .isPrimary) - try container.encode(order, forKey: .order) - } - - // Decodable protocol methods - - public init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: InternalCodingKeys.self) - - code = try container.decode(String.self, forKey: .code) - name = try container.decode(String.self, forKey: .name) - isPrimary = try container.decode(Bool.self, forKey: .isPrimary) - order = try container.decode(Int.self, forKey: .order) - } -} diff --git a/Sources/Gravatar/OpenApi/Generated/Link.swift b/Sources/Gravatar/OpenApi/Generated/Link.swift deleted file mode 100644 index 27fd4b81..00000000 --- a/Sources/Gravatar/OpenApi/Generated/Link.swift +++ /dev/null @@ -1,44 +0,0 @@ -import Foundation - -/// A link the user has added to their profile. -/// -public struct Link: Codable, Hashable, Sendable { - /// The label for the link. - public private(set) var label: String - /// The URL to the link. - public private(set) var url: String - - @available(*, deprecated, message: "init will become internal on the next release") - public init(label: String, url: String) { - self.label = label - self.url = url - } - - @available(*, deprecated, message: "CodingKeys will become internal on the next release.") - public enum CodingKeys: String, CodingKey, CaseIterable { - case label - case url - } - - enum InternalCodingKeys: String, CodingKey, CaseIterable { - case label - case url - } - - // Encodable protocol methods - - public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: InternalCodingKeys.self) - try container.encode(label, forKey: .label) - try container.encode(url, forKey: .url) - } - - // Decodable protocol methods - - public init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: InternalCodingKeys.self) - - label = try container.decode(String.self, forKey: .label) - url = try container.decode(String.self, forKey: .url) - } -} diff --git a/Sources/Gravatar/OpenApi/Generated/ModelError.swift b/Sources/Gravatar/OpenApi/Generated/ModelError.swift deleted file mode 100644 index 7da1c59a..00000000 --- a/Sources/Gravatar/OpenApi/Generated/ModelError.swift +++ /dev/null @@ -1,44 +0,0 @@ -import Foundation - -/// An error response from the API. -/// -struct ModelError: Codable, Hashable, Sendable { - /// The error message - private(set) var error: String - /// The error code for the error message - private(set) var code: String? - - @available(*, deprecated, message: "init will become internal on the next release") - init(error: String, code: String? = nil) { - self.error = error - self.code = code - } - - @available(*, deprecated, message: "CodingKeys will become internal on the next release.") - enum CodingKeys: String, CodingKey, CaseIterable { - case error - case code - } - - enum InternalCodingKeys: String, CodingKey, CaseIterable { - case error - case code - } - - // Encodable protocol methods - - func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: InternalCodingKeys.self) - try container.encode(error, forKey: .error) - try container.encodeIfPresent(code, forKey: .code) - } - - // Decodable protocol methods - - init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: InternalCodingKeys.self) - - error = try container.decode(String.self, forKey: .error) - code = try container.decodeIfPresent(String.self, forKey: .code) - } -} diff --git a/Sources/Gravatar/OpenApi/Generated/Profile.swift b/Sources/Gravatar/OpenApi/Generated/Profile.swift deleted file mode 100644 index 84880eb8..00000000 --- a/Sources/Gravatar/OpenApi/Generated/Profile.swift +++ /dev/null @@ -1,274 +0,0 @@ -import Foundation - -/// A user's profile information. -/// -public struct Profile: Codable, Hashable, Sendable { - /// The SHA256 hash of the user's primary email address. - public private(set) var hash: String - /// The user's display name. This is the name that is displayed on their profile. - public private(set) var displayName: String - /// The full URL for the user's profile. - public private(set) var profileUrl: String - /// The URL for the user's avatar image if it has been set. - public private(set) var avatarUrl: String - /// The alt text for the user's avatar image if it has been set. - public private(set) var avatarAltText: String - /// The user's location. - public private(set) var location: String - /// The about section on a user's profile. - public private(set) var description: String - /// The user's job title. - public private(set) var jobTitle: String - /// The user's current company's name. - public private(set) var company: String - /// A list of verified accounts the user has added to their profile. This is limited to a max of 4 in unauthenticated requests. - public private(set) var verifiedAccounts: [VerifiedAccount] - /// The phonetic pronunciation of the user's name. - public private(set) var pronunciation: String - /// The pronouns the user uses. - public private(set) var pronouns: String - /// The timezone the user has. This is only provided in authenticated API requests. - public private(set) var timezone: String? - /// The languages the user knows. This is only provided in authenticated API requests. - public private(set) var languages: [Language]? - /// User's first name. This is only provided in authenticated API requests. - public private(set) var firstName: String? - /// User's last name. This is only provided in authenticated API requests. - public private(set) var lastName: String? - /// Whether user is an organization. This is only provided in authenticated API requests. - public private(set) var isOrganization: Bool? - /// A list of links the user has added to their profile. This is only provided in authenticated API requests. - public private(set) var links: [Link]? - /// A list of interests the user has added to their profile. This is only provided in authenticated API requests. - public private(set) var interests: [Interest]? - public private(set) var payments: ProfilePayments? - public private(set) var contactInfo: ProfileContactInfo? - /// Additional images a user has uploaded. This is only provided in authenticated API requests. - public private(set) var gallery: [GalleryImage]? - /// The number of verified accounts the user has added to their profile. This count includes verified accounts the user is hiding from their profile. This - /// is only provided in authenticated API requests. - public private(set) var numberVerifiedAccounts: Int? - /// The date and time (UTC) the user last edited their profile. This is only provided in authenticated API requests. - public private(set) var lastProfileEdit: Date? - /// The date the user registered their account. This is only provided in authenticated API requests. - public private(set) var registrationDate: Date? - - @available(*, deprecated, message: "init will become internal on the next release") - public init( - hash: String, - displayName: String, - profileUrl: String, - avatarUrl: String, - avatarAltText: String, - location: String, - description: String, - jobTitle: String, - company: String, - verifiedAccounts: [VerifiedAccount], - pronunciation: String, - pronouns: String, - links: [Link]? = nil, - payments: ProfilePayments? = nil, - contactInfo: ProfileContactInfo? = nil, - gallery: [GalleryImage]? = nil, - numberVerifiedAccounts: Int? = nil, - lastProfileEdit: Date? = nil, - registrationDate: Date? = nil - ) { - self.hash = hash - self.displayName = displayName - self.profileUrl = profileUrl - self.avatarUrl = avatarUrl - self.avatarAltText = avatarAltText - self.location = location - self.description = description - self.jobTitle = jobTitle - self.company = company - self.verifiedAccounts = verifiedAccounts - self.pronunciation = pronunciation - self.pronouns = pronouns - self.links = links - self.payments = payments - self.contactInfo = contactInfo - self.gallery = gallery - self.numberVerifiedAccounts = numberVerifiedAccounts - self.lastProfileEdit = lastProfileEdit - self.registrationDate = registrationDate - } - - // NOTE: This init is maintained manually. - // Avoid deleting this init until the deprecation is applied. - init( - hash: String, - displayName: String, - profileUrl: String, - avatarUrl: String, - avatarAltText: String, - location: String, - description: String, - jobTitle: String, - company: String, - verifiedAccounts: [VerifiedAccount], - pronunciation: String, - pronouns: String, - timezone: String? = nil, - languages: [Language]? = nil, - firstName: String? = nil, - lastName: String? = nil, - isOrganization: Bool? = nil, - links: [Link]? = nil, - interests: [Interest]? = nil, - payments: ProfilePayments? = nil, - contactInfo: ProfileContactInfo? = nil, - gallery: [GalleryImage]? = nil, - numberVerifiedAccounts: Int? = nil, - lastProfileEdit: Date? = nil, - registrationDate: Date? = nil - ) { - self.hash = hash - self.displayName = displayName - self.profileUrl = profileUrl - self.avatarUrl = avatarUrl - self.avatarAltText = avatarAltText - self.location = location - self.description = description - self.jobTitle = jobTitle - self.company = company - self.verifiedAccounts = verifiedAccounts - self.pronunciation = pronunciation - self.pronouns = pronouns - self.timezone = timezone - self.languages = languages - self.firstName = firstName - self.lastName = lastName - self.isOrganization = isOrganization - self.links = links - self.interests = interests - self.payments = payments - self.contactInfo = contactInfo - self.gallery = gallery - self.numberVerifiedAccounts = numberVerifiedAccounts - self.lastProfileEdit = lastProfileEdit - self.registrationDate = registrationDate - } - - @available(*, deprecated, message: "CodingKeys will become internal on the next release.") - public enum CodingKeys: String, CodingKey, CaseIterable { - case hash - case displayName = "display_name" - case profileUrl = "profile_url" - case avatarUrl = "avatar_url" - case avatarAltText = "avatar_alt_text" - case location - case description - case jobTitle = "job_title" - case company - case verifiedAccounts = "verified_accounts" - case pronunciation - case pronouns - case timezone - case languages - case firstName = "first_name" - case lastName = "last_name" - case isOrganization = "is_organization" - case links - case interests - case payments - case contactInfo = "contact_info" - case gallery - case numberVerifiedAccounts = "number_verified_accounts" - case lastProfileEdit = "last_profile_edit" - case registrationDate = "registration_date" - } - - enum InternalCodingKeys: String, CodingKey, CaseIterable { - case hash - case displayName = "display_name" - case profileUrl = "profile_url" - case avatarUrl = "avatar_url" - case avatarAltText = "avatar_alt_text" - case location - case description - case jobTitle = "job_title" - case company - case verifiedAccounts = "verified_accounts" - case pronunciation - case pronouns - case timezone - case languages - case firstName = "first_name" - case lastName = "last_name" - case isOrganization = "is_organization" - case links - case interests - case payments - case contactInfo = "contact_info" - case gallery - case numberVerifiedAccounts = "number_verified_accounts" - case lastProfileEdit = "last_profile_edit" - case registrationDate = "registration_date" - } - - // Encodable protocol methods - - public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: InternalCodingKeys.self) - try container.encode(hash, forKey: .hash) - try container.encode(displayName, forKey: .displayName) - try container.encode(profileUrl, forKey: .profileUrl) - try container.encode(avatarUrl, forKey: .avatarUrl) - try container.encode(avatarAltText, forKey: .avatarAltText) - try container.encode(location, forKey: .location) - try container.encode(description, forKey: .description) - try container.encode(jobTitle, forKey: .jobTitle) - try container.encode(company, forKey: .company) - try container.encode(verifiedAccounts, forKey: .verifiedAccounts) - try container.encode(pronunciation, forKey: .pronunciation) - try container.encode(pronouns, forKey: .pronouns) - try container.encodeIfPresent(timezone, forKey: .timezone) - try container.encodeIfPresent(languages, forKey: .languages) - try container.encodeIfPresent(firstName, forKey: .firstName) - try container.encodeIfPresent(lastName, forKey: .lastName) - try container.encodeIfPresent(isOrganization, forKey: .isOrganization) - try container.encodeIfPresent(links, forKey: .links) - try container.encodeIfPresent(interests, forKey: .interests) - try container.encodeIfPresent(payments, forKey: .payments) - try container.encodeIfPresent(contactInfo, forKey: .contactInfo) - try container.encodeIfPresent(gallery, forKey: .gallery) - try container.encodeIfPresent(numberVerifiedAccounts, forKey: .numberVerifiedAccounts) - try container.encodeIfPresent(lastProfileEdit, forKey: .lastProfileEdit) - try container.encodeIfPresent(registrationDate, forKey: .registrationDate) - } - - // Decodable protocol methods - - public init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: InternalCodingKeys.self) - - hash = try container.decode(String.self, forKey: .hash) - displayName = try container.decode(String.self, forKey: .displayName) - profileUrl = try container.decode(String.self, forKey: .profileUrl) - avatarUrl = try container.decode(String.self, forKey: .avatarUrl) - avatarAltText = try container.decode(String.self, forKey: .avatarAltText) - location = try container.decode(String.self, forKey: .location) - description = try container.decode(String.self, forKey: .description) - jobTitle = try container.decode(String.self, forKey: .jobTitle) - company = try container.decode(String.self, forKey: .company) - verifiedAccounts = try container.decode([VerifiedAccount].self, forKey: .verifiedAccounts) - pronunciation = try container.decode(String.self, forKey: .pronunciation) - pronouns = try container.decode(String.self, forKey: .pronouns) - timezone = try container.decodeIfPresent(String.self, forKey: .timezone) - languages = try container.decodeIfPresent([Language].self, forKey: .languages) - firstName = try container.decodeIfPresent(String.self, forKey: .firstName) - lastName = try container.decodeIfPresent(String.self, forKey: .lastName) - isOrganization = try container.decodeIfPresent(Bool.self, forKey: .isOrganization) - links = try container.decodeIfPresent([Link].self, forKey: .links) - interests = try container.decodeIfPresent([Interest].self, forKey: .interests) - payments = try container.decodeIfPresent(ProfilePayments.self, forKey: .payments) - contactInfo = try container.decodeIfPresent(ProfileContactInfo.self, forKey: .contactInfo) - gallery = try container.decodeIfPresent([GalleryImage].self, forKey: .gallery) - numberVerifiedAccounts = try container.decodeIfPresent(Int.self, forKey: .numberVerifiedAccounts) - lastProfileEdit = try container.decodeIfPresent(Date.self, forKey: .lastProfileEdit) - registrationDate = try container.decodeIfPresent(Date.self, forKey: .registrationDate) - } -} diff --git a/Sources/Gravatar/OpenApi/Generated/ProfileContactInfo.swift b/Sources/Gravatar/OpenApi/Generated/ProfileContactInfo.swift deleted file mode 100644 index 2895a6e5..00000000 --- a/Sources/Gravatar/OpenApi/Generated/ProfileContactInfo.swift +++ /dev/null @@ -1,79 +0,0 @@ -import Foundation - -/// The user's contact information. This is only available if the user has chosen to make it public. This is only provided in authenticated API requests. -/// -public struct ProfileContactInfo: Codable, Hashable, Sendable { - /// The user's home phone number. - public private(set) var homePhone: String? - /// The user's work phone number. - public private(set) var workPhone: String? - /// The user's cell phone number. - public private(set) var cellPhone: String? - /// The user's email address as provided on the contact section of the profile. Might differ from their account emails. - public private(set) var email: String? - /// The URL to the user's contact form. - public private(set) var contactForm: String? - /// The URL to the user's calendar. - public private(set) var calendar: String? - - @available(*, deprecated, message: "init will become internal on the next release") - public init( - homePhone: String? = nil, - workPhone: String? = nil, - cellPhone: String? = nil, - email: String? = nil, - contactForm: String? = nil, - calendar: String? = nil - ) { - self.homePhone = homePhone - self.workPhone = workPhone - self.cellPhone = cellPhone - self.email = email - self.contactForm = contactForm - self.calendar = calendar - } - - @available(*, deprecated, message: "CodingKeys will become internal on the next release.") - public enum CodingKeys: String, CodingKey, CaseIterable { - case homePhone = "home_phone" - case workPhone = "work_phone" - case cellPhone = "cell_phone" - case email - case contactForm = "contact_form" - case calendar - } - - enum InternalCodingKeys: String, CodingKey, CaseIterable { - case homePhone = "home_phone" - case workPhone = "work_phone" - case cellPhone = "cell_phone" - case email - case contactForm = "contact_form" - case calendar - } - - // Encodable protocol methods - - public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: InternalCodingKeys.self) - try container.encodeIfPresent(homePhone, forKey: .homePhone) - try container.encodeIfPresent(workPhone, forKey: .workPhone) - try container.encodeIfPresent(cellPhone, forKey: .cellPhone) - try container.encodeIfPresent(email, forKey: .email) - try container.encodeIfPresent(contactForm, forKey: .contactForm) - try container.encodeIfPresent(calendar, forKey: .calendar) - } - - // Decodable protocol methods - - public init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: InternalCodingKeys.self) - - homePhone = try container.decodeIfPresent(String.self, forKey: .homePhone) - workPhone = try container.decodeIfPresent(String.self, forKey: .workPhone) - cellPhone = try container.decodeIfPresent(String.self, forKey: .cellPhone) - email = try container.decodeIfPresent(String.self, forKey: .email) - contactForm = try container.decodeIfPresent(String.self, forKey: .contactForm) - calendar = try container.decodeIfPresent(String.self, forKey: .calendar) - } -} diff --git a/Sources/Gravatar/OpenApi/Generated/ProfilePayments.swift b/Sources/Gravatar/OpenApi/Generated/ProfilePayments.swift deleted file mode 100644 index 841afe2d..00000000 --- a/Sources/Gravatar/OpenApi/Generated/ProfilePayments.swift +++ /dev/null @@ -1,44 +0,0 @@ -import Foundation - -/// The user's public payment information. This is only provided in authenticated API requests. -/// -public struct ProfilePayments: Codable, Hashable, Sendable { - /// A list of payment URLs the user has added to their profile. - public private(set) var links: [Link] - /// A list of crypto currencies the user accepts. - public private(set) var cryptoWallets: [CryptoWalletAddress] - - @available(*, deprecated, message: "init will become internal on the next release") - public init(links: [Link], cryptoWallets: [CryptoWalletAddress]) { - self.links = links - self.cryptoWallets = cryptoWallets - } - - @available(*, deprecated, message: "CodingKeys will become internal on the next release.") - public enum CodingKeys: String, CodingKey, CaseIterable { - case links - case cryptoWallets = "crypto_wallets" - } - - enum InternalCodingKeys: String, CodingKey, CaseIterable { - case links - case cryptoWallets = "crypto_wallets" - } - - // Encodable protocol methods - - public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: InternalCodingKeys.self) - try container.encode(links, forKey: .links) - try container.encode(cryptoWallets, forKey: .cryptoWallets) - } - - // Decodable protocol methods - - public init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: InternalCodingKeys.self) - - links = try container.decode([Link].self, forKey: .links) - cryptoWallets = try container.decode([CryptoWalletAddress].self, forKey: .cryptoWallets) - } -} diff --git a/Sources/Gravatar/OpenApi/Generated/SetEmailAvatarRequest.swift b/Sources/Gravatar/OpenApi/Generated/SetEmailAvatarRequest.swift deleted file mode 100644 index 8b9b0662..00000000 --- a/Sources/Gravatar/OpenApi/Generated/SetEmailAvatarRequest.swift +++ /dev/null @@ -1,25 +0,0 @@ -import Foundation - -struct SetEmailAvatarRequest: Codable, Hashable, Sendable { - /// The email SHA256 hash to set the avatar for. - private(set) var emailHash: String - - enum InternalCodingKeys: String, CodingKey, CaseIterable { - case emailHash = "email_hash" - } - - // Encodable protocol methods - - func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: InternalCodingKeys.self) - try container.encode(emailHash, forKey: .emailHash) - } - - // Decodable protocol methods - - init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: InternalCodingKeys.self) - - emailHash = try container.decode(String.self, forKey: .emailHash) - } -} diff --git a/Sources/Gravatar/OpenApi/Generated/VerifiedAccount.swift b/Sources/Gravatar/OpenApi/Generated/VerifiedAccount.swift deleted file mode 100644 index b0a58047..00000000 --- a/Sources/Gravatar/OpenApi/Generated/VerifiedAccount.swift +++ /dev/null @@ -1,75 +0,0 @@ -import Foundation - -/// A verified account on a user's profile. -/// -public struct VerifiedAccount: Codable, Hashable, Sendable { - /// The type of the service. - public private(set) var serviceType: String - /// The name of the service. - public private(set) var serviceLabel: String - /// The URL to the service's icon. - public private(set) var serviceIcon: String - /// The URL to the user's profile on the service. - public private(set) var url: String - /// Whether the verified account is hidden from the user's profile. - public private(set) var isHidden: Bool - - // NOTE: This init is maintained manually. - // Avoid deleting this init until the deprecation of is applied. - @available(*, deprecated, message: "init will become internal on the next release") - public init(serviceLabel: String, serviceIcon: String, url: String) { - self.init( - serviceType: "", - serviceLabel: serviceLabel, - serviceIcon: serviceIcon, - url: url, - isHidden: false - ) - } - - init(serviceType: String, serviceLabel: String, serviceIcon: String, url: String, isHidden: Bool) { - self.serviceType = serviceType - self.serviceLabel = serviceLabel - self.serviceIcon = serviceIcon - self.url = url - self.isHidden = isHidden - } - - @available(*, deprecated, message: "CodingKeys will become internal on the next release.") - public enum CodingKeys: String, CodingKey, CaseIterable { - case serviceLabel = "service_label" - case serviceIcon = "service_icon" - case url - } - - enum InternalCodingKeys: String, CodingKey, CaseIterable { - case serviceType = "service_type" - case serviceLabel = "service_label" - case serviceIcon = "service_icon" - case url - case isHidden = "is_hidden" - } - - // Encodable protocol methods - - public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: InternalCodingKeys.self) - try container.encode(serviceType, forKey: .serviceType) - try container.encode(serviceLabel, forKey: .serviceLabel) - try container.encode(serviceIcon, forKey: .serviceIcon) - try container.encode(url, forKey: .url) - try container.encode(isHidden, forKey: .isHidden) - } - - // Decodable protocol methods - - public init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: InternalCodingKeys.self) - - serviceType = try container.decode(String.self, forKey: .serviceType) - serviceLabel = try container.decode(String.self, forKey: .serviceLabel) - serviceIcon = try container.decode(String.self, forKey: .serviceIcon) - url = try container.decode(String.self, forKey: .url) - isHidden = try container.decode(Bool.self, forKey: .isHidden) - } -} From 68fd36e79e2fa781827ab012e71baef1209d9086 Mon Sep 17 00:00:00 2001 From: Andrew Montgomery Date: Fri, 4 Oct 2024 17:18:05 -0500 Subject: [PATCH 03/20] Export OpenAPI types --- Sources/Gravatar/OpenAPIExports.swift | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 Sources/Gravatar/OpenAPIExports.swift diff --git a/Sources/Gravatar/OpenAPIExports.swift b/Sources/Gravatar/OpenAPIExports.swift new file mode 100644 index 00000000..a85500b4 --- /dev/null +++ b/Sources/Gravatar/OpenAPIExports.swift @@ -0,0 +1,23 @@ +import OpenAPIClient + +// MARK: OpenAPI Models: Public + +public typealias CryptoWalletAddress = OpenAPIClient.CryptoWalletAddress +public typealias GalleryImage = OpenAPIClient.GalleryImage +public typealias Interest = OpenAPIClient.Interest +public typealias Language = OpenAPIClient.Language +public typealias Link = OpenAPIClient.Link +public typealias Profile = OpenAPIClient.Profile +public typealias ProfileContactInfo = OpenAPIClient.ProfileContactInfo +public typealias ProfilePayments = OpenAPIClient.ProfilePayments +public typealias VerifiedAccount = OpenAPIClient.VerifiedAccount + +// MARK: - OpenAPI Models: Package + +package typealias Avatar = OpenAPIClient.Avatar + +// MARK: - OpenAPI Models: Internal + +typealias AssociatedResponse = OpenAPIClient.AssociatedResponse +typealias ModelError = OpenAPIClient.ModelError +typealias SetEmailAvatarRequest = OpenAPIClient.SetEmailAvatarRequest From 667a4292b304baa81a75dc787b52c42371f51bcd Mon Sep 17 00:00:00 2001 From: Andrew Montgomery Date: Tue, 8 Oct 2024 14:02:37 -0500 Subject: [PATCH 04/20] Refactor openapi-generator call --- Makefile | 14 ++++++++++---- openapi/templates/Podspec.mustache | 22 ++++++++++++++++++++++ 2 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 openapi/templates/Podspec.mustache diff --git a/Makefile b/Makefile index 3bb4fa70..6402f3e3 100644 --- a/Makefile +++ b/Makefile @@ -28,6 +28,10 @@ CURRENT_MAKEFILE_DIR := $(patsubst %/,%,$(dir $(CURRENT_MAKEFILE_PATH))) SCHEME_DEMO_SWIFTUI = Gravatar-SwiftUI-Demo SCHEME_DEMO_UIKIT = Gravatar-UIKit-Demo +VERSION_FILE = ./version.rb +SDK_VERSION := $(shell ruby -r$(VERSION_FILE) -e "puts Gravatar::VERSION") +OPENAPI_CLIENT_PROPERTIES ?= projectName=OpenAPIClient,useSPMFileStructure=true,podVersion=$(SDK_VERSION) + # If no target is specified, display help .DEFAULT_GOAL := help @@ -98,8 +102,8 @@ validate-pod: bundle-install # https://github.com/Automattic/buildkite-ci/issues/7 xcrun simctl list >> /dev/null bundle exec pod lib lint \ - --include-podspecs="*.podspec" \ - --verbose --fail-fast + --include-podspecs="[\"*.podspec\", \"openapi/GravatarOpenAPIClient/*.podspec\"]" \ + --verbose --fail-fast --no-clean update-example-snapshots: for filePath in ./Sources/GravatarUI/GravatarUI.docc/Resources/ProfileExamples/*; \ @@ -116,16 +120,18 @@ install-and-generate: $(OPENAPI_GENERATOR_CLONE_DIR) # Clones and setup the open generate: $(OUTPUT_DIRECTORY) # Generates the open-api model rm -rf "$(OPENAPI_GENERATED_DIR)/*" && \ docker run --rm \ - -v ${OPENAPI_DIR}:/local openapitools/openapi-generator-cli:"$(OPENAPI_GENERATOR_GIT_TAG)" generate \ + -v $(OPENAPI_DIR):/local openapitools/openapi-generator-cli:"$(OPENAPI_GENERATOR_GIT_TAG)" generate \ -i /local/openapi.yaml \ -o /local/GravatarOpenAPIClient \ -t /local/templates \ -g swift5 \ -p packageName=Gravatar \ - --additional-properties=useJsonEncodable=false,readonlyProperties=true,projectName=OpenAPIClient,useSPMFileStructure=true && \ + --additional-properties=useJsonEncodable=false,readonlyProperties=true,$(OPENAPI_CLIENT_PROPERTIES) && \ make swiftformat && \ echo "DONE! 🎉" + + generate-strings: bundle-install bundle exec fastlane generate_strings diff --git a/openapi/templates/Podspec.mustache b/openapi/templates/Podspec.mustache new file mode 100644 index 00000000..e69a8702 --- /dev/null +++ b/openapi/templates/Podspec.mustache @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +Pod::Spec.new do |s| + s.name = '{{projectName}}' + s.summary = 'A Gravatar OpenAPI Client' + s.version = '{{podVersion}}{{^podVersion}}{{#apiInfo}}{{version}}{{/apiInfo}}{{^apiInfo}}}0.0.1{{/apiInfo}}{{/podVersion}}' + + # These are defined by openapi-generator + s.ios.deployment_target = '11.0' + s.osx.deployment_target = '10.13' + s.tvos.deployment_target = '11.0' + s.watchos.deployment_target = '4.0' + + s.homepage = 'https://gravatar.com' + s.license = { type: 'Mozilla Public License v2', file: 'LICENSE.md'} + s.authors = 'Automattic, Inc.' + s.source = { :git => 'https://github.com/Automattic/Gravatar-SDK-iOS.git', :tag => s.version.to_s } + + s.documentation_url = 'https://automattic.github.io/Gravatar-SDK-iOS/gravatar' + + s.source_files = '{{swiftPackagePath}}{{^swiftPackagePath}}{{#useSPMFileStructure}}Sources/{{projectName}}{{/useSPMFileStructure}}{{^useSPMFileStructure}}{{projectName}}/Classes{{/useSPMFileStructure}}{{/swiftPackagePath}}/**/*.swift' +end From 707bd37025a6fddac26e20fdbc102df459e170a4 Mon Sep 17 00:00:00 2001 From: Andrew Montgomery Date: Tue, 8 Oct 2024 14:03:52 -0500 Subject: [PATCH 05/20] Update generated client --- .../OpenAPIClient.podspec | 23 ++++++++++++------- openapi/GravatarOpenAPIClient/project.yml | 2 +- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/openapi/GravatarOpenAPIClient/OpenAPIClient.podspec b/openapi/GravatarOpenAPIClient/OpenAPIClient.podspec index 0d10326e..8aaec599 100644 --- a/openapi/GravatarOpenAPIClient/OpenAPIClient.podspec +++ b/openapi/GravatarOpenAPIClient/OpenAPIClient.podspec @@ -1,15 +1,22 @@ +# frozen_string_literal: true + Pod::Spec.new do |s| - s.name = 'OpenAPIClient' + s.name = 'OpenAPIClient' + s.summary = 'A Gravatar OpenAPI Client' + s.version = '2.1.1' + + # These are defined by openapi-generator s.ios.deployment_target = '11.0' s.osx.deployment_target = '10.13' s.tvos.deployment_target = '11.0' s.watchos.deployment_target = '4.0' - s.version = '3.0.0' - s.source = { :git => 'git@github.com:OpenAPITools/openapi-generator.git', :tag => 'v3.0.0' } - s.authors = 'OpenAPI Generator' - s.license = 'Proprietary' - s.homepage = 'https://github.com/OpenAPITools/openapi-generator' - s.summary = 'OpenAPIClient Swift SDK' + + s.homepage = 'https://gravatar.com' + s.license = { type: 'Mozilla Public License v2', file: 'LICENSE.md'} + s.authors = 'Automattic, Inc.' + s.source = { :git => 'https://github.com/Automattic/Gravatar-SDK-iOS.git', :tag => s.version.to_s } + + s.documentation_url = 'https://automattic.github.io/Gravatar-SDK-iOS/gravatar' + s.source_files = 'Sources/OpenAPIClient/**/*.swift' - s.dependency 'AnyCodable-FlightSchool', '~> 0.6' end diff --git a/openapi/GravatarOpenAPIClient/project.yml b/openapi/GravatarOpenAPIClient/project.yml index 69390791..42fed201 100644 --- a/openapi/GravatarOpenAPIClient/project.yml +++ b/openapi/GravatarOpenAPIClient/project.yml @@ -7,7 +7,7 @@ targets: sources: [Sources] info: path: ./Info.plist - version: 3.0.0 + version: 2.1.1 settings: APPLICATION_EXTENSION_API_ONLY: true scheme: {} From 32f8dd839aaea8b3b29cfee490e78e11db717c44 Mon Sep 17 00:00:00 2001 From: Andrew Montgomery Date: Tue, 8 Oct 2024 14:16:39 -0500 Subject: [PATCH 06/20] Rename OpenAPIClient --> GravatarOpenAPIClient --- .../xcshareddata/swiftpm/Package.resolved | 11 +++- Gravatar.podspec | 1 + Makefile | 9 ++-- Package.swift | 2 +- Sources/Gravatar/OpenAPIExports.swift | 28 +++++----- .../.openapi-generator-ignore | 2 +- .../.openapi-generator/FILES | 52 +++++++++---------- ....podspec => GravatarOpenAPIClient.podspec} | 4 +- openapi/GravatarOpenAPIClient/Package.swift | 10 ++-- openapi/GravatarOpenAPIClient/README.md | 2 +- .../APIHelper.swift | 0 .../APIs.swift | 8 +-- .../CodableHelper.swift | 0 .../Configuration.swift | 0 .../Extensions.swift | 0 .../JSONDataEncoding.swift | 0 .../JSONEncodingHelper.swift | 0 .../Models.swift | 0 .../Models/AssociatedResponse.swift | 0 .../Models/Avatar.swift | 0 .../Models/CryptoWalletAddress.swift | 0 .../Models/GalleryImage.swift | 0 .../Models/Interest.swift | 0 .../Models/Language.swift | 0 .../Models/Link.swift | 0 .../Models/ModelError.swift | 0 .../Models/Profile.swift | 0 .../Models/ProfileContactInfo.swift | 0 .../Models/ProfilePayments.swift | 0 .../Models/SetEmailAvatarRequest.swift | 0 .../Models/VerifiedAccount.swift | 0 .../OpenISO8601DateFormatter.swift | 0 .../SynchronizedDictionary.swift | 0 .../URLSessionImplementations.swift | 12 ++--- .../Validation.swift | 0 .../GravatarOpenAPIClient/docs/AvatarsAPI.md | 6 +-- .../GravatarOpenAPIClient/docs/ProfilesAPI.md | 4 +- openapi/GravatarOpenAPIClient/project.yml | 4 +- 38 files changed, 83 insertions(+), 72 deletions(-) rename openapi/GravatarOpenAPIClient/{OpenAPIClient.podspec => GravatarOpenAPIClient.podspec} (85%) rename openapi/GravatarOpenAPIClient/Sources/{OpenAPIClient => GravatarOpenAPIClient}/APIHelper.swift (100%) rename openapi/GravatarOpenAPIClient/Sources/{OpenAPIClient => GravatarOpenAPIClient}/APIs.swift (84%) rename openapi/GravatarOpenAPIClient/Sources/{OpenAPIClient => GravatarOpenAPIClient}/CodableHelper.swift (100%) rename openapi/GravatarOpenAPIClient/Sources/{OpenAPIClient => GravatarOpenAPIClient}/Configuration.swift (100%) rename openapi/GravatarOpenAPIClient/Sources/{OpenAPIClient => GravatarOpenAPIClient}/Extensions.swift (100%) rename openapi/GravatarOpenAPIClient/Sources/{OpenAPIClient => GravatarOpenAPIClient}/JSONDataEncoding.swift (100%) rename openapi/GravatarOpenAPIClient/Sources/{OpenAPIClient => GravatarOpenAPIClient}/JSONEncodingHelper.swift (100%) rename openapi/GravatarOpenAPIClient/Sources/{OpenAPIClient => GravatarOpenAPIClient}/Models.swift (100%) rename openapi/GravatarOpenAPIClient/Sources/{OpenAPIClient => GravatarOpenAPIClient}/Models/AssociatedResponse.swift (100%) rename openapi/GravatarOpenAPIClient/Sources/{OpenAPIClient => GravatarOpenAPIClient}/Models/Avatar.swift (100%) rename openapi/GravatarOpenAPIClient/Sources/{OpenAPIClient => GravatarOpenAPIClient}/Models/CryptoWalletAddress.swift (100%) rename openapi/GravatarOpenAPIClient/Sources/{OpenAPIClient => GravatarOpenAPIClient}/Models/GalleryImage.swift (100%) rename openapi/GravatarOpenAPIClient/Sources/{OpenAPIClient => GravatarOpenAPIClient}/Models/Interest.swift (100%) rename openapi/GravatarOpenAPIClient/Sources/{OpenAPIClient => GravatarOpenAPIClient}/Models/Language.swift (100%) rename openapi/GravatarOpenAPIClient/Sources/{OpenAPIClient => GravatarOpenAPIClient}/Models/Link.swift (100%) rename openapi/GravatarOpenAPIClient/Sources/{OpenAPIClient => GravatarOpenAPIClient}/Models/ModelError.swift (100%) rename openapi/GravatarOpenAPIClient/Sources/{OpenAPIClient => GravatarOpenAPIClient}/Models/Profile.swift (100%) rename openapi/GravatarOpenAPIClient/Sources/{OpenAPIClient => GravatarOpenAPIClient}/Models/ProfileContactInfo.swift (100%) rename openapi/GravatarOpenAPIClient/Sources/{OpenAPIClient => GravatarOpenAPIClient}/Models/ProfilePayments.swift (100%) rename openapi/GravatarOpenAPIClient/Sources/{OpenAPIClient => GravatarOpenAPIClient}/Models/SetEmailAvatarRequest.swift (100%) rename openapi/GravatarOpenAPIClient/Sources/{OpenAPIClient => GravatarOpenAPIClient}/Models/VerifiedAccount.swift (100%) rename openapi/GravatarOpenAPIClient/Sources/{OpenAPIClient => GravatarOpenAPIClient}/OpenISO8601DateFormatter.swift (100%) rename openapi/GravatarOpenAPIClient/Sources/{OpenAPIClient => GravatarOpenAPIClient}/SynchronizedDictionary.swift (100%) rename openapi/GravatarOpenAPIClient/Sources/{OpenAPIClient => GravatarOpenAPIClient}/URLSessionImplementations.swift (97%) rename openapi/GravatarOpenAPIClient/Sources/{OpenAPIClient => GravatarOpenAPIClient}/Validation.swift (100%) diff --git a/Demo/Gravatar-Demo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Demo/Gravatar-Demo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 25fedc2e..a935fc1b 100644 --- a/Demo/Gravatar-Demo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Demo/Gravatar-Demo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,6 +1,15 @@ { - "originHash" : "89aad130e119d7a4b1dea1ad42b23e52b29cf016999eed5d14af43b0dc276ac1", + "originHash" : "2636afb60bdeb27536d533a4fd95ce1b1476cf7e53d8bc0bcaa63387fbefb579", "pins" : [ + { + "identity" : "anycodable", + "kind" : "remoteSourceControl", + "location" : "https://github.com/Flight-School/AnyCodable", + "state" : { + "revision" : "862808b2070cd908cb04f9aafe7de83d35f81b05", + "version" : "0.6.7" + } + }, { "identity" : "swift-snapshot-testing", "kind" : "remoteSourceControl", diff --git a/Gravatar.podspec b/Gravatar.podspec index 03229947..5e4606ea 100644 --- a/Gravatar.podspec +++ b/Gravatar.podspec @@ -22,6 +22,7 @@ Pod::Spec.new do |s| s.ios.deployment_target = ios_deployment_target + s.dependency 'GravatarOpenAPIClient', s.version.to_s s.source_files = 'Sources/Gravatar/**/*.swift' s.resource_bundles = { 'Gravatar' => ['Sources/Gravatar/Resources/*.plist'] diff --git a/Makefile b/Makefile index 6402f3e3..697cdae1 100644 --- a/Makefile +++ b/Makefile @@ -8,6 +8,10 @@ # No spaces allowed SWIFTFORMAT_CACHE = ~/Library/Caches/com.charcoaldesign.swiftformat +# SDK Version +VERSION_FILE = ./version.rb +SDK_VERSION := $(shell ruby -r$(VERSION_FILE) -e "puts Gravatar::VERSION") + # The following values can be changed here, or passed on the command line. OPENAPI_GENERATOR_GIT_URL ?= https://github.com/openapitools/openapi-generator OPENAPI_GENERATOR_GIT_TAG ?= v7.5.0 @@ -16,6 +20,7 @@ OPENAPI_GENERATOR_CLONE_DIR ?= $(CURRENT_MAKEFILE_DIR)/openapi-generator OPENAPI_PROJECT_NAME ?= GravatarOpenAPIClient OPENAPI_DIR ?= $(CURRENT_MAKEFILE_DIR)/openapi OPENAPI_GENERATED_DIR ?= $(CURRENT_MAKEFILE_DIR)/openapi/$(OPENAPI_PROJECT_NAME) +OPENAPI_CLIENT_PROPERTIES ?= projectName=$(OPENAPI_PROJECT_NAME),useSPMFileStructure=true,podVersion=$(SDK_VERSION) OPENAPI_YAML_PATH ?= $(CURRENT_MAKEFILE_DIR)/openapi/spec.yaml MODEL_TEMPLATE_PATH ?= $(CURRENT_MAKEFILE_DIR)/openapi @@ -28,10 +33,6 @@ CURRENT_MAKEFILE_DIR := $(patsubst %/,%,$(dir $(CURRENT_MAKEFILE_PATH))) SCHEME_DEMO_SWIFTUI = Gravatar-SwiftUI-Demo SCHEME_DEMO_UIKIT = Gravatar-UIKit-Demo -VERSION_FILE = ./version.rb -SDK_VERSION := $(shell ruby -r$(VERSION_FILE) -e "puts Gravatar::VERSION") -OPENAPI_CLIENT_PROPERTIES ?= projectName=OpenAPIClient,useSPMFileStructure=true,podVersion=$(SDK_VERSION) - # If no target is specified, display help .DEFAULT_GOAL := help diff --git a/Package.swift b/Package.swift index a59590aa..c39138ba 100644 --- a/Package.swift +++ b/Package.swift @@ -33,7 +33,7 @@ let package = Package( // Targets can depend on other targets in this package and products from dependencies. .target( name: "Gravatar", - dependencies: [.product(name: "OpenAPIClient", package: "GravatarOpenAPIClient")], + dependencies: [.product(name: "GravatarOpenAPIClient", package: "GravatarOpenAPIClient")], resources: [.process("Resources")], swiftSettings: [ .enableExperimentalFeature("StrictConcurrency") diff --git a/Sources/Gravatar/OpenAPIExports.swift b/Sources/Gravatar/OpenAPIExports.swift index a85500b4..e4bc953f 100644 --- a/Sources/Gravatar/OpenAPIExports.swift +++ b/Sources/Gravatar/OpenAPIExports.swift @@ -1,23 +1,23 @@ -import OpenAPIClient +import GravatarOpenAPIClient // MARK: OpenAPI Models: Public -public typealias CryptoWalletAddress = OpenAPIClient.CryptoWalletAddress -public typealias GalleryImage = OpenAPIClient.GalleryImage -public typealias Interest = OpenAPIClient.Interest -public typealias Language = OpenAPIClient.Language -public typealias Link = OpenAPIClient.Link -public typealias Profile = OpenAPIClient.Profile -public typealias ProfileContactInfo = OpenAPIClient.ProfileContactInfo -public typealias ProfilePayments = OpenAPIClient.ProfilePayments -public typealias VerifiedAccount = OpenAPIClient.VerifiedAccount +public typealias CryptoWalletAddress = GravatarOpenAPIClient.CryptoWalletAddress +public typealias GalleryImage = GravatarOpenAPIClient.GalleryImage +public typealias Interest = GravatarOpenAPIClient.Interest +public typealias Language = GravatarOpenAPIClient.Language +public typealias Link = GravatarOpenAPIClient.Link +public typealias Profile = GravatarOpenAPIClient.Profile +public typealias ProfileContactInfo = GravatarOpenAPIClient.ProfileContactInfo +public typealias ProfilePayments = GravatarOpenAPIClient.ProfilePayments +public typealias VerifiedAccount = GravatarOpenAPIClient.VerifiedAccount // MARK: - OpenAPI Models: Package -package typealias Avatar = OpenAPIClient.Avatar +package typealias Avatar = GravatarOpenAPIClient.Avatar // MARK: - OpenAPI Models: Internal -typealias AssociatedResponse = OpenAPIClient.AssociatedResponse -typealias ModelError = OpenAPIClient.ModelError -typealias SetEmailAvatarRequest = OpenAPIClient.SetEmailAvatarRequest +typealias AssociatedResponse = GravatarOpenAPIClient.AssociatedResponse +typealias ModelError = GravatarOpenAPIClient.ModelError +typealias SetEmailAvatarRequest = GravatarOpenAPIClient.SetEmailAvatarRequest diff --git a/openapi/GravatarOpenAPIClient/.openapi-generator-ignore b/openapi/GravatarOpenAPIClient/.openapi-generator-ignore index f20534fd..5f696832 100644 --- a/openapi/GravatarOpenAPIClient/.openapi-generator-ignore +++ b/openapi/GravatarOpenAPIClient/.openapi-generator-ignore @@ -25,4 +25,4 @@ .swiftformat Cartfile git_push.sh -Sources/OpenAPIClient/APIs/ \ No newline at end of file +Sources/GravatarOpenAPIClient/APIs/ \ No newline at end of file diff --git a/openapi/GravatarOpenAPIClient/.openapi-generator/FILES b/openapi/GravatarOpenAPIClient/.openapi-generator/FILES index cd579e69..f2365749 100644 --- a/openapi/GravatarOpenAPIClient/.openapi-generator/FILES +++ b/openapi/GravatarOpenAPIClient/.openapi-generator/FILES @@ -1,32 +1,32 @@ .gitignore -OpenAPIClient.podspec +GravatarOpenAPIClient.podspec Package.swift README.md -Sources/OpenAPIClient/APIHelper.swift -Sources/OpenAPIClient/APIs.swift -Sources/OpenAPIClient/CodableHelper.swift -Sources/OpenAPIClient/Configuration.swift -Sources/OpenAPIClient/Extensions.swift -Sources/OpenAPIClient/JSONDataEncoding.swift -Sources/OpenAPIClient/JSONEncodingHelper.swift -Sources/OpenAPIClient/Models.swift -Sources/OpenAPIClient/Models/AssociatedResponse.swift -Sources/OpenAPIClient/Models/Avatar.swift -Sources/OpenAPIClient/Models/CryptoWalletAddress.swift -Sources/OpenAPIClient/Models/GalleryImage.swift -Sources/OpenAPIClient/Models/Interest.swift -Sources/OpenAPIClient/Models/Language.swift -Sources/OpenAPIClient/Models/Link.swift -Sources/OpenAPIClient/Models/ModelError.swift -Sources/OpenAPIClient/Models/Profile.swift -Sources/OpenAPIClient/Models/ProfileContactInfo.swift -Sources/OpenAPIClient/Models/ProfilePayments.swift -Sources/OpenAPIClient/Models/SetEmailAvatarRequest.swift -Sources/OpenAPIClient/Models/VerifiedAccount.swift -Sources/OpenAPIClient/OpenISO8601DateFormatter.swift -Sources/OpenAPIClient/SynchronizedDictionary.swift -Sources/OpenAPIClient/URLSessionImplementations.swift -Sources/OpenAPIClient/Validation.swift +Sources/GravatarOpenAPIClient/APIHelper.swift +Sources/GravatarOpenAPIClient/APIs.swift +Sources/GravatarOpenAPIClient/CodableHelper.swift +Sources/GravatarOpenAPIClient/Configuration.swift +Sources/GravatarOpenAPIClient/Extensions.swift +Sources/GravatarOpenAPIClient/JSONDataEncoding.swift +Sources/GravatarOpenAPIClient/JSONEncodingHelper.swift +Sources/GravatarOpenAPIClient/Models.swift +Sources/GravatarOpenAPIClient/Models/AssociatedResponse.swift +Sources/GravatarOpenAPIClient/Models/Avatar.swift +Sources/GravatarOpenAPIClient/Models/CryptoWalletAddress.swift +Sources/GravatarOpenAPIClient/Models/GalleryImage.swift +Sources/GravatarOpenAPIClient/Models/Interest.swift +Sources/GravatarOpenAPIClient/Models/Language.swift +Sources/GravatarOpenAPIClient/Models/Link.swift +Sources/GravatarOpenAPIClient/Models/ModelError.swift +Sources/GravatarOpenAPIClient/Models/Profile.swift +Sources/GravatarOpenAPIClient/Models/ProfileContactInfo.swift +Sources/GravatarOpenAPIClient/Models/ProfilePayments.swift +Sources/GravatarOpenAPIClient/Models/SetEmailAvatarRequest.swift +Sources/GravatarOpenAPIClient/Models/VerifiedAccount.swift +Sources/GravatarOpenAPIClient/OpenISO8601DateFormatter.swift +Sources/GravatarOpenAPIClient/SynchronizedDictionary.swift +Sources/GravatarOpenAPIClient/URLSessionImplementations.swift +Sources/GravatarOpenAPIClient/Validation.swift docs/AssociatedResponse.md docs/Avatar.md docs/AvatarsAPI.md diff --git a/openapi/GravatarOpenAPIClient/OpenAPIClient.podspec b/openapi/GravatarOpenAPIClient/GravatarOpenAPIClient.podspec similarity index 85% rename from openapi/GravatarOpenAPIClient/OpenAPIClient.podspec rename to openapi/GravatarOpenAPIClient/GravatarOpenAPIClient.podspec index 8aaec599..8bd41984 100644 --- a/openapi/GravatarOpenAPIClient/OpenAPIClient.podspec +++ b/openapi/GravatarOpenAPIClient/GravatarOpenAPIClient.podspec @@ -1,7 +1,7 @@ # frozen_string_literal: true Pod::Spec.new do |s| - s.name = 'OpenAPIClient' + s.name = 'GravatarOpenAPIClient' s.summary = 'A Gravatar OpenAPI Client' s.version = '2.1.1' @@ -18,5 +18,5 @@ Pod::Spec.new do |s| s.documentation_url = 'https://automattic.github.io/Gravatar-SDK-iOS/gravatar' - s.source_files = 'Sources/OpenAPIClient/**/*.swift' + s.source_files = 'Sources/GravatarOpenAPIClient/**/*.swift' end diff --git a/openapi/GravatarOpenAPIClient/Package.swift b/openapi/GravatarOpenAPIClient/Package.swift index bfcd84c0..b773c9f6 100644 --- a/openapi/GravatarOpenAPIClient/Package.swift +++ b/openapi/GravatarOpenAPIClient/Package.swift @@ -3,7 +3,7 @@ import PackageDescription let package = Package( - name: "OpenAPIClient", + name: "GravatarOpenAPIClient", platforms: [ .iOS(.v11), .macOS(.v10_13), @@ -13,8 +13,8 @@ let package = Package( products: [ // Products define the executables and libraries produced by a package, and make them visible to other packages. .library( - name: "OpenAPIClient", - targets: ["OpenAPIClient"] + name: "GravatarOpenAPIClient", + targets: ["GravatarOpenAPIClient"] ), ], dependencies: [ @@ -25,9 +25,9 @@ let package = Package( // 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", + name: "GravatarOpenAPIClient", dependencies: ["AnyCodable", ], - path: "Sources/OpenAPIClient" + path: "Sources/GravatarOpenAPIClient" ), ] ) diff --git a/openapi/GravatarOpenAPIClient/README.md b/openapi/GravatarOpenAPIClient/README.md index a8e2ff3d..c31350d5 100644 --- a/openapi/GravatarOpenAPIClient/README.md +++ b/openapi/GravatarOpenAPIClient/README.md @@ -1,4 +1,4 @@ -# Swift5 API client for OpenAPIClient +# Swift5 API client for GravatarOpenAPIClient Gravatar's public API endpoints diff --git a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/APIHelper.swift b/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/APIHelper.swift similarity index 100% rename from openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/APIHelper.swift rename to openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/APIHelper.swift diff --git a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/APIs.swift b/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/APIs.swift similarity index 84% rename from openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/APIs.swift rename to openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/APIs.swift index fa2ea4a0..1c80cf4c 100644 --- a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/APIs.swift +++ b/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/APIs.swift @@ -8,7 +8,7 @@ import Foundation #if canImport(FoundationNetworking) import FoundationNetworking #endif -open class OpenAPIClientAPI { +open class GravatarOpenAPIClientAPI { public static var basePath = "https://api.gravatar.com/v3" public static var customHeaders: [String: String] = [:] public static var credential: URLCredential? @@ -35,7 +35,7 @@ open class RequestBuilder { self.headers = headers self.requiresAuthentication = requiresAuthentication - addHeaders(OpenAPIClientAPI.customHeaders) + addHeaders(GravatarOpenAPIClientAPI.customHeaders) } open func addHeaders(_ aHeaders: [String: String]) { @@ -45,7 +45,7 @@ open class RequestBuilder { } @discardableResult - open func execute(_ apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, _ completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) -> RequestTask { + open func execute(_ apiResponseQueue: DispatchQueue = GravatarOpenAPIClientAPI.apiResponseQueue, _ completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) -> RequestTask { return requestTask } @@ -57,7 +57,7 @@ open class RequestBuilder { } open func addCredential() -> Self { - credential = OpenAPIClientAPI.credential + credential = GravatarOpenAPIClientAPI.credential return self } } diff --git a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/CodableHelper.swift b/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/CodableHelper.swift similarity index 100% rename from openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/CodableHelper.swift rename to openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/CodableHelper.swift diff --git a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Configuration.swift b/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Configuration.swift similarity index 100% rename from openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Configuration.swift rename to openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Configuration.swift diff --git a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Extensions.swift b/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Extensions.swift similarity index 100% rename from openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Extensions.swift rename to openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Extensions.swift diff --git a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/JSONDataEncoding.swift b/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/JSONDataEncoding.swift similarity index 100% rename from openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/JSONDataEncoding.swift rename to openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/JSONDataEncoding.swift diff --git a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/JSONEncodingHelper.swift b/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/JSONEncodingHelper.swift similarity index 100% rename from openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/JSONEncodingHelper.swift rename to openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/JSONEncodingHelper.swift diff --git a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models.swift b/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models.swift similarity index 100% rename from openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models.swift rename to openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models.swift diff --git a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/AssociatedResponse.swift b/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/AssociatedResponse.swift similarity index 100% rename from openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/AssociatedResponse.swift rename to openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/AssociatedResponse.swift diff --git a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/Avatar.swift b/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/Avatar.swift similarity index 100% rename from openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/Avatar.swift rename to openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/Avatar.swift diff --git a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/CryptoWalletAddress.swift b/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/CryptoWalletAddress.swift similarity index 100% rename from openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/CryptoWalletAddress.swift rename to openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/CryptoWalletAddress.swift diff --git a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/GalleryImage.swift b/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/GalleryImage.swift similarity index 100% rename from openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/GalleryImage.swift rename to openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/GalleryImage.swift diff --git a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/Interest.swift b/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/Interest.swift similarity index 100% rename from openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/Interest.swift rename to openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/Interest.swift diff --git a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/Language.swift b/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/Language.swift similarity index 100% rename from openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/Language.swift rename to openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/Language.swift diff --git a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/Link.swift b/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/Link.swift similarity index 100% rename from openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/Link.swift rename to openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/Link.swift diff --git a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/ModelError.swift b/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/ModelError.swift similarity index 100% rename from openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/ModelError.swift rename to openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/ModelError.swift diff --git a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/Profile.swift b/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/Profile.swift similarity index 100% rename from openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/Profile.swift rename to openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/Profile.swift diff --git a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/ProfileContactInfo.swift b/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/ProfileContactInfo.swift similarity index 100% rename from openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/ProfileContactInfo.swift rename to openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/ProfileContactInfo.swift diff --git a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/ProfilePayments.swift b/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/ProfilePayments.swift similarity index 100% rename from openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/ProfilePayments.swift rename to openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/ProfilePayments.swift diff --git a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/SetEmailAvatarRequest.swift b/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/SetEmailAvatarRequest.swift similarity index 100% rename from openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/SetEmailAvatarRequest.swift rename to openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/SetEmailAvatarRequest.swift diff --git a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/VerifiedAccount.swift b/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/VerifiedAccount.swift similarity index 100% rename from openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Models/VerifiedAccount.swift rename to openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/VerifiedAccount.swift diff --git a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/OpenISO8601DateFormatter.swift b/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/OpenISO8601DateFormatter.swift similarity index 100% rename from openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/OpenISO8601DateFormatter.swift rename to openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/OpenISO8601DateFormatter.swift diff --git a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/SynchronizedDictionary.swift b/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/SynchronizedDictionary.swift similarity index 100% rename from openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/SynchronizedDictionary.swift rename to openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/SynchronizedDictionary.swift diff --git a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/URLSessionImplementations.swift b/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/URLSessionImplementations.swift similarity index 97% rename from openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/URLSessionImplementations.swift rename to openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/URLSessionImplementations.swift index 3813d86c..917eb573 100644 --- a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/URLSessionImplementations.swift +++ b/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/URLSessionImplementations.swift @@ -28,7 +28,7 @@ class URLSessionRequestBuilderFactory: RequestBuilderFactory { } } -public typealias OpenAPIClientAPIChallengeHandler = ((URLSession, URLSessionTask, URLAuthenticationChallenge) -> (URLSession.AuthChallengeDisposition, URLCredential?)) +public typealias GravatarOpenAPIClientAPIChallengeHandler = ((URLSession, URLSessionTask, URLAuthenticationChallenge) -> (URLSession.AuthChallengeDisposition, URLCredential?)) // Store the URLSession's delegate to retain its reference private let sessionDelegate = SessionDelegate() @@ -37,7 +37,7 @@ private let sessionDelegate = SessionDelegate() private let defaultURLSession = URLSession(configuration: .default, delegate: sessionDelegate, delegateQueue: nil) // Store current taskDidReceiveChallenge for every URLSessionTask -private var challengeHandlerStore = SynchronizedDictionary() +private var challengeHandlerStore = SynchronizedDictionary() // Store current URLCredential for every URLSessionTask private var credentialStore = SynchronizedDictionary() @@ -47,7 +47,7 @@ open class URLSessionRequestBuilder: RequestBuilder { /** May be assigned if you want to control the authentication challenges. */ - public var taskDidReceiveChallenge: OpenAPIClientAPIChallengeHandler? + public var taskDidReceiveChallenge: GravatarOpenAPIClientAPIChallengeHandler? required public init(method: String, URLString: String, parameters: [String: Any]?, headers: [String: String] = [:], requiresAuthentication: Bool) { super.init(method: method, URLString: URLString, parameters: parameters, headers: headers, requiresAuthentication: requiresAuthentication) @@ -96,7 +96,7 @@ open class URLSessionRequestBuilder: RequestBuilder { } @discardableResult - override open func execute(_ apiResponseQueue: DispatchQueue = OpenAPIClientAPI.apiResponseQueue, _ completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) -> RequestTask { + override open func execute(_ apiResponseQueue: DispatchQueue = GravatarOpenAPIClientAPI.apiResponseQueue, _ completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) -> RequestTask { let urlSession = createURLSession() guard let xMethod = HTTPMethod(rawValue: method) else { @@ -191,7 +191,7 @@ open class URLSessionRequestBuilder: RequestBuilder { open func buildHeaders() -> [String: String] { var httpHeaders: [String: String] = [:] - for (key, value) in OpenAPIClientAPI.customHeaders { + for (key, value) in GravatarOpenAPIClientAPI.customHeaders { httpHeaders[key] = value } for (key, value) in headers { @@ -298,7 +298,7 @@ open class URLSessionDecodableRequestBuilder: URLSessionRequestBui if let headerFileName = getFileName(fromContentDisposition: httpResponse.allHeaderFields["Content-Disposition"] as? String) { requestPath = requestPath.appending("/\(headerFileName)") } else { - requestPath = requestPath.appending("/tmp.OpenAPIClient.\(UUID().uuidString)") + requestPath = requestPath.appending("/tmp.GravatarOpenAPIClient.\(UUID().uuidString)") } let filePath = cachesDirectory.appendingPathComponent(requestPath) diff --git a/openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Validation.swift b/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Validation.swift similarity index 100% rename from openapi/GravatarOpenAPIClient/Sources/OpenAPIClient/Validation.swift rename to openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Validation.swift diff --git a/openapi/GravatarOpenAPIClient/docs/AvatarsAPI.md b/openapi/GravatarOpenAPIClient/docs/AvatarsAPI.md index b630d636..aaf5a46f 100644 --- a/openapi/GravatarOpenAPIClient/docs/AvatarsAPI.md +++ b/openapi/GravatarOpenAPIClient/docs/AvatarsAPI.md @@ -21,7 +21,7 @@ Retrieves a list of available avatars for the authenticated user. ### Example ```swift // The following code samples are still beta. For any issue, please report via http://github.com/OpenAPITools/openapi-generator/issues/new -import OpenAPIClient +import GravatarOpenAPIClient let selectedEmailHash = "selectedEmailHash_example" // String | The sha256 hash of the email address used to determine which avatar is selected. The 'selected' attribute in the avatar list will be set to 'true' for the avatar associated with this email. (optional) (default to "null") @@ -71,7 +71,7 @@ Sets the avatar for the provided email hash. ### Example ```swift // The following code samples are still beta. For any issue, please report via http://github.com/OpenAPITools/openapi-generator/issues/new -import OpenAPIClient +import GravatarOpenAPIClient let imageId = "imageId_example" // String | Image ID of the avatar to set as the provided hashed email avatar. let setEmailAvatarRequest = setEmailAvatar_request(emailHash: "emailHash_example") // SetEmailAvatarRequest | Avatar selection details @@ -123,7 +123,7 @@ Uploads a new avatar image for the authenticated user. ### Example ```swift // The following code samples are still beta. For any issue, please report via http://github.com/OpenAPITools/openapi-generator/issues/new -import OpenAPIClient +import GravatarOpenAPIClient let data = URL(string: "https://example.com")! // URL | The avatar image file diff --git a/openapi/GravatarOpenAPIClient/docs/ProfilesAPI.md b/openapi/GravatarOpenAPIClient/docs/ProfilesAPI.md index 210504f1..39c79c09 100644 --- a/openapi/GravatarOpenAPIClient/docs/ProfilesAPI.md +++ b/openapi/GravatarOpenAPIClient/docs/ProfilesAPI.md @@ -20,7 +20,7 @@ Checks if the provided email address is associated with the authenticated user. ### Example ```swift // The following code samples are still beta. For any issue, please report via http://github.com/OpenAPITools/openapi-generator/issues/new -import OpenAPIClient +import GravatarOpenAPIClient let emailHash = "emailHash_example" // String | The hash of the email address to check. @@ -70,7 +70,7 @@ Returns a profile by the given identifier. ### Example ```swift // The following code samples are still beta. For any issue, please report via http://github.com/OpenAPITools/openapi-generator/issues/new -import OpenAPIClient +import GravatarOpenAPIClient let profileIdentifier = "profileIdentifier_example" // String | This can either be an SHA256 hash of an email address or profile URL slug. diff --git a/openapi/GravatarOpenAPIClient/project.yml b/openapi/GravatarOpenAPIClient/project.yml index 42fed201..b7e48af1 100644 --- a/openapi/GravatarOpenAPIClient/project.yml +++ b/openapi/GravatarOpenAPIClient/project.yml @@ -1,6 +1,6 @@ -name: OpenAPIClient +name: GravatarOpenAPIClient targets: - OpenAPIClient: + GravatarOpenAPIClient: type: framework platform: iOS deploymentTarget: "11.0" From 283a10f7ac9831e48354ccf7c70958d8d9d00807 Mon Sep 17 00:00:00 2001 From: Andrew Montgomery Date: Tue, 8 Oct 2024 16:41:16 -0500 Subject: [PATCH 07/20] Match iOS deployment targets for all podspecs --- Gravatar.podspec | 2 +- GravatarUI.podspec | 2 +- openapi/GravatarOpenAPIClient/GravatarOpenAPIClient.podspec | 5 +---- openapi/templates/Podspec.mustache | 5 +---- version.rb | 1 + 5 files changed, 5 insertions(+), 10 deletions(-) diff --git a/Gravatar.podspec b/Gravatar.podspec index 5e4606ea..dfa958a4 100644 --- a/Gravatar.podspec +++ b/Gravatar.podspec @@ -18,7 +18,7 @@ Pod::Spec.new do |s| s.swift_versions = Gravatar::SWIFT_VERSIONS - ios_deployment_target = '15.0' + ios_deployment_target = Gravatar::IOS_DEPLOYMENT_TARGET s.ios.deployment_target = ios_deployment_target diff --git a/GravatarUI.podspec b/GravatarUI.podspec index f16fed4f..b1cafb73 100644 --- a/GravatarUI.podspec +++ b/GravatarUI.podspec @@ -18,7 +18,7 @@ Pod::Spec.new do |s| s.swift_versions = Gravatar::SWIFT_VERSIONS - ios_deployment_target = '15.0' + ios_deployment_target = Gravatar::IOS_DEPLOYMENT_TARGET s.ios.deployment_target = ios_deployment_target s.source_files = 'Sources/GravatarUI/**/*.swift' diff --git a/openapi/GravatarOpenAPIClient/GravatarOpenAPIClient.podspec b/openapi/GravatarOpenAPIClient/GravatarOpenAPIClient.podspec index 8bd41984..b3e38708 100644 --- a/openapi/GravatarOpenAPIClient/GravatarOpenAPIClient.podspec +++ b/openapi/GravatarOpenAPIClient/GravatarOpenAPIClient.podspec @@ -6,10 +6,7 @@ Pod::Spec.new do |s| s.version = '2.1.1' # These are defined by openapi-generator - s.ios.deployment_target = '11.0' - s.osx.deployment_target = '10.13' - s.tvos.deployment_target = '11.0' - s.watchos.deployment_target = '4.0' + s.ios.deployment_target = Gravatar::IOS_DEPLOYMENT_TARGET s.homepage = 'https://gravatar.com' s.license = { type: 'Mozilla Public License v2', file: 'LICENSE.md'} diff --git a/openapi/templates/Podspec.mustache b/openapi/templates/Podspec.mustache index e69a8702..1701fada 100644 --- a/openapi/templates/Podspec.mustache +++ b/openapi/templates/Podspec.mustache @@ -6,10 +6,7 @@ Pod::Spec.new do |s| s.version = '{{podVersion}}{{^podVersion}}{{#apiInfo}}{{version}}{{/apiInfo}}{{^apiInfo}}}0.0.1{{/apiInfo}}{{/podVersion}}' # These are defined by openapi-generator - s.ios.deployment_target = '11.0' - s.osx.deployment_target = '10.13' - s.tvos.deployment_target = '11.0' - s.watchos.deployment_target = '4.0' + s.ios.deployment_target = Gravatar::IOS_DEPLOYMENT_TARGET s.homepage = 'https://gravatar.com' s.license = { type: 'Mozilla Public License v2', file: 'LICENSE.md'} diff --git a/version.rb b/version.rb index 49dc2173..9507d688 100644 --- a/version.rb +++ b/version.rb @@ -5,4 +5,5 @@ module Gravatar SWIFT_VERSIONS = [ '5.10' ].freeze + IOS_DEPLOYMENT_TARGET = '15.0' end From 944c5d68dbbdeb7ce8dc15235e0ffee7d7822a70 Mon Sep 17 00:00:00 2001 From: Andrew Montgomery Date: Tue, 8 Oct 2024 16:42:17 -0500 Subject: [PATCH 08/20] Update Makefile generation of GravatarOpenAPIClient.podspec --- GravatarOpenAPIClient.podspec | 23 +++++++++++++++ Makefile | 29 +++++++++---------- .../GravatarOpenAPIClient.podspec | 12 +++++--- openapi/templates/Podspec.mustache | 12 +++++--- 4 files changed, 52 insertions(+), 24 deletions(-) create mode 100644 GravatarOpenAPIClient.podspec diff --git a/GravatarOpenAPIClient.podspec b/GravatarOpenAPIClient.podspec new file mode 100644 index 00000000..15ba2b8a --- /dev/null +++ b/GravatarOpenAPIClient.podspec @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +require_relative 'version' + +Pod::Spec.new do |s| + s.name = 'GravatarOpenAPIClient' + s.summary = 'A Gravatar OpenAPI Client' + s.version = Gravatar::VERSION + + s.swift_versions = Gravatar::SWIFT_VERSIONS + + # Match the deployment target of Gravatar in order to satisfy `pod lib lint` + s.ios.deployment_target = Gravatar::IOS_DEPLOYMENT_TARGET + + s.homepage = 'https://gravatar.com' + s.license = { type: 'Mozilla Public License v2', file: 'LICENSE.md' } + s.authors = 'Automattic, Inc.' + s.source = { :git => 'https://github.com/Automattic/Gravatar-SDK-iOS.git', :tag => s.version.to_s } + + s.documentation_url = 'https://automattic.github.io/Gravatar-SDK-iOS/gravatar' + + s.source_files = 'openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/**/*.swift' +end diff --git a/Makefile b/Makefile index 697cdae1..85682089 100644 --- a/Makefile +++ b/Makefile @@ -8,23 +8,19 @@ # No spaces allowed SWIFTFORMAT_CACHE = ~/Library/Caches/com.charcoaldesign.swiftformat -# SDK Version -VERSION_FILE = ./version.rb -SDK_VERSION := $(shell ruby -r$(VERSION_FILE) -e "puts Gravatar::VERSION") - # The following values can be changed here, or passed on the command line. OPENAPI_GENERATOR_GIT_URL ?= https://github.com/openapitools/openapi-generator OPENAPI_GENERATOR_GIT_TAG ?= v7.5.0 OPENAPI_GENERATOR_CLONE_DIR ?= $(CURRENT_MAKEFILE_DIR)/openapi-generator OPENAPI_PROJECT_NAME ?= GravatarOpenAPIClient -OPENAPI_DIR ?= $(CURRENT_MAKEFILE_DIR)/openapi +OPENAPI_DIR ?= $(CURRENT_MAKEFILE_DIR)/$(OPENAPI_REL_DIR) +OPENAPI_REL_DIR ?= openapi OPENAPI_GENERATED_DIR ?= $(CURRENT_MAKEFILE_DIR)/openapi/$(OPENAPI_PROJECT_NAME) -OPENAPI_CLIENT_PROPERTIES ?= projectName=$(OPENAPI_PROJECT_NAME),useSPMFileStructure=true,podVersion=$(SDK_VERSION) +OPENAPI_CLIENT_PROPERTIES ?= projectName=$(OPENAPI_PROJECT_NAME),useSPMFileStructure=true,packageRootPath="$(OPENAPI_REL_DIR)/$(OPENAPI_PROJECT_NAME)" OPENAPI_YAML_PATH ?= $(CURRENT_MAKEFILE_DIR)/openapi/spec.yaml MODEL_TEMPLATE_PATH ?= $(CURRENT_MAKEFILE_DIR)/openapi -OUTPUT_DIRECTORY ?= $(CURRENT_MAKEFILE_DIR)/OpenAPIClient # Derived values (don't change these). CURRENT_MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST))) @@ -103,8 +99,8 @@ validate-pod: bundle-install # https://github.com/Automattic/buildkite-ci/issues/7 xcrun simctl list >> /dev/null bundle exec pod lib lint \ - --include-podspecs="[\"*.podspec\", \"openapi/GravatarOpenAPIClient/*.podspec\"]" \ - --verbose --fail-fast --no-clean + --include-podspecs="*.podspec" \ + --verbose --fail-fast --allow-warnings update-example-snapshots: for filePath in ./Sources/GravatarUI/GravatarUI.docc/Resources/ProfileExamples/*; \ @@ -118,7 +114,7 @@ install-and-generate: $(OPENAPI_GENERATOR_CLONE_DIR) # Clones and setup the open "$(OPENAPI_GENERATOR_CLONE_DIR)"/run-in-docker.sh mvn package make generate -generate: $(OUTPUT_DIRECTORY) # Generates the open-api model +generate: $(OPENAPI_GENERATED_DIR) # Generates the open-api model rm -rf "$(OPENAPI_GENERATED_DIR)/*" && \ docker run --rm \ -v $(OPENAPI_DIR):/local openapitools/openapi-generator-cli:"$(OPENAPI_GENERATOR_GIT_TAG)" generate \ @@ -129,6 +125,7 @@ generate: $(OUTPUT_DIRECTORY) # Generates the open-api model -p packageName=Gravatar \ --additional-properties=useJsonEncodable=false,readonlyProperties=true,$(OPENAPI_CLIENT_PROPERTIES) && \ make swiftformat && \ + cp -fp "$(OPENAPI_GENERATED_DIR)/$(OPENAPI_PROJECT_NAME).podspec" "$(CURRENT_MAKEFILE_DIR)/" && \ echo "DONE! 🎉" @@ -140,22 +137,22 @@ download-strings: bundle-install bundle exec fastlane download_localized_strings clean-generated: # Delete the output directory used for generated sources. - @echo 'Delete entire directory: $(OUTPUT_DIRECTORY)? [y/N] ' && read ans && [ $${ans:-N} = y ] || (echo "Aborted"; exit 1) - rm -rf "$(OUTPUT_DIRECTORY)" + @echo 'Delete entire directory: $(OPENAPI_GENERATED_DIR)? [y/N] ' && read ans && [ $${ans:-N} = y ] || (echo "Aborted"; exit 1) + rm -rf "$(OPENAPI_GENERATED_DIR)" -clean: # Clean everything, including the checkout of swift-openapi-generator. +clean: # Clean everything @echo 'Delete checkout of openapi-generator $(OPENAPI_GENERATOR_CLONE_DIR)? [y/N] ' && read ans && [ $${ans:-N} = y ] || (echo "Aborted"; exit 1) - rm -rf "$(OPENAPI_GENERATOR_CLONE_DIR)" + rm -rf "$(OPENAPI_GENERATOR_CLONE_DIR)/*" dump: # Dump all derived values used by the Makefile. @echo "CURRENT_MAKEFILE_PATH = $(CURRENT_MAKEFILE_PATH)" @echo "CURRENT_MAKEFILE_DIR = $(CURRENT_MAKEFILE_DIR)" + @echo "OPENAPI_GENERATED_DIR = $(OPENAPI_GENERATED_DIR)" @echo "OPENAPI_GENERATOR_GIT_URL = $(OPENAPI_GENERATOR_GIT_URL)" @echo "OPENAPI_GENERATOR_GIT_TAG = $(OPENAPI_GENERATOR_GIT_TAG)" @echo "OPENAPI_GENERATOR_CLONE_DIR = $(OPENAPI_GENERATOR_CLONE_DIR)" @echo "OPENAPI_YAML_PATH = $(OPENAPI_YAML_PATH)" - @echo "OUTPUT_DIRECTORY = $(OUTPUT_DIRECTORY)" $(OPENAPI_GENERATOR_CLONE_DIR): git \ @@ -166,5 +163,5 @@ $(OPENAPI_GENERATOR_CLONE_DIR): "$(OPENAPI_GENERATOR_GIT_URL)" \ $@ -$(OUTPUT_DIRECTORY): +$(OPENAPI_GENERATED_DIR): mkdir -p "$@" diff --git a/openapi/GravatarOpenAPIClient/GravatarOpenAPIClient.podspec b/openapi/GravatarOpenAPIClient/GravatarOpenAPIClient.podspec index b3e38708..15ba2b8a 100644 --- a/openapi/GravatarOpenAPIClient/GravatarOpenAPIClient.podspec +++ b/openapi/GravatarOpenAPIClient/GravatarOpenAPIClient.podspec @@ -1,19 +1,23 @@ # frozen_string_literal: true +require_relative 'version' + Pod::Spec.new do |s| s.name = 'GravatarOpenAPIClient' s.summary = 'A Gravatar OpenAPI Client' - s.version = '2.1.1' + s.version = Gravatar::VERSION + + s.swift_versions = Gravatar::SWIFT_VERSIONS - # These are defined by openapi-generator + # Match the deployment target of Gravatar in order to satisfy `pod lib lint` s.ios.deployment_target = Gravatar::IOS_DEPLOYMENT_TARGET s.homepage = 'https://gravatar.com' - s.license = { type: 'Mozilla Public License v2', file: 'LICENSE.md'} + s.license = { type: 'Mozilla Public License v2', file: 'LICENSE.md' } s.authors = 'Automattic, Inc.' s.source = { :git => 'https://github.com/Automattic/Gravatar-SDK-iOS.git', :tag => s.version.to_s } s.documentation_url = 'https://automattic.github.io/Gravatar-SDK-iOS/gravatar' - s.source_files = 'Sources/GravatarOpenAPIClient/**/*.swift' + s.source_files = 'openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/**/*.swift' end diff --git a/openapi/templates/Podspec.mustache b/openapi/templates/Podspec.mustache index 1701fada..6db4fbb6 100644 --- a/openapi/templates/Podspec.mustache +++ b/openapi/templates/Podspec.mustache @@ -1,19 +1,23 @@ # frozen_string_literal: true +require_relative 'version' + Pod::Spec.new do |s| s.name = '{{projectName}}' s.summary = 'A Gravatar OpenAPI Client' - s.version = '{{podVersion}}{{^podVersion}}{{#apiInfo}}{{version}}{{/apiInfo}}{{^apiInfo}}}0.0.1{{/apiInfo}}{{/podVersion}}' + s.version = Gravatar::VERSION + + s.swift_versions = Gravatar::SWIFT_VERSIONS - # These are defined by openapi-generator + # Match the deployment target of Gravatar in order to satisfy `pod lib lint` s.ios.deployment_target = Gravatar::IOS_DEPLOYMENT_TARGET s.homepage = 'https://gravatar.com' - s.license = { type: 'Mozilla Public License v2', file: 'LICENSE.md'} + s.license = { type: 'Mozilla Public License v2', file: 'LICENSE.md' } s.authors = 'Automattic, Inc.' s.source = { :git => 'https://github.com/Automattic/Gravatar-SDK-iOS.git', :tag => s.version.to_s } s.documentation_url = 'https://automattic.github.io/Gravatar-SDK-iOS/gravatar' - s.source_files = '{{swiftPackagePath}}{{^swiftPackagePath}}{{#useSPMFileStructure}}Sources/{{projectName}}{{/useSPMFileStructure}}{{^useSPMFileStructure}}{{projectName}}/Classes{{/useSPMFileStructure}}{{/swiftPackagePath}}/**/*.swift' + s.source_files = '{{swiftPackagePath}}{{^swiftPackagePath}}{{#packageRootPath}}{{.}}/{{/packageRootPath}}{{#useSPMFileStructure}}Sources/{{projectName}}{{/useSPMFileStructure}}{{^useSPMFileStructure}}{{projectName}}/Classes{{/useSPMFileStructure}}{{/swiftPackagePath}}/**/*.swift' end From 3c19a1e958bd239679b4ba498ac2a23c3747784e Mon Sep 17 00:00:00 2001 From: Andrew Montgomery Date: Tue, 8 Oct 2024 16:44:18 -0500 Subject: [PATCH 09/20] Revert project.yml version --- openapi/GravatarOpenAPIClient/project.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openapi/GravatarOpenAPIClient/project.yml b/openapi/GravatarOpenAPIClient/project.yml index b7e48af1..3a9d171c 100644 --- a/openapi/GravatarOpenAPIClient/project.yml +++ b/openapi/GravatarOpenAPIClient/project.yml @@ -7,7 +7,7 @@ targets: sources: [Sources] info: path: ./Info.plist - version: 2.1.1 + version: 3.0.0 settings: APPLICATION_EXTENSION_API_ONLY: true scheme: {} From 024e041237a3b2aa4ffa1a0b10c9e529634aa2e6 Mon Sep 17 00:00:00 2001 From: Andrew Montgomery Date: Tue, 8 Oct 2024 17:29:47 -0500 Subject: [PATCH 10/20] Stop ignoring the `openapi-generator` directory, since we don't need it any more --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index ac56bfb8..6c91eae3 100644 --- a/.gitignore +++ b/.gitignore @@ -46,5 +46,4 @@ fastlane/report.xml fastlane/test_output # Other -openapi-generator/ Demo/Demo/Secrets.swift From 6e3d2a42c38287024ddbed1dbc129b9bbe43bd8a Mon Sep 17 00:00:00 2001 From: Andrew Montgomery Date: Wed, 9 Oct 2024 17:21:24 -0500 Subject: [PATCH 11/20] Move GravatarOpenAPIClient into module (without third-party dep) --- .gitignore | 11 ++ Makefile | 3 +- Package.resolved | 11 +- Package.swift | 11 +- .../GravatarOpenAPIClient/APIHelper.swift | 22 +-- .../GravatarOpenAPIClient/APIs.swift | 17 +-- .../GravatarOpenAPIClient/CodableHelper.swift | 21 ++- .../GravatarOpenAPIClient/Configuration.swift | 9 +- .../GravatarOpenAPIClient/Extensions.swift | 49 +++---- .../JSONDataEncoding.swift | 11 +- .../JSONEncodingHelper.swift | 15 +- .../GravatarOpenAPIClient/Models.swift | 10 +- .../Models/AssociatedResponse.swift | 22 +-- .../GravatarOpenAPIClient/Models/Avatar.swift | 21 +-- .../Models/CryptoWalletAddress.swift | 21 +-- .../Models/GalleryImage.swift | 21 +-- .../Models/Interest.swift | 21 +-- .../Models/Language.swift | 21 +-- .../GravatarOpenAPIClient/Models/Link.swift | 21 +-- .../Models/ModelError.swift | 21 +-- .../Models/Profile.swift | 52 ++++--- .../Models/ProfileContactInfo.swift | 30 ++-- .../Models/ProfilePayments.swift | 21 +-- .../Models/SetEmailAvatarRequest.swift | 22 +-- .../Models/VerifiedAccount.swift | 21 +-- .../OpenISO8601DateFormatter.swift | 7 - .../SynchronizedDictionary.swift | 11 +- .../URLSessionImplementations.swift | 132 +++++++++--------- .../GravatarOpenAPIClient/Validation.swift | 8 +- .../.openapi-generator-ignore | 1 + .../.openapi-generator/FILES | 1 - .../GravatarOpenAPIClient/Package.resolved | 16 +++ 32 files changed, 207 insertions(+), 474 deletions(-) rename {openapi/GravatarOpenAPIClient/Sources => Sources}/GravatarOpenAPIClient/APIHelper.swift (88%) rename {openapi/GravatarOpenAPIClient/Sources => Sources}/GravatarOpenAPIClient/APIs.swift (80%) rename {openapi/GravatarOpenAPIClient/Sources => Sources}/GravatarOpenAPIClient/CodableHelper.swift (69%) rename {openapi/GravatarOpenAPIClient/Sources => Sources}/GravatarOpenAPIClient/Configuration.swift (65%) rename {openapi/GravatarOpenAPIClient/Sources => Sources}/GravatarOpenAPIClient/Extensions.swift (81%) rename {openapi/GravatarOpenAPIClient/Sources => Sources}/GravatarOpenAPIClient/JSONDataEncoding.swift (90%) rename {openapi/GravatarOpenAPIClient/Sources => Sources}/GravatarOpenAPIClient/JSONEncodingHelper.swift (75%) rename {openapi/GravatarOpenAPIClient/Sources => Sources}/GravatarOpenAPIClient/Models.swift (94%) rename {openapi/GravatarOpenAPIClient/Sources => Sources}/GravatarOpenAPIClient/Models/AssociatedResponse.swift (84%) rename {openapi/GravatarOpenAPIClient/Sources => Sources}/GravatarOpenAPIClient/Models/Avatar.swift (94%) rename {openapi/GravatarOpenAPIClient/Sources => Sources}/GravatarOpenAPIClient/Models/CryptoWalletAddress.swift (87%) rename {openapi/GravatarOpenAPIClient/Sources => Sources}/GravatarOpenAPIClient/Models/GalleryImage.swift (87%) rename {openapi/GravatarOpenAPIClient/Sources => Sources}/GravatarOpenAPIClient/Models/Interest.swift (87%) rename {openapi/GravatarOpenAPIClient/Sources => Sources}/GravatarOpenAPIClient/Models/Language.swift (91%) rename {openapi/GravatarOpenAPIClient/Sources => Sources}/GravatarOpenAPIClient/Models/Link.swift (87%) rename {openapi/GravatarOpenAPIClient/Sources => Sources}/GravatarOpenAPIClient/Models/ModelError.swift (87%) rename {openapi/GravatarOpenAPIClient/Sources => Sources}/GravatarOpenAPIClient/Models/Profile.swift (90%) rename {openapi/GravatarOpenAPIClient/Sources => Sources}/GravatarOpenAPIClient/Models/ProfileContactInfo.swift (88%) rename {openapi/GravatarOpenAPIClient/Sources => Sources}/GravatarOpenAPIClient/Models/ProfilePayments.swift (89%) rename {openapi/GravatarOpenAPIClient/Sources => Sources}/GravatarOpenAPIClient/Models/SetEmailAvatarRequest.swift (84%) rename {openapi/GravatarOpenAPIClient/Sources => Sources}/GravatarOpenAPIClient/Models/VerifiedAccount.swift (92%) rename {openapi/GravatarOpenAPIClient/Sources => Sources}/GravatarOpenAPIClient/OpenISO8601DateFormatter.swift (93%) rename {openapi/GravatarOpenAPIClient/Sources => Sources}/GravatarOpenAPIClient/SynchronizedDictionary.swift (76%) rename {openapi/GravatarOpenAPIClient/Sources => Sources}/GravatarOpenAPIClient/URLSessionImplementations.swift (87%) rename {openapi/GravatarOpenAPIClient/Sources => Sources}/GravatarOpenAPIClient/Validation.swift (97%) create mode 100644 openapi/GravatarOpenAPIClient/Package.resolved diff --git a/.gitignore b/.gitignore index 6c91eae3..99d78867 100644 --- a/.gitignore +++ b/.gitignore @@ -45,5 +45,16 @@ fastlane/README.md fastlane/report.xml fastlane/test_output +# OpenAPI +openapi/GravatarOpenAPIClient/ +!openapi/GravatarOpenAPIClient/.gitignore +!openapi/GravatarOpenAPIClient/.openapi-generator/ +!openapi/GravatarOpenAPIClient/.openapi-generator-ignore +!openapi/GravatarOpenAPIClient/docs/ +!openapi/GravatarOpenAPIClient/GravatarOpenAPIClient.podspec +!openapi/GravatarOpenAPIClient/Package.swift +!openapi/GravatarOpenAPIClient/project.yml +!openapi/GravatarOpenAPIClient/README.md + # Other Demo/Demo/Secrets.swift diff --git a/Makefile b/Makefile index 85682089..3ecb77b8 100644 --- a/Makefile +++ b/Makefile @@ -124,8 +124,9 @@ generate: $(OPENAPI_GENERATED_DIR) # Generates the open-api model -g swift5 \ -p packageName=Gravatar \ --additional-properties=useJsonEncodable=false,readonlyProperties=true,$(OPENAPI_CLIENT_PROPERTIES) && \ - make swiftformat && \ + rsync -av --delete "$(OPENAPI_GENERATED_DIR)/Sources/$(OPENAPI_PROJECT_NAME)/" "$(CURRENT_MAKEFILE_DIR)/Sources/$(OPENAPI_PROJECT_NAME)/" && \ cp -fp "$(OPENAPI_GENERATED_DIR)/$(OPENAPI_PROJECT_NAME).podspec" "$(CURRENT_MAKEFILE_DIR)/" && \ + make swiftformat && \ echo "DONE! 🎉" diff --git a/Package.resolved b/Package.resolved index 2529a2aa..a54e8877 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,15 +1,6 @@ { - "originHash" : "f286c874d53f4f63ae9bc379fe0d0c9b6d434ca00525d0b39b97876e1db9fbbd", + "originHash" : "ce90f93a035f7d411d81060dce4cdc6d5bcbe81fce7d7260084532fa492ff797", "pins" : [ - { - "identity" : "anycodable", - "kind" : "remoteSourceControl", - "location" : "https://github.com/Flight-School/AnyCodable", - "state" : { - "revision" : "862808b2070cd908cb04f9aafe7de83d35f81b05", - "version" : "0.6.7" - } - }, { "identity" : "swift-snapshot-testing", "kind" : "remoteSourceControl", diff --git a/Package.swift b/Package.swift index c39138ba..f58f1841 100644 --- a/Package.swift +++ b/Package.swift @@ -25,15 +25,14 @@ let package = Package( dependencies: [ .package(url: "https://github.com/nicklockwood/SwiftFormat", from: "0.54.0"), .package(url: "https://github.com/pointfreeco/swift-snapshot-testing", from: "1.8.1"), - .package(url: "https://github.com/SimplyDanny/SwiftLintPlugins", exact: "0.56.2"), - .package(path: "openapi/GravatarOpenAPIClient") + .package(url: "https://github.com/SimplyDanny/SwiftLintPlugins", exact: "0.56.2") ], targets: [ // Targets are the basic building blocks of a package, defining a module or a test suite. // Targets can depend on other targets in this package and products from dependencies. .target( name: "Gravatar", - dependencies: [.product(name: "GravatarOpenAPIClient", package: "GravatarOpenAPIClient")], + dependencies: ["GravatarOpenAPIClient"], resources: [.process("Resources")], swiftSettings: [ .enableExperimentalFeature("StrictConcurrency") @@ -74,6 +73,12 @@ let package = Package( swiftSettings: [ .enableExperimentalFeature("StrictConcurrency") ] + ), + .target( + name: "GravatarOpenAPIClient", + swiftSettings: [ + .enableExperimentalFeature("StrictConcurrency") + ] ) ] ) diff --git a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/APIHelper.swift b/Sources/GravatarOpenAPIClient/APIHelper.swift similarity index 88% rename from openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/APIHelper.swift rename to Sources/GravatarOpenAPIClient/APIHelper.swift index 6dd1b44c..afd13cd6 100644 --- a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/APIHelper.swift +++ b/Sources/GravatarOpenAPIClient/APIHelper.swift @@ -1,12 +1,6 @@ -// APIHelper.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech -// - import Foundation -public struct APIHelper { +public enum APIHelper { public static func rejectNil(_ source: [String: Any?]) -> [String: Any]? { let destination = source.reduce(into: [String: Any]()) { result, item in if let value = item.value { @@ -21,7 +15,7 @@ public struct APIHelper { } public static func rejectNilHeaders(_ source: [String: Any?]) -> [String: String] { - return source.reduce(into: [String: String]()) { result, item in + source.reduce(into: [String: String]()) { result, item in if let collection = item.value as? [Any?] { result[item.key] = collection .compactMap { value in convertAnyToString(value) } @@ -33,7 +27,7 @@ public struct APIHelper { } public static func convertBoolToString(_ source: [String: Any]?) -> [String: Any]? { - guard let source = source else { + guard let source else { return nil } @@ -48,7 +42,7 @@ public struct APIHelper { } public static func convertAnyToString(_ value: Any?) -> String? { - guard let value = value else { return nil } + guard let value else { return nil } if let value = value as? any RawRepresentable { return "\(value.rawValue)" } else { @@ -71,16 +65,14 @@ public struct APIHelper { public static func mapValuesToQueryItems(_ source: [String: (wrappedValue: Any?, isExplode: Bool)]) -> [URLQueryItem]? { let destination = source.filter { $0.value.wrappedValue != nil }.reduce(into: [URLQueryItem]()) { result, item in if let collection = item.value.wrappedValue as? [Any?] { - let collectionValues: [String] = collection.compactMap { value in convertAnyToString(value) } if !item.value.isExplode { result.append(URLQueryItem(name: item.key, value: collectionValues.joined(separator: ","))) } else { - collectionValues - .forEach { value in - result.append(URLQueryItem(name: item.key, value: value)) - } + for value in collectionValues { + result.append(URLQueryItem(name: item.key, value: value)) + } } } else if let value = item.value.wrappedValue { diff --git a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/APIs.swift b/Sources/GravatarOpenAPIClient/APIs.swift similarity index 80% rename from openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/APIs.swift rename to Sources/GravatarOpenAPIClient/APIs.swift index 1c80cf4c..5bbb200e 100644 --- a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/APIs.swift +++ b/Sources/GravatarOpenAPIClient/APIs.swift @@ -1,9 +1,3 @@ -// APIs.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech -// - import Foundation #if canImport(FoundationNetworking) import FoundationNetworking @@ -22,13 +16,13 @@ open class RequestBuilder { public let parameters: [String: Any]? public let method: String public let URLString: String - public let requestTask: RequestTask = RequestTask() + public let requestTask: RequestTask = .init() public let requiresAuthentication: Bool /// Optional block to obtain a reference to the request's progress instance when available. public var onProgressReady: ((Progress) -> Void)? - required public init(method: String, URLString: String, parameters: [String: Any]?, headers: [String: String] = [:], requiresAuthentication: Bool) { + public required init(method: String, URLString: String, parameters: [String: Any]?, headers: [String: String] = [:], requiresAuthentication: Bool) { self.method = method self.URLString = URLString self.parameters = parameters @@ -45,8 +39,11 @@ open class RequestBuilder { } @discardableResult - open func execute(_ apiResponseQueue: DispatchQueue = GravatarOpenAPIClientAPI.apiResponseQueue, _ completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) -> RequestTask { - return requestTask + open func execute( + _: DispatchQueue = GravatarOpenAPIClientAPI.apiResponseQueue, + _: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void + ) -> RequestTask { + requestTask } public func addHeader(name: String, value: String) -> Self { diff --git a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/CodableHelper.swift b/Sources/GravatarOpenAPIClient/CodableHelper.swift similarity index 69% rename from openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/CodableHelper.swift rename to Sources/GravatarOpenAPIClient/CodableHelper.swift index 09c82e53..e7c23d1d 100644 --- a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/CodableHelper.swift +++ b/Sources/GravatarOpenAPIClient/CodableHelper.swift @@ -1,10 +1,3 @@ -// -// CodableHelper.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech -// - import Foundation open class CodableHelper { @@ -27,23 +20,25 @@ open class CodableHelper { }() public static var dateFormatter: DateFormatter { - get { return customDateFormatter ?? defaultDateFormatter } + get { customDateFormatter ?? defaultDateFormatter } set { customDateFormatter = newValue } } + public static var jsonDecoder: JSONDecoder { - get { return customJSONDecoder ?? defaultJSONDecoder } + get { customJSONDecoder ?? defaultJSONDecoder } set { customJSONDecoder = newValue } } + public static var jsonEncoder: JSONEncoder { - get { return customJSONEncoder ?? defaultJSONEncoder } + get { customJSONEncoder ?? defaultJSONEncoder } set { customJSONEncoder = newValue } } open class func decode(_ type: T.Type, from data: Data) -> Swift.Result where T: Decodable { - return Swift.Result { try jsonDecoder.decode(type, from: data) } + Swift.Result { try jsonDecoder.decode(type, from: data) } } - open class func encode(_ value: T) -> Swift.Result where T: Encodable { - return Swift.Result { try jsonEncoder.encode(value) } + open class func encode(_ value: some Encodable) -> Swift.Result { + Swift.Result { try jsonEncoder.encode(value) } } } diff --git a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Configuration.swift b/Sources/GravatarOpenAPIClient/Configuration.swift similarity index 65% rename from openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Configuration.swift rename to Sources/GravatarOpenAPIClient/Configuration.swift index 0457d990..f66f68de 100644 --- a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Configuration.swift +++ b/Sources/GravatarOpenAPIClient/Configuration.swift @@ -1,18 +1,11 @@ -// Configuration.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech -// - import Foundation #if canImport(FoundationNetworking) import FoundationNetworking #endif open class Configuration { - /// Configures the range of HTTP status codes that will result in a successful response /// /// If a HTTP status code is outside of this range the response will be interpreted as failed. - public static var successfulStatusCodeRange: Range = 200..<300 + public static var successfulStatusCodeRange: Range = 200 ..< 300 } diff --git a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Extensions.swift b/Sources/GravatarOpenAPIClient/Extensions.swift similarity index 81% rename from openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Extensions.swift rename to Sources/GravatarOpenAPIClient/Extensions.swift index ac04dba5..bb09d70f 100644 --- a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Extensions.swift +++ b/Sources/GravatarOpenAPIClient/Extensions.swift @@ -1,9 +1,3 @@ -// Extensions.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech -// - import Foundation #if canImport(FoundationNetworking) import FoundationNetworking @@ -53,26 +47,26 @@ extension UUID: JSONEncodable { } extension RawRepresentable where RawValue: JSONEncodable { - func encodeToJSON() -> Any { return self.rawValue } + func encodeToJSON() -> Any { self.rawValue } } -private func encodeIfPossible(_ object: T) -> Any { +private func encodeIfPossible(_ object: some Any) -> Any { if let encodableObject = object as? JSONEncodable { - return encodableObject.encodeToJSON() + encodableObject.encodeToJSON() } else { - return object + object } } extension Array: JSONEncodable { func encodeToJSON() -> Any { - return self.map(encodeIfPossible) + self.map(encodeIfPossible) } } extension Set: JSONEncodable { func encodeToJSON() -> Any { - return Array(self).encodeToJSON() + Array(self).encodeToJSON() } } @@ -88,13 +82,13 @@ extension Dictionary: JSONEncodable { extension Data: JSONEncodable { func encodeToJSON() -> Any { - return self.base64EncodedString(options: Data.Base64EncodingOptions()) + self.base64EncodedString(options: Data.Base64EncodingOptions()) } } extension Date: JSONEncodable { func encodeToJSON() -> Any { - return CodableHelper.dateFormatter.string(from: self) + CodableHelper.dateFormatter.string(from: self) } } @@ -108,9 +102,8 @@ extension JSONEncodable where Self: Encodable { } extension String: CodingKey { - public var stringValue: String { - return self + self } public init?(stringValue: String) { @@ -118,36 +111,34 @@ extension String: CodingKey { } public var intValue: Int? { - return nil + nil } public init?(intValue: Int) { - return nil + nil } - } extension KeyedEncodingContainerProtocol { - - public mutating func encodeArray(_ values: [T], forKey key: Self.Key) throws where T: Encodable { + public mutating func encodeArray(_ values: [some Encodable], forKey key: Self.Key) throws { var arrayContainer = nestedUnkeyedContainer(forKey: key) try arrayContainer.encode(contentsOf: values) } - public mutating func encodeArrayIfPresent(_ values: [T]?, forKey key: Self.Key) throws where T: Encodable { - if let values = values { + public mutating func encodeArrayIfPresent(_ values: [some Encodable]?, forKey key: Self.Key) throws { + if let values { try encodeArray(values, forKey: key) } } - public mutating func encodeMap(_ pairs: [Self.Key: T]) throws where T: Encodable { + public mutating func encodeMap(_ pairs: [Self.Key: some Encodable]) throws { for (key, value) in pairs { try encode(value, forKey: key) } } - public mutating func encodeMapIfPresent(_ pairs: [Self.Key: T]?) throws where T: Encodable { - if let pairs = pairs { + public mutating func encodeMapIfPresent(_ pairs: [Self.Key: some Encodable]?) throws { + if let pairs { try encodeMap(pairs) } } @@ -159,14 +150,13 @@ extension KeyedEncodingContainerProtocol { } public mutating func encodeIfPresent(_ value: Decimal?, forKey key: Self.Key) throws { - if let value = value { + if let value { try encode(value, forKey: key) } } } extension KeyedDecodingContainerProtocol { - public func decodeArray(_ type: T.Type, forKey key: Self.Key) throws -> [T] where T: Decodable { var tmpArray = [T]() @@ -223,11 +213,10 @@ extension KeyedDecodingContainerProtocol { return decimalValue } - } extension HTTPURLResponse { var isStatusCodeSuccessful: Bool { - return Configuration.successfulStatusCodeRange.contains(statusCode) + Configuration.successfulStatusCodeRange.contains(statusCode) } } diff --git a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/JSONDataEncoding.swift b/Sources/GravatarOpenAPIClient/JSONDataEncoding.swift similarity index 90% rename from openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/JSONDataEncoding.swift rename to Sources/GravatarOpenAPIClient/JSONDataEncoding.swift index cb3121a4..b0fecb5f 100644 --- a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/JSONDataEncoding.swift +++ b/Sources/GravatarOpenAPIClient/JSONDataEncoding.swift @@ -1,17 +1,9 @@ -// -// JSONDataEncoding.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech -// - import Foundation #if canImport(FoundationNetworking) import FoundationNetworking #endif public struct JSONDataEncoding { - // MARK: Properties private static let jsonDataKey = "jsonData" @@ -45,12 +37,11 @@ public struct JSONDataEncoding { public static func encodingParameters(jsonData: Data?) -> [String: Any]? { var returnedParams: [String: Any]? - if let jsonData = jsonData, !jsonData.isEmpty { + if let jsonData, !jsonData.isEmpty { var params: [String: Any] = [:] params[jsonDataKey] = jsonData returnedParams = params } return returnedParams } - } diff --git a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/JSONEncodingHelper.swift b/Sources/GravatarOpenAPIClient/JSONEncodingHelper.swift similarity index 75% rename from openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/JSONEncodingHelper.swift rename to Sources/GravatarOpenAPIClient/JSONEncodingHelper.swift index 02f78ffb..c7cbd646 100644 --- a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/JSONEncodingHelper.swift +++ b/Sources/GravatarOpenAPIClient/JSONEncodingHelper.swift @@ -1,19 +1,11 @@ -// -// JSONEncodingHelper.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech -// - import Foundation open class JSONEncodingHelper { - - open class func encodingParameters(forEncodableObject encodableObj: T?) -> [String: Any]? { + open class func encodingParameters(forEncodableObject encodableObj: (some Encodable)?) -> [String: Any]? { var params: [String: Any]? // Encode the Encodable object - if let encodableObj = encodableObj { + if let encodableObj { let encodeResult = CodableHelper.encode(encodableObj) do { let data = try encodeResult.get() @@ -29,7 +21,7 @@ open class JSONEncodingHelper { open class func encodingParameters(forEncodableObject encodableObj: Any?) -> [String: Any]? { var params: [String: Any]? - if let encodableObj = encodableObj { + if let encodableObj { do { let data = try JSONSerialization.data(withJSONObject: encodableObj, options: .prettyPrinted) params = JSONDataEncoding.encodingParameters(jsonData: data) @@ -41,5 +33,4 @@ open class JSONEncodingHelper { return params } - } diff --git a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models.swift b/Sources/GravatarOpenAPIClient/Models.swift similarity index 94% rename from openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models.swift rename to Sources/GravatarOpenAPIClient/Models.swift index 7094040c..00d31cb2 100644 --- a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models.swift +++ b/Sources/GravatarOpenAPIClient/Models.swift @@ -1,9 +1,3 @@ -// Models.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech -// - import Foundation #if canImport(FoundationNetworking) import FoundationNetworking @@ -15,7 +9,7 @@ protocol JSONEncodable { /// An enum where the last case value can be used as a default catch-all. protocol CaseIterableDefaultsLast: Decodable & CaseIterable & RawRepresentable -where RawValue: Decodable, AllCases: BidirectionalCollection {} + where RawValue: Decodable, AllCases: BidirectionalCollection {} extension CaseIterableDefaultsLast { /// Initializes an enum such that if a known raw value is found, then it is decoded. @@ -114,7 +108,7 @@ public final class RequestTask { private var lock = NSRecursiveLock() private var task: URLSessionTask? - internal func set(task: URLSessionTask) { + func set(task: URLSessionTask) { lock.lock() defer { lock.unlock() } self.task = task diff --git a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/AssociatedResponse.swift b/Sources/GravatarOpenAPIClient/Models/AssociatedResponse.swift similarity index 84% rename from openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/AssociatedResponse.swift rename to Sources/GravatarOpenAPIClient/Models/AssociatedResponse.swift index 5c530c59..7bc94dc6 100644 --- a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/AssociatedResponse.swift +++ b/Sources/GravatarOpenAPIClient/Models/AssociatedResponse.swift @@ -1,15 +1,6 @@ -// -// AssociatedResponse.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech -// - import Foundation - public struct AssociatedResponse: Codable, Hashable, Sendable { - /// Whether the entity is associated with the account. public private(set) var associated: Bool @@ -23,16 +14,10 @@ public struct AssociatedResponse: Codable, Hashable, Sendable { case associated } - - - - internal enum InternalCodingKeys: String, CodingKey, CaseIterable { + enum InternalCodingKeys: String, CodingKey, CaseIterable { case associated } - - - // Encodable protocol methods public func encode(to encoder: Encoder) throws { @@ -40,7 +25,6 @@ public struct AssociatedResponse: Codable, Hashable, Sendable { try container.encode(associated, forKey: .associated) } - // Decodable protocol methods public init(from decoder: Decoder) throws { @@ -48,8 +32,4 @@ public struct AssociatedResponse: Codable, Hashable, Sendable { associated = try container.decode(Bool.self, forKey: .associated) } - - - } - diff --git a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/Avatar.swift b/Sources/GravatarOpenAPIClient/Models/Avatar.swift similarity index 94% rename from openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/Avatar.swift rename to Sources/GravatarOpenAPIClient/Models/Avatar.swift index fb55cacb..f74c7f3c 100644 --- a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/Avatar.swift +++ b/Sources/GravatarOpenAPIClient/Models/Avatar.swift @@ -1,16 +1,8 @@ -// -// Avatar.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech -// - import Foundation /// An avatar that the user has already uploaded to their Gravatar account. /// public struct Avatar: Codable, Hashable, Sendable { - public enum Rating: String, Codable, CaseIterable, Sendable { case g = "G" case pg = "PG" @@ -51,10 +43,7 @@ public struct Avatar: Codable, Hashable, Sendable { case selected } - - - - internal enum InternalCodingKeys: String, CodingKey, CaseIterable { + enum InternalCodingKeys: String, CodingKey, CaseIterable { case imageId = "image_id" case imageUrl = "image_url" case rating @@ -63,9 +52,6 @@ public struct Avatar: Codable, Hashable, Sendable { case selected } - - - // Encodable protocol methods public func encode(to encoder: Encoder) throws { @@ -78,7 +64,6 @@ public struct Avatar: Codable, Hashable, Sendable { try container.encodeIfPresent(selected, forKey: .selected) } - // Decodable protocol methods public init(from decoder: Decoder) throws { @@ -91,8 +76,4 @@ public struct Avatar: Codable, Hashable, Sendable { altText = try container.decode(String.self, forKey: .altText) selected = try container.decodeIfPresent(Bool.self, forKey: .selected) } - - - } - diff --git a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/CryptoWalletAddress.swift b/Sources/GravatarOpenAPIClient/Models/CryptoWalletAddress.swift similarity index 87% rename from openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/CryptoWalletAddress.swift rename to Sources/GravatarOpenAPIClient/Models/CryptoWalletAddress.swift index 20896a7a..ddafe110 100644 --- a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/CryptoWalletAddress.swift +++ b/Sources/GravatarOpenAPIClient/Models/CryptoWalletAddress.swift @@ -1,16 +1,8 @@ -// -// CryptoWalletAddress.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech -// - import Foundation /// A crypto currency wallet address the user accepts. /// public struct CryptoWalletAddress: Codable, Hashable, Sendable { - /// The label for the crypto currency. public private(set) var label: String /// The wallet address for the crypto currency. @@ -28,17 +20,11 @@ public struct CryptoWalletAddress: Codable, Hashable, Sendable { case address } - - - - internal enum InternalCodingKeys: String, CodingKey, CaseIterable { + enum InternalCodingKeys: String, CodingKey, CaseIterable { case label case address } - - - // Encodable protocol methods public func encode(to encoder: Encoder) throws { @@ -47,7 +33,6 @@ public struct CryptoWalletAddress: Codable, Hashable, Sendable { try container.encode(address, forKey: .address) } - // Decodable protocol methods public init(from decoder: Decoder) throws { @@ -56,8 +41,4 @@ public struct CryptoWalletAddress: Codable, Hashable, Sendable { label = try container.decode(String.self, forKey: .label) address = try container.decode(String.self, forKey: .address) } - - - } - diff --git a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/GalleryImage.swift b/Sources/GravatarOpenAPIClient/Models/GalleryImage.swift similarity index 87% rename from openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/GalleryImage.swift rename to Sources/GravatarOpenAPIClient/Models/GalleryImage.swift index 739c5ec5..632638f1 100644 --- a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/GalleryImage.swift +++ b/Sources/GravatarOpenAPIClient/Models/GalleryImage.swift @@ -1,16 +1,8 @@ -// -// GalleryImage.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech -// - import Foundation /// A gallery image a user has uploaded. /// public struct GalleryImage: Codable, Hashable, Sendable { - /// The URL to the image. public private(set) var url: String /// The image alt text. @@ -28,17 +20,11 @@ public struct GalleryImage: Codable, Hashable, Sendable { case altText = "alt_text" } - - - - internal enum InternalCodingKeys: String, CodingKey, CaseIterable { + enum InternalCodingKeys: String, CodingKey, CaseIterable { case url case altText = "alt_text" } - - - // Encodable protocol methods public func encode(to encoder: Encoder) throws { @@ -47,7 +33,6 @@ public struct GalleryImage: Codable, Hashable, Sendable { try container.encodeIfPresent(altText, forKey: .altText) } - // Decodable protocol methods public init(from decoder: Decoder) throws { @@ -56,8 +41,4 @@ public struct GalleryImage: Codable, Hashable, Sendable { url = try container.decode(String.self, forKey: .url) altText = try container.decodeIfPresent(String.self, forKey: .altText) } - - - } - diff --git a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/Interest.swift b/Sources/GravatarOpenAPIClient/Models/Interest.swift similarity index 87% rename from openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/Interest.swift rename to Sources/GravatarOpenAPIClient/Models/Interest.swift index 7fefad0d..2ce8cef5 100644 --- a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/Interest.swift +++ b/Sources/GravatarOpenAPIClient/Models/Interest.swift @@ -1,16 +1,8 @@ -// -// Interest.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech -// - import Foundation /// An interest the user has added to their profile. /// public struct Interest: Codable, Hashable, Sendable { - /// The unique identifier for the interest. public private(set) var id: Int /// The name of the interest. @@ -28,17 +20,11 @@ public struct Interest: Codable, Hashable, Sendable { case name } - - - - internal enum InternalCodingKeys: String, CodingKey, CaseIterable { + enum InternalCodingKeys: String, CodingKey, CaseIterable { case id case name } - - - // Encodable protocol methods public func encode(to encoder: Encoder) throws { @@ -47,7 +33,6 @@ public struct Interest: Codable, Hashable, Sendable { try container.encode(name, forKey: .name) } - // Decodable protocol methods public init(from decoder: Decoder) throws { @@ -56,8 +41,4 @@ public struct Interest: Codable, Hashable, Sendable { id = try container.decode(Int.self, forKey: .id) name = try container.decode(String.self, forKey: .name) } - - - } - diff --git a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/Language.swift b/Sources/GravatarOpenAPIClient/Models/Language.swift similarity index 91% rename from openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/Language.swift rename to Sources/GravatarOpenAPIClient/Models/Language.swift index ac357bf3..95f70c9f 100644 --- a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/Language.swift +++ b/Sources/GravatarOpenAPIClient/Models/Language.swift @@ -1,16 +1,8 @@ -// -// Language.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech -// - import Foundation /// The languages the user knows. This is only provided in authenticated API requests. /// public struct Language: Codable, Hashable, Sendable { - /// The language code. public private(set) var code: String /// The language name. @@ -36,19 +28,13 @@ public struct Language: Codable, Hashable, Sendable { case order } - - - - internal enum InternalCodingKeys: String, CodingKey, CaseIterable { + enum InternalCodingKeys: String, CodingKey, CaseIterable { case code case name case isPrimary = "is_primary" case order } - - - // Encodable protocol methods public func encode(to encoder: Encoder) throws { @@ -59,7 +45,6 @@ public struct Language: Codable, Hashable, Sendable { try container.encode(order, forKey: .order) } - // Decodable protocol methods public init(from decoder: Decoder) throws { @@ -70,8 +55,4 @@ public struct Language: Codable, Hashable, Sendable { isPrimary = try container.decode(Bool.self, forKey: .isPrimary) order = try container.decode(Int.self, forKey: .order) } - - - } - diff --git a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/Link.swift b/Sources/GravatarOpenAPIClient/Models/Link.swift similarity index 87% rename from openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/Link.swift rename to Sources/GravatarOpenAPIClient/Models/Link.swift index 813c72b1..27fd4b81 100644 --- a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/Link.swift +++ b/Sources/GravatarOpenAPIClient/Models/Link.swift @@ -1,16 +1,8 @@ -// -// Link.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech -// - import Foundation /// A link the user has added to their profile. /// public struct Link: Codable, Hashable, Sendable { - /// The label for the link. public private(set) var label: String /// The URL to the link. @@ -28,17 +20,11 @@ public struct Link: Codable, Hashable, Sendable { case url } - - - - internal enum InternalCodingKeys: String, CodingKey, CaseIterable { + enum InternalCodingKeys: String, CodingKey, CaseIterable { case label case url } - - - // Encodable protocol methods public func encode(to encoder: Encoder) throws { @@ -47,7 +33,6 @@ public struct Link: Codable, Hashable, Sendable { try container.encode(url, forKey: .url) } - // Decodable protocol methods public init(from decoder: Decoder) throws { @@ -56,8 +41,4 @@ public struct Link: Codable, Hashable, Sendable { label = try container.decode(String.self, forKey: .label) url = try container.decode(String.self, forKey: .url) } - - - } - diff --git a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/ModelError.swift b/Sources/GravatarOpenAPIClient/Models/ModelError.swift similarity index 87% rename from openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/ModelError.swift rename to Sources/GravatarOpenAPIClient/Models/ModelError.swift index 4f5be692..44d6a799 100644 --- a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/ModelError.swift +++ b/Sources/GravatarOpenAPIClient/Models/ModelError.swift @@ -1,16 +1,8 @@ -// -// ModelError.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech -// - import Foundation /// An error response from the API. /// public struct ModelError: Codable, Hashable, Sendable { - /// The error message public private(set) var error: String /// The error code for the error message @@ -28,17 +20,11 @@ public struct ModelError: Codable, Hashable, Sendable { case code } - - - - internal enum InternalCodingKeys: String, CodingKey, CaseIterable { + enum InternalCodingKeys: String, CodingKey, CaseIterable { case error case code } - - - // Encodable protocol methods public func encode(to encoder: Encoder) throws { @@ -47,7 +33,6 @@ public struct ModelError: Codable, Hashable, Sendable { try container.encodeIfPresent(code, forKey: .code) } - // Decodable protocol methods public init(from decoder: Decoder) throws { @@ -56,8 +41,4 @@ public struct ModelError: Codable, Hashable, Sendable { error = try container.decode(String.self, forKey: .error) code = try container.decodeIfPresent(String.self, forKey: .code) } - - - } - diff --git a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/Profile.swift b/Sources/GravatarOpenAPIClient/Models/Profile.swift similarity index 90% rename from openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/Profile.swift rename to Sources/GravatarOpenAPIClient/Models/Profile.swift index 7d0b0c05..93870223 100644 --- a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/Profile.swift +++ b/Sources/GravatarOpenAPIClient/Models/Profile.swift @@ -1,16 +1,8 @@ -// -// Profile.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech -// - import Foundation /// A user's profile information. /// public struct Profile: Codable, Hashable, Sendable { - /// The SHA256 hash of the user's primary email address. public private(set) var hash: String /// The user's display name. This is the name that is displayed on their profile. @@ -53,7 +45,8 @@ public struct Profile: Codable, Hashable, Sendable { public private(set) var contactInfo: ProfileContactInfo? /// Additional images a user has uploaded. This is only provided in authenticated API requests. public private(set) var gallery: [GalleryImage]? - /// The number of verified accounts the user has added to their profile. This count includes verified accounts the user is hiding from their profile. This is only provided in authenticated API requests. + /// The number of verified accounts the user has added to their profile. This count includes verified accounts the user is hiding from their profile. This + /// is only provided in authenticated API requests. public private(set) var numberVerifiedAccounts: Int? /// The date and time (UTC) the user last edited their profile. This is only provided in authenticated API requests. public private(set) var lastProfileEdit: Date? @@ -61,7 +54,33 @@ public struct Profile: Codable, Hashable, Sendable { public private(set) var registrationDate: Date? @available(*, deprecated, message: "init will become internal on the next release") - public init(hash: String, displayName: String, profileUrl: String, avatarUrl: String, avatarAltText: String, location: String, description: String, jobTitle: String, company: String, verifiedAccounts: [VerifiedAccount], pronunciation: String, pronouns: String, timezone: String? = nil, languages: [Language]? = nil, firstName: String? = nil, lastName: String? = nil, isOrganization: Bool? = nil, links: [Link]? = nil, interests: [Interest]? = nil, payments: ProfilePayments? = nil, contactInfo: ProfileContactInfo? = nil, gallery: [GalleryImage]? = nil, numberVerifiedAccounts: Int? = nil, lastProfileEdit: Date? = nil, registrationDate: Date? = nil) { + public init( + hash: String, + displayName: String, + profileUrl: String, + avatarUrl: String, + avatarAltText: String, + location: String, + description: String, + jobTitle: String, + company: String, + verifiedAccounts: [VerifiedAccount], + pronunciation: String, + pronouns: String, + timezone: String? = nil, + languages: [Language]? = nil, + firstName: String? = nil, + lastName: String? = nil, + isOrganization: Bool? = nil, + links: [Link]? = nil, + interests: [Interest]? = nil, + payments: ProfilePayments? = nil, + contactInfo: ProfileContactInfo? = nil, + gallery: [GalleryImage]? = nil, + numberVerifiedAccounts: Int? = nil, + lastProfileEdit: Date? = nil, + registrationDate: Date? = nil + ) { self.hash = hash self.displayName = displayName self.profileUrl = profileUrl @@ -118,10 +137,7 @@ public struct Profile: Codable, Hashable, Sendable { case registrationDate = "registration_date" } - - - - internal enum InternalCodingKeys: String, CodingKey, CaseIterable { + enum InternalCodingKeys: String, CodingKey, CaseIterable { case hash case displayName = "display_name" case profileUrl = "profile_url" @@ -149,9 +165,6 @@ public struct Profile: Codable, Hashable, Sendable { case registrationDate = "registration_date" } - - - // Encodable protocol methods public func encode(to encoder: Encoder) throws { @@ -183,7 +196,6 @@ public struct Profile: Codable, Hashable, Sendable { try container.encodeIfPresent(registrationDate, forKey: .registrationDate) } - // Decodable protocol methods public init(from decoder: Decoder) throws { @@ -215,8 +227,4 @@ public struct Profile: Codable, Hashable, Sendable { lastProfileEdit = try container.decodeIfPresent(Date.self, forKey: .lastProfileEdit) registrationDate = try container.decodeIfPresent(Date.self, forKey: .registrationDate) } - - - } - diff --git a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/ProfileContactInfo.swift b/Sources/GravatarOpenAPIClient/Models/ProfileContactInfo.swift similarity index 88% rename from openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/ProfileContactInfo.swift rename to Sources/GravatarOpenAPIClient/Models/ProfileContactInfo.swift index 16aaf252..2895a6e5 100644 --- a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/ProfileContactInfo.swift +++ b/Sources/GravatarOpenAPIClient/Models/ProfileContactInfo.swift @@ -1,16 +1,8 @@ -// -// ProfileContactInfo.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech -// - import Foundation /// The user's contact information. This is only available if the user has chosen to make it public. This is only provided in authenticated API requests. /// public struct ProfileContactInfo: Codable, Hashable, Sendable { - /// The user's home phone number. public private(set) var homePhone: String? /// The user's work phone number. @@ -25,7 +17,14 @@ public struct ProfileContactInfo: Codable, Hashable, Sendable { public private(set) var calendar: String? @available(*, deprecated, message: "init will become internal on the next release") - public init(homePhone: String? = nil, workPhone: String? = nil, cellPhone: String? = nil, email: String? = nil, contactForm: String? = nil, calendar: String? = nil) { + public init( + homePhone: String? = nil, + workPhone: String? = nil, + cellPhone: String? = nil, + email: String? = nil, + contactForm: String? = nil, + calendar: String? = nil + ) { self.homePhone = homePhone self.workPhone = workPhone self.cellPhone = cellPhone @@ -44,10 +43,7 @@ public struct ProfileContactInfo: Codable, Hashable, Sendable { case calendar } - - - - internal enum InternalCodingKeys: String, CodingKey, CaseIterable { + enum InternalCodingKeys: String, CodingKey, CaseIterable { case homePhone = "home_phone" case workPhone = "work_phone" case cellPhone = "cell_phone" @@ -56,9 +52,6 @@ public struct ProfileContactInfo: Codable, Hashable, Sendable { case calendar } - - - // Encodable protocol methods public func encode(to encoder: Encoder) throws { @@ -71,7 +64,6 @@ public struct ProfileContactInfo: Codable, Hashable, Sendable { try container.encodeIfPresent(calendar, forKey: .calendar) } - // Decodable protocol methods public init(from decoder: Decoder) throws { @@ -84,8 +76,4 @@ public struct ProfileContactInfo: Codable, Hashable, Sendable { contactForm = try container.decodeIfPresent(String.self, forKey: .contactForm) calendar = try container.decodeIfPresent(String.self, forKey: .calendar) } - - - } - diff --git a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/ProfilePayments.swift b/Sources/GravatarOpenAPIClient/Models/ProfilePayments.swift similarity index 89% rename from openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/ProfilePayments.swift rename to Sources/GravatarOpenAPIClient/Models/ProfilePayments.swift index 0ef1ecce..841afe2d 100644 --- a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/ProfilePayments.swift +++ b/Sources/GravatarOpenAPIClient/Models/ProfilePayments.swift @@ -1,16 +1,8 @@ -// -// ProfilePayments.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech -// - import Foundation /// The user's public payment information. This is only provided in authenticated API requests. /// public struct ProfilePayments: Codable, Hashable, Sendable { - /// A list of payment URLs the user has added to their profile. public private(set) var links: [Link] /// A list of crypto currencies the user accepts. @@ -28,17 +20,11 @@ public struct ProfilePayments: Codable, Hashable, Sendable { case cryptoWallets = "crypto_wallets" } - - - - internal enum InternalCodingKeys: String, CodingKey, CaseIterable { + enum InternalCodingKeys: String, CodingKey, CaseIterable { case links case cryptoWallets = "crypto_wallets" } - - - // Encodable protocol methods public func encode(to encoder: Encoder) throws { @@ -47,7 +33,6 @@ public struct ProfilePayments: Codable, Hashable, Sendable { try container.encode(cryptoWallets, forKey: .cryptoWallets) } - // Decodable protocol methods public init(from decoder: Decoder) throws { @@ -56,8 +41,4 @@ public struct ProfilePayments: Codable, Hashable, Sendable { links = try container.decode([Link].self, forKey: .links) cryptoWallets = try container.decode([CryptoWalletAddress].self, forKey: .cryptoWallets) } - - - } - diff --git a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/SetEmailAvatarRequest.swift b/Sources/GravatarOpenAPIClient/Models/SetEmailAvatarRequest.swift similarity index 84% rename from openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/SetEmailAvatarRequest.swift rename to Sources/GravatarOpenAPIClient/Models/SetEmailAvatarRequest.swift index 51e5c8ff..2e6741a4 100644 --- a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/SetEmailAvatarRequest.swift +++ b/Sources/GravatarOpenAPIClient/Models/SetEmailAvatarRequest.swift @@ -1,15 +1,6 @@ -// -// SetEmailAvatarRequest.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech -// - import Foundation - public struct SetEmailAvatarRequest: Codable, Hashable, Sendable { - /// The email SHA256 hash to set the avatar for. public private(set) var emailHash: String @@ -23,16 +14,10 @@ public struct SetEmailAvatarRequest: Codable, Hashable, Sendable { case emailHash = "email_hash" } - - - - internal enum InternalCodingKeys: String, CodingKey, CaseIterable { + enum InternalCodingKeys: String, CodingKey, CaseIterable { case emailHash = "email_hash" } - - - // Encodable protocol methods public func encode(to encoder: Encoder) throws { @@ -40,7 +25,6 @@ public struct SetEmailAvatarRequest: Codable, Hashable, Sendable { try container.encode(emailHash, forKey: .emailHash) } - // Decodable protocol methods public init(from decoder: Decoder) throws { @@ -48,8 +32,4 @@ public struct SetEmailAvatarRequest: Codable, Hashable, Sendable { emailHash = try container.decode(String.self, forKey: .emailHash) } - - - } - diff --git a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/VerifiedAccount.swift b/Sources/GravatarOpenAPIClient/Models/VerifiedAccount.swift similarity index 92% rename from openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/VerifiedAccount.swift rename to Sources/GravatarOpenAPIClient/Models/VerifiedAccount.swift index 4fcf74de..42758910 100644 --- a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Models/VerifiedAccount.swift +++ b/Sources/GravatarOpenAPIClient/Models/VerifiedAccount.swift @@ -1,16 +1,8 @@ -// -// VerifiedAccount.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech -// - import Foundation /// A verified account on a user's profile. /// public struct VerifiedAccount: Codable, Hashable, Sendable { - /// The type of the service. public private(set) var serviceType: String /// The name of the service. @@ -40,10 +32,7 @@ public struct VerifiedAccount: Codable, Hashable, Sendable { case isHidden = "is_hidden" } - - - - internal enum InternalCodingKeys: String, CodingKey, CaseIterable { + enum InternalCodingKeys: String, CodingKey, CaseIterable { case serviceType = "service_type" case serviceLabel = "service_label" case serviceIcon = "service_icon" @@ -51,9 +40,6 @@ public struct VerifiedAccount: Codable, Hashable, Sendable { case isHidden = "is_hidden" } - - - // Encodable protocol methods public func encode(to encoder: Encoder) throws { @@ -65,7 +51,6 @@ public struct VerifiedAccount: Codable, Hashable, Sendable { try container.encode(isHidden, forKey: .isHidden) } - // Decodable protocol methods public init(from decoder: Decoder) throws { @@ -77,8 +62,4 @@ public struct VerifiedAccount: Codable, Hashable, Sendable { url = try container.decode(String.self, forKey: .url) isHidden = try container.decode(Bool.self, forKey: .isHidden) } - - - } - diff --git a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/OpenISO8601DateFormatter.swift b/Sources/GravatarOpenAPIClient/OpenISO8601DateFormatter.swift similarity index 93% rename from openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/OpenISO8601DateFormatter.swift rename to Sources/GravatarOpenAPIClient/OpenISO8601DateFormatter.swift index cc328880..865b317c 100644 --- a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/OpenISO8601DateFormatter.swift +++ b/Sources/GravatarOpenAPIClient/OpenISO8601DateFormatter.swift @@ -1,10 +1,3 @@ -// -// OpenISO8601DateFormatter.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech -// - import Foundation // https://stackoverflow.com/a/50281094/976628 diff --git a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/SynchronizedDictionary.swift b/Sources/GravatarOpenAPIClient/SynchronizedDictionary.swift similarity index 76% rename from openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/SynchronizedDictionary.swift rename to Sources/GravatarOpenAPIClient/SynchronizedDictionary.swift index acf7ff40..b47892bd 100644 --- a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/SynchronizedDictionary.swift +++ b/Sources/GravatarOpenAPIClient/SynchronizedDictionary.swift @@ -1,13 +1,6 @@ -// SynchronizedDictionary.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech -// - import Foundation -internal struct SynchronizedDictionary { - +struct SynchronizedDictionary { private var dictionary = [K: V]() private let queue = DispatchQueue( label: "SynchronizedDictionary", @@ -17,7 +10,7 @@ internal struct SynchronizedDictionary { target: nil ) - internal subscript(key: K) -> V? { + subscript(key: K) -> V? { get { var value: V? diff --git a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/URLSessionImplementations.swift b/Sources/GravatarOpenAPIClient/URLSessionImplementations.swift similarity index 87% rename from openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/URLSessionImplementations.swift rename to Sources/GravatarOpenAPIClient/URLSessionImplementations.swift index 917eb573..2214597b 100644 --- a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/URLSessionImplementations.swift +++ b/Sources/GravatarOpenAPIClient/URLSessionImplementations.swift @@ -1,9 +1,3 @@ -// URLSessionImplementations.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech -// - import Foundation #if !os(macOS) import MobileCoreServices @@ -20,15 +14,18 @@ extension URLSession: URLSessionProtocol {} class URLSessionRequestBuilderFactory: RequestBuilderFactory { func getNonDecodableBuilder() -> RequestBuilder.Type { - return URLSessionRequestBuilder.self + URLSessionRequestBuilder.self } func getBuilder() -> RequestBuilder.Type { - return URLSessionDecodableRequestBuilder.self + URLSessionDecodableRequestBuilder.self } } -public typealias GravatarOpenAPIClientAPIChallengeHandler = ((URLSession, URLSessionTask, URLAuthenticationChallenge) -> (URLSession.AuthChallengeDisposition, URLCredential?)) +public typealias GravatarOpenAPIClientAPIChallengeHandler = (URLSession, URLSessionTask, URLAuthenticationChallenge) -> ( + URLSession.AuthChallengeDisposition, + URLCredential? +) // Store the URLSession's delegate to retain its reference private let sessionDelegate = SessionDelegate() @@ -43,13 +40,12 @@ private var challengeHandlerStore = SynchronizedDictionary() open class URLSessionRequestBuilder: RequestBuilder { - /** May be assigned if you want to control the authentication challenges. */ public var taskDidReceiveChallenge: GravatarOpenAPIClientAPIChallengeHandler? - required public init(method: String, URLString: String, parameters: [String: Any]?, headers: [String: String] = [:], requiresAuthentication: Bool) { + public required init(method: String, URLString: String, parameters: [String: Any]?, headers: [String: String] = [:], requiresAuthentication: Bool) { super.init(method: method, URLString: URLString, parameters: parameters, headers: headers, requiresAuthentication: requiresAuthentication) } @@ -58,7 +54,7 @@ open class URLSessionRequestBuilder: RequestBuilder { configuration. */ open func createURLSession() -> URLSessionProtocol { - return defaultURLSession + defaultURLSession } /** @@ -69,15 +65,19 @@ open class URLSessionRequestBuilder: RequestBuilder { the file extension). Return the desired Content-Type otherwise. */ open func contentTypeForFormPart(fileURL: URL) -> String? { - return nil + nil } /** May be overridden by a subclass if you want to control the URLRequest configuration (e.g. to override the cache policy). */ - open func createURLRequest(urlSession: URLSessionProtocol, method: HTTPMethod, encoding: ParameterEncoding, headers: [String: String]) throws -> URLRequest { - + open func createURLRequest( + urlSession: URLSessionProtocol, + method: HTTPMethod, + encoding: ParameterEncoding, + headers: [String: String] + ) throws -> URLRequest { guard let url = URL(string: URLString) else { throw DownloadException.requestMissingURL } @@ -86,7 +86,7 @@ open class URLSessionRequestBuilder: RequestBuilder { originalRequest.httpMethod = method.rawValue - buildHeaders().forEach { key, value in + for (key, value) in buildHeaders() { originalRequest.setValue(value, forHTTPHeaderField: key) } @@ -96,7 +96,10 @@ open class URLSessionRequestBuilder: RequestBuilder { } @discardableResult - override open func execute(_ apiResponseQueue: DispatchQueue = GravatarOpenAPIClientAPI.apiResponseQueue, _ completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) -> RequestTask { + override open func execute( + _ apiResponseQueue: DispatchQueue = GravatarOpenAPIClientAPI.apiResponseQueue, + _ completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void + ) -> RequestTask { let urlSession = createURLSession() guard let xMethod = HTTPMethod(rawValue: method) else { @@ -118,7 +121,7 @@ open class URLSessionRequestBuilder: RequestBuilder { encoding = FormDataEncoding(contentTypeForFormPart: contentTypeForFormPart(fileURL:)) } else if contentType.hasPrefix("application/x-www-form-urlencoded") { encoding = FormURLEncoding() - } else if contentType.hasPrefix("application/octet-stream"){ + } else if contentType.hasPrefix("application/octet-stream") { encoding = OctetStreamEncoding() } else { fatalError("Unsupported Media Type - \(contentType)") @@ -129,12 +132,12 @@ open class URLSessionRequestBuilder: RequestBuilder { let request = try createURLRequest(urlSession: urlSession, method: xMethod, encoding: encoding, headers: headers) var taskIdentifier: Int? - let cleanupRequest = { - if let taskIdentifier = taskIdentifier { - challengeHandlerStore[taskIdentifier] = nil - credentialStore[taskIdentifier] = nil - } - } + let cleanupRequest = { + if let taskIdentifier { + challengeHandlerStore[taskIdentifier] = nil + credentialStore[taskIdentifier] = nil + } + } let dataTask = urlSession.dataTask(with: request) { data, response, error in apiResponseQueue.async { @@ -161,9 +164,14 @@ open class URLSessionRequestBuilder: RequestBuilder { return requestTask } - fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, response: URLResponse?, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { - - if let error = error { + fileprivate func processRequestResponse( + urlRequest: URLRequest, + data: Data?, + response: URLResponse?, + error: Error?, + completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void + ) { + if let error { completion(.failure(ErrorResponse.error(-1, data, response, error))) return } @@ -186,7 +194,6 @@ open class URLSessionRequestBuilder: RequestBuilder { default: fatalError("Unsupported Response Body Type - \(String(describing: T.self))") } - } open func buildHeaders() -> [String: String] { @@ -201,8 +208,7 @@ open class URLSessionRequestBuilder: RequestBuilder { } fileprivate func getFileName(fromContentDisposition contentDisposition: String?) -> String? { - - guard let contentDisposition = contentDisposition else { + guard let contentDisposition else { return nil } @@ -211,7 +217,6 @@ open class URLSessionRequestBuilder: RequestBuilder { var filename: String? for contentItem in items { - let filenameKey = "filename=" guard let range = contentItem.range(of: filenameKey) else { continue @@ -225,11 +230,9 @@ open class URLSessionRequestBuilder: RequestBuilder { } return filename - } fileprivate func getPath(from url: URL) throws -> String { - guard var path = URLComponents(url: url, resolvingAgainstBaseURL: true)?.path else { throw DownloadException.requestMissingPath } @@ -239,24 +242,26 @@ open class URLSessionRequestBuilder: RequestBuilder { } return path - } fileprivate func getURL(from urlRequest: URLRequest) throws -> URL { - guard let url = urlRequest.url else { throw DownloadException.requestMissingURL } return url } - } open class URLSessionDecodableRequestBuilder: URLSessionRequestBuilder { - override fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, response: URLResponse?, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { - - if let error = error { + override fileprivate func processRequestResponse( + urlRequest: URLRequest, + data: Data?, + response: URLResponse?, + error: Error?, + completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void + ) { + if let error { completion(.failure(ErrorResponse.error(-1, data, response, error))) return } @@ -280,12 +285,11 @@ open class URLSessionDecodableRequestBuilder: URLSessionRequestBui case is URL.Type: do { - guard error == nil else { throw DownloadException.responseFailed } - guard let data = data else { + guard let data else { throw DownloadException.responseDataMissing } @@ -337,9 +341,9 @@ open class URLSessionDecodableRequestBuilder: URLSessionRequestBui let decodeResult = CodableHelper.decode(T.self, from: unwrappedData) switch decodeResult { - case let .success(decodableObj): + case .success(let decodableObj): completion(.success(Response(response: httpResponse, body: decodableObj, bodyData: unwrappedData))) - case let .failure(error): + case .failure(let error): completion(.failure(ErrorResponse.error(httpResponse.statusCode, unwrappedData, response, error))) } } @@ -347,8 +351,12 @@ open class URLSessionDecodableRequestBuilder: URLSessionRequestBui } private class SessionDelegate: NSObject, URLSessionTaskDelegate { - func urlSession(_ session: URLSession, task: URLSessionTask, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { - + func urlSession( + _ session: URLSession, + task: URLSessionTask, + didReceive challenge: URLAuthenticationChallenge, + completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void + ) { var disposition: URLSession.AuthChallengeDisposition = .performDefaultHandling var credential: URLCredential? @@ -359,7 +367,8 @@ private class SessionDelegate: NSObject, URLSessionTaskDelegate { if challenge.previousFailureCount > 0 { disposition = .rejectProtectionSpace } else { - credential = credentialStore[task.taskIdentifier] ?? session.configuration.urlCredentialStorage?.defaultCredential(for: challenge.protectionSpace) + credential = credentialStore[task.taskIdentifier] ?? session.configuration.urlCredentialStorage? + .defaultCredential(for: challenge.protectionSpace) if credential != nil { disposition = .useCredential @@ -389,10 +398,9 @@ public protocol ParameterEncoding { private class URLEncoding: ParameterEncoding { func encode(_ urlRequest: URLRequest, with parameters: [String: Any]?) throws -> URLRequest { - var urlRequest = urlRequest - guard let parameters = parameters else { return urlRequest } + guard let parameters else { return urlRequest } guard let url = urlRequest.url else { throw DownloadException.requestMissingURL @@ -408,7 +416,6 @@ private class URLEncoding: ParameterEncoding { } private class FormDataEncoding: ParameterEncoding { - let contentTypeForFormPart: (_ fileURL: URL) -> String? init(contentTypeForFormPart: @escaping (_ fileURL: URL) -> String?) { @@ -416,10 +423,9 @@ private class FormDataEncoding: ParameterEncoding { } func encode(_ urlRequest: URLRequest, with parameters: [String: Any]?) throws -> URLRequest { - var urlRequest = urlRequest - guard let parameters = parameters, !parameters.isEmpty else { + guard let parameters, !parameters.isEmpty else { return urlRequest } @@ -428,7 +434,7 @@ private class FormDataEncoding: ParameterEncoding { urlRequest.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type") for (key, value) in parameters { - for value in (value as? Array ?? [value]) { + for value in value as? Array ?? [value] { switch value { case let fileURL as URL: @@ -497,7 +503,6 @@ private class FormDataEncoding: ParameterEncoding { } private func configureFileUploadRequest(urlRequest: URLRequest, boundary: String, name: String, fileURL: URL) throws -> URLRequest { - var urlRequest = urlRequest var body = urlRequest.httpBody.orEmpty @@ -532,7 +537,6 @@ private class FormDataEncoding: ParameterEncoding { } private func configureDataUploadRequest(urlRequest: URLRequest, boundary: String, name: String, data: Data) -> URLRequest { - var urlRequest = urlRequest var body = urlRequest.httpBody.orEmpty @@ -557,7 +561,6 @@ private class FormDataEncoding: ParameterEncoding { urlRequest.httpBody = body return urlRequest - } func mimeType(for url: URL) -> String { @@ -569,23 +572,22 @@ private class FormDataEncoding: ParameterEncoding { return utType.preferredMIMEType ?? "application/octet-stream" } #else - return "application/octet-stream" + return "application/octet-stream" #endif } else { if let uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, pathExtension as NSString, nil)?.takeRetainedValue(), - let mimetype = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType)?.takeRetainedValue() { + let mimetype = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType)?.takeRetainedValue() + { return mimetype as String } return "application/octet-stream" } return "application/octet-stream" } - } private class FormURLEncoding: ParameterEncoding { func encode(_ urlRequest: URLRequest, with parameters: [String: Any]?) throws -> URLRequest { - var urlRequest = urlRequest var requestBodyComponents = URLComponents() @@ -603,7 +605,6 @@ private class FormURLEncoding: ParameterEncoding { private class OctetStreamEncoding: ParameterEncoding { func encode(_ urlRequest: URLRequest, with parameters: [String: Any]?) throws -> URLRequest { - var urlRequest = urlRequest guard let body = parameters?["body"] else { return urlRequest } @@ -625,22 +626,23 @@ private class OctetStreamEncoding: ParameterEncoding { } } -private extension Data { +extension Data { /// Append string to Data /// - /// Rather than littering my code with calls to `dataUsingEncoding` to convert strings to Data, and then add that data to the Data, this wraps it in a nice convenient little extension to Data. This converts using UTF-8. + /// Rather than littering my code with calls to `dataUsingEncoding` to convert strings to Data, and then add that data to the Data, this wraps it in a nice + /// convenient little extension to Data. This converts using UTF-8. /// /// - parameter string: The string to be added to the `Data`. - mutating func append(_ string: String) { + fileprivate mutating func append(_ string: String) { if let data = string.data(using: .utf8) { append(data) } } } -private extension Optional where Wrapped == Data { - var orEmpty: Data { +extension Data? { + fileprivate var orEmpty: Data { self ?? Data() } } diff --git a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Validation.swift b/Sources/GravatarOpenAPIClient/Validation.swift similarity index 97% rename from openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Validation.swift rename to Sources/GravatarOpenAPIClient/Validation.swift index b520bd7e..5ae7e28c 100644 --- a/openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/Validation.swift +++ b/Sources/GravatarOpenAPIClient/Validation.swift @@ -1,9 +1,3 @@ -// Validation.swift -// -// Generated by openapi-generator -// https://openapi-generator.tech -// - import Foundation public struct StringRule { @@ -32,7 +26,7 @@ public struct ValidationError: Error { public fileprivate(set) var kinds: Set } -public struct Validator { +public enum Validator { /// Validate a string against a rule. /// - Parameter string: The String you wish to validate. /// - Parameter rule: The StringRule you wish to use for validation. diff --git a/openapi/GravatarOpenAPIClient/.openapi-generator-ignore b/openapi/GravatarOpenAPIClient/.openapi-generator-ignore index 5f696832..146d6f12 100644 --- a/openapi/GravatarOpenAPIClient/.openapi-generator-ignore +++ b/openapi/GravatarOpenAPIClient/.openapi-generator-ignore @@ -22,6 +22,7 @@ # Then explicitly reverse the ignore rule for a single file: #!docs/README.md +.gitignore .swiftformat Cartfile git_push.sh diff --git a/openapi/GravatarOpenAPIClient/.openapi-generator/FILES b/openapi/GravatarOpenAPIClient/.openapi-generator/FILES index f2365749..cbf23778 100644 --- a/openapi/GravatarOpenAPIClient/.openapi-generator/FILES +++ b/openapi/GravatarOpenAPIClient/.openapi-generator/FILES @@ -1,4 +1,3 @@ -.gitignore GravatarOpenAPIClient.podspec Package.swift README.md diff --git a/openapi/GravatarOpenAPIClient/Package.resolved b/openapi/GravatarOpenAPIClient/Package.resolved new file mode 100644 index 00000000..ad0d0423 --- /dev/null +++ b/openapi/GravatarOpenAPIClient/Package.resolved @@ -0,0 +1,16 @@ +{ + "object": { + "pins": [ + { + "package": "AnyCodable", + "repositoryURL": "https://github.com/Flight-School/AnyCodable", + "state": { + "branch": null, + "revision": "862808b2070cd908cb04f9aafe7de83d35f81b05", + "version": "0.6.7" + } + } + ] + }, + "version": 1 +} From 84eeb1ff9e93d879743c5fab0a58ee4e9fd19ca6 Mon Sep 17 00:00:00 2001 From: Andrew Montgomery Date: Wed, 9 Oct 2024 17:55:12 -0500 Subject: [PATCH 12/20] Stop tracking some files --- .gitignore | 1 - openapi/GravatarOpenAPIClient/.gitignore | 100 ------------------ .../GravatarOpenAPIClient/Package.resolved | 16 --- 3 files changed, 117 deletions(-) delete mode 100644 openapi/GravatarOpenAPIClient/.gitignore delete mode 100644 openapi/GravatarOpenAPIClient/Package.resolved diff --git a/.gitignore b/.gitignore index 99d78867..2171bfbd 100644 --- a/.gitignore +++ b/.gitignore @@ -47,7 +47,6 @@ fastlane/test_output # OpenAPI openapi/GravatarOpenAPIClient/ -!openapi/GravatarOpenAPIClient/.gitignore !openapi/GravatarOpenAPIClient/.openapi-generator/ !openapi/GravatarOpenAPIClient/.openapi-generator-ignore !openapi/GravatarOpenAPIClient/docs/ diff --git a/openapi/GravatarOpenAPIClient/.gitignore b/openapi/GravatarOpenAPIClient/.gitignore deleted file mode 100644 index 316a8450..00000000 --- a/openapi/GravatarOpenAPIClient/.gitignore +++ /dev/null @@ -1,100 +0,0 @@ -# Created by https://www.toptal.com/developers/gitignore/api/xcode,swift -# Edit at https://www.toptal.com/developers/gitignore?templates=xcode,swift - -### Swift ### -# Xcode -# -# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore - -## User settings -xcuserdata/ - -## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) -*.xcscmblueprint -*.xccheckout - -## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) -build/ -DerivedData/ -*.moved-aside -*.pbxuser -!default.pbxuser -*.mode1v3 -!default.mode1v3 -*.mode2v3 -!default.mode2v3 -*.perspectivev3 -!default.perspectivev3 - -## Obj-C/Swift specific -*.hmap - -## App packaging -*.ipa -*.dSYM.zip -*.dSYM - -## 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/ -# Package.pins -# Package.resolved -# *.xcodeproj -# Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata -# hence it is not needed unless you have added a package configuration file to your project -# .swiftpm - -.build/ - -# 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/ -# Add this line if you want to avoid checking in source code from the Xcode workspace -# *.xcworkspace - -# Carthage -# Add this line if you want to avoid checking in source code from Carthage dependencies. -# Carthage/Checkouts - -Carthage/Build/ - -# Accio dependency management -Dependencies/ -.accio/ - -# 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://docs.fastlane.tools/best-practices/source-control/#source-control - -fastlane/report.xml -fastlane/Preview.html -fastlane/screenshots/**/*.png -fastlane/test_output - -# Code Injection -# After new code Injection tools there's a generated folder /iOSInjectionProject -# https://github.com/johnno1962/injectionforxcode - -iOSInjectionProject/ - -### Xcode ### - -## Xcode 8 and earlier - -### Xcode Patch ### -*.xcodeproj/* -!*.xcodeproj/project.pbxproj -!*.xcodeproj/xcshareddata/ -!*.xcworkspace/contents.xcworkspacedata -/*.gcno -**/xcshareddata/WorkspaceSettings.xcsettings - -# End of https://www.toptal.com/developers/gitignore/api/xcode,swift diff --git a/openapi/GravatarOpenAPIClient/Package.resolved b/openapi/GravatarOpenAPIClient/Package.resolved deleted file mode 100644 index ad0d0423..00000000 --- a/openapi/GravatarOpenAPIClient/Package.resolved +++ /dev/null @@ -1,16 +0,0 @@ -{ - "object": { - "pins": [ - { - "package": "AnyCodable", - "repositoryURL": "https://github.com/Flight-School/AnyCodable", - "state": { - "branch": null, - "revision": "862808b2070cd908cb04f9aafe7de83d35f81b05", - "version": "0.6.7" - } - } - ] - }, - "version": 1 -} From 01c459fc4c89a1e6053457162c029c5fcfed0b5e Mon Sep 17 00:00:00 2001 From: Andrew Montgomery Date: Wed, 9 Oct 2024 20:18:00 -0500 Subject: [PATCH 13/20] Removes unnecessary `install-and-generate` Makefile task --- Makefile | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Makefile b/Makefile index 3ecb77b8..0e400383 100644 --- a/Makefile +++ b/Makefile @@ -110,10 +110,6 @@ update-example-snapshots: cd ./Sources/GravatarUI/GravatarUI.docc/Resources/ProfileExamples && \ for filePath in *; do name=$${filePath%.*}; mv $$filePath $${name//-dark/~dark}@2x$${filePath#$$name}; done -install-and-generate: $(OPENAPI_GENERATOR_CLONE_DIR) # Clones and setup the openapi-generator. - "$(OPENAPI_GENERATOR_CLONE_DIR)"/run-in-docker.sh mvn package - make generate - generate: $(OPENAPI_GENERATED_DIR) # Generates the open-api model rm -rf "$(OPENAPI_GENERATED_DIR)/*" && \ docker run --rm \ @@ -129,8 +125,6 @@ generate: $(OPENAPI_GENERATED_DIR) # Generates the open-api model make swiftformat && \ echo "DONE! 🎉" - - generate-strings: bundle-install bundle exec fastlane generate_strings From 9c5b7e4d0f29fe28a8123fa48af1d5353d8466d2 Mon Sep 17 00:00:00 2001 From: Andrew Montgomery Date: Wed, 9 Oct 2024 20:23:51 -0500 Subject: [PATCH 14/20] Update GravatarOpenAPIClient.podspec with path to module --- GravatarOpenAPIClient.podspec | 2 +- Makefile | 2 +- openapi/GravatarOpenAPIClient/GravatarOpenAPIClient.podspec | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/GravatarOpenAPIClient.podspec b/GravatarOpenAPIClient.podspec index 15ba2b8a..3dd802f1 100644 --- a/GravatarOpenAPIClient.podspec +++ b/GravatarOpenAPIClient.podspec @@ -19,5 +19,5 @@ Pod::Spec.new do |s| s.documentation_url = 'https://automattic.github.io/Gravatar-SDK-iOS/gravatar' - s.source_files = 'openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/**/*.swift' + s.source_files = 'Sources/GravatarOpenAPIClient/**/*.swift' end diff --git a/Makefile b/Makefile index 0e400383..8774a921 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ OPENAPI_PROJECT_NAME ?= GravatarOpenAPIClient OPENAPI_DIR ?= $(CURRENT_MAKEFILE_DIR)/$(OPENAPI_REL_DIR) OPENAPI_REL_DIR ?= openapi OPENAPI_GENERATED_DIR ?= $(CURRENT_MAKEFILE_DIR)/openapi/$(OPENAPI_PROJECT_NAME) -OPENAPI_CLIENT_PROPERTIES ?= projectName=$(OPENAPI_PROJECT_NAME),useSPMFileStructure=true,packageRootPath="$(OPENAPI_REL_DIR)/$(OPENAPI_PROJECT_NAME)" +OPENAPI_CLIENT_PROPERTIES ?= projectName=$(OPENAPI_PROJECT_NAME),useSPMFileStructure=true OPENAPI_YAML_PATH ?= $(CURRENT_MAKEFILE_DIR)/openapi/spec.yaml MODEL_TEMPLATE_PATH ?= $(CURRENT_MAKEFILE_DIR)/openapi diff --git a/openapi/GravatarOpenAPIClient/GravatarOpenAPIClient.podspec b/openapi/GravatarOpenAPIClient/GravatarOpenAPIClient.podspec index 15ba2b8a..3dd802f1 100644 --- a/openapi/GravatarOpenAPIClient/GravatarOpenAPIClient.podspec +++ b/openapi/GravatarOpenAPIClient/GravatarOpenAPIClient.podspec @@ -19,5 +19,5 @@ Pod::Spec.new do |s| s.documentation_url = 'https://automattic.github.io/Gravatar-SDK-iOS/gravatar' - s.source_files = 'openapi/GravatarOpenAPIClient/Sources/GravatarOpenAPIClient/**/*.swift' + s.source_files = 'Sources/GravatarOpenAPIClient/**/*.swift' end From 0b6d4dc0e726b6baa6a63a8cba5c27727ca98499 Mon Sep 17 00:00:00 2001 From: Andrew Montgomery Date: Wed, 9 Oct 2024 20:44:42 -0500 Subject: [PATCH 15/20] Update the validate-pods.sh script to check the new podspec --- .buildkite/commands/validate-pods.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.buildkite/commands/validate-pods.sh b/.buildkite/commands/validate-pods.sh index a3228ecb..70536f10 100644 --- a/.buildkite/commands/validate-pods.sh +++ b/.buildkite/commands/validate-pods.sh @@ -5,3 +5,6 @@ validate_podspec --allow-warnings Gravatar.podspec echo "--- :cocoapods: Validate GravatarUI.podspec" validate_podspec --allow-warnings GravatarUI.podspec + +echo "--- :cocoapods: Validate GravatarOpenAPIClient.podspec" +validate_podspec --allow-warnings GravatarOpenAPIClient.podspec From c6a8e9690e13922b50bf96bd9a67c91941f11ce1 Mon Sep 17 00:00:00 2001 From: Andrew Montgomery Date: Wed, 9 Oct 2024 20:45:48 -0500 Subject: [PATCH 16/20] Update pipeline to publish the new podspec --- .buildkite/pipeline.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml index ffd1b4cb..489ec0e9 100644 --- a/.buildkite/pipeline.yml +++ b/.buildkite/pipeline.yml @@ -44,6 +44,7 @@ steps: command: | .buildkite/commands/publish-pod.sh "Gravatar.podspec" .buildkite/commands/publish-pod.sh "GravatarUI.podspec" + .buildkite/commands/publish-pod.sh "GravatarOpenAPIClient.podspec" plugins: [$CI_TOOLKIT] depends_on: - "test" From d28429db4fc267f3907120b4c380251dbf556629 Mon Sep 17 00:00:00 2001 From: Andrew Montgomery Date: Wed, 9 Oct 2024 20:54:32 -0500 Subject: [PATCH 17/20] Update Demo project Package.resolved --- .../xcshareddata/swiftpm/Package.resolved | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/Demo/Gravatar-Demo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Demo/Gravatar-Demo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index a935fc1b..17c22476 100644 --- a/Demo/Gravatar-Demo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Demo/Gravatar-Demo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,15 +1,6 @@ { - "originHash" : "2636afb60bdeb27536d533a4fd95ce1b1476cf7e53d8bc0bcaa63387fbefb579", + "originHash" : "bf24fbca0585c9e7707869442e833d48e8fbe49f5e904fe58370244d9f54521e", "pins" : [ - { - "identity" : "anycodable", - "kind" : "remoteSourceControl", - "location" : "https://github.com/Flight-School/AnyCodable", - "state" : { - "revision" : "862808b2070cd908cb04f9aafe7de83d35f81b05", - "version" : "0.6.7" - } - }, { "identity" : "swift-snapshot-testing", "kind" : "remoteSourceControl", From e1e7191e65253ef5eda6550a677c17360fc4b404 Mon Sep 17 00:00:00 2001 From: Andrew Montgomery Date: Thu, 10 Oct 2024 12:41:17 -0500 Subject: [PATCH 18/20] Regenerate SetEmailAvatarRequest --- .../Models/SetEmailAvatarRequest.swift | 20 +++---------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/Sources/GravatarOpenAPIClient/Models/SetEmailAvatarRequest.swift b/Sources/GravatarOpenAPIClient/Models/SetEmailAvatarRequest.swift index 2e6741a4..54ad2f69 100644 --- a/Sources/GravatarOpenAPIClient/Models/SetEmailAvatarRequest.swift +++ b/Sources/GravatarOpenAPIClient/Models/SetEmailAvatarRequest.swift @@ -4,32 +4,18 @@ public struct SetEmailAvatarRequest: Codable, Hashable, Sendable { /// The email SHA256 hash to set the avatar for. public private(set) var emailHash: String - @available(*, deprecated, message: "init will become internal on the next release") - public init(emailHash: String) { + init(emailHash: String) { self.emailHash = emailHash } - @available(*, deprecated, message: "CodingKeys will become internal on the next release.") - public enum CodingKeys: String, CodingKey, CaseIterable { - case emailHash = "email_hash" - } - - enum InternalCodingKeys: String, CodingKey, CaseIterable { + enum CodingKeys: String, CodingKey, CaseIterable { case emailHash = "email_hash" } // Encodable protocol methods public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: InternalCodingKeys.self) + var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(emailHash, forKey: .emailHash) } - - // Decodable protocol methods - - public init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: InternalCodingKeys.self) - - emailHash = try container.decode(String.self, forKey: .emailHash) - } } From 93446f79270de531f896fff9cce0d31f52c4b48a Mon Sep 17 00:00:00 2001 From: Andrew Montgomery Date: Thu, 10 Oct 2024 12:46:05 -0500 Subject: [PATCH 19/20] Fix typo in `generate` Makefile command --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 8774a921..e53a4000 100644 --- a/Makefile +++ b/Makefile @@ -111,7 +111,7 @@ update-example-snapshots: for filePath in *; do name=$${filePath%.*}; mv $$filePath $${name//-dark/~dark}@2x$${filePath#$$name}; done generate: $(OPENAPI_GENERATED_DIR) # Generates the open-api model - rm -rf "$(OPENAPI_GENERATED_DIR)/*" && \ + rm -rf "$(OPENAPI_GENERATED_DIR)"/* && \ docker run --rm \ -v $(OPENAPI_DIR):/local openapitools/openapi-generator-cli:"$(OPENAPI_GENERATOR_GIT_TAG)" generate \ -i /local/openapi.yaml \ From b3b9f4c747a980c28999fa9ea950c555a6ce8c63 Mon Sep 17 00:00:00 2001 From: Andrew Montgomery Date: Thu, 10 Oct 2024 12:46:53 -0500 Subject: [PATCH 20/20] Update .openapi-generator-ignore to generate only `Models` dir --- Sources/GravatarOpenAPIClient/APIHelper.swift | 111 --- Sources/GravatarOpenAPIClient/APIs.swift | 65 -- .../GravatarOpenAPIClient/CodableHelper.swift | 44 -- .../GravatarOpenAPIClient/Configuration.swift | 11 - .../GravatarOpenAPIClient/Extensions.swift | 222 ------ .../JSONDataEncoding.swift | 47 -- .../JSONEncodingHelper.swift | 36 - Sources/GravatarOpenAPIClient/Models.swift | 123 ---- .../OpenISO8601DateFormatter.swift | 49 -- .../SynchronizedDictionary.swift | 29 - .../URLSessionImplementations.swift | 650 ------------------ .../GravatarOpenAPIClient/Validation.swift | 120 ---- .../.openapi-generator-ignore | 3 +- .../.openapi-generator/FILES | 12 - 14 files changed, 2 insertions(+), 1520 deletions(-) delete mode 100644 Sources/GravatarOpenAPIClient/APIHelper.swift delete mode 100644 Sources/GravatarOpenAPIClient/APIs.swift delete mode 100644 Sources/GravatarOpenAPIClient/CodableHelper.swift delete mode 100644 Sources/GravatarOpenAPIClient/Configuration.swift delete mode 100644 Sources/GravatarOpenAPIClient/Extensions.swift delete mode 100644 Sources/GravatarOpenAPIClient/JSONDataEncoding.swift delete mode 100644 Sources/GravatarOpenAPIClient/JSONEncodingHelper.swift delete mode 100644 Sources/GravatarOpenAPIClient/Models.swift delete mode 100644 Sources/GravatarOpenAPIClient/OpenISO8601DateFormatter.swift delete mode 100644 Sources/GravatarOpenAPIClient/SynchronizedDictionary.swift delete mode 100644 Sources/GravatarOpenAPIClient/URLSessionImplementations.swift delete mode 100644 Sources/GravatarOpenAPIClient/Validation.swift diff --git a/Sources/GravatarOpenAPIClient/APIHelper.swift b/Sources/GravatarOpenAPIClient/APIHelper.swift deleted file mode 100644 index afd13cd6..00000000 --- a/Sources/GravatarOpenAPIClient/APIHelper.swift +++ /dev/null @@ -1,111 +0,0 @@ -import Foundation - -public enum APIHelper { - public 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 - } - - public static func rejectNilHeaders(_ source: [String: Any?]) -> [String: String] { - source.reduce(into: [String: String]()) { result, item in - if let collection = item.value as? [Any?] { - result[item.key] = collection - .compactMap { value in convertAnyToString(value) } - .joined(separator: ",") - } else if let value: Any = item.value { - result[item.key] = convertAnyToString(value) - } - } - } - - public static func convertBoolToString(_ source: [String: Any]?) -> [String: Any]? { - guard let 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 - } - } - } - - public static func convertAnyToString(_ value: Any?) -> String? { - guard let value else { return nil } - if let value = value as? any RawRepresentable { - return "\(value.rawValue)" - } else { - return "\(value)" - } - } - - public static func mapValueToPathItem(_ source: Any) -> Any { - if let collection = source as? [Any?] { - return collection - .compactMap { value in convertAnyToString(value) } - .joined(separator: ",") - } - return source - } - - /// maps all values from source to query parameters - /// - /// explode attribute is respected: collection values might be either joined or split up into separate key value pairs - public static func mapValuesToQueryItems(_ source: [String: (wrappedValue: Any?, isExplode: Bool)]) -> [URLQueryItem]? { - let destination = source.filter { $0.value.wrappedValue != nil }.reduce(into: [URLQueryItem]()) { result, item in - if let collection = item.value.wrappedValue as? [Any?] { - let collectionValues: [String] = collection.compactMap { value in convertAnyToString(value) } - - if !item.value.isExplode { - result.append(URLQueryItem(name: item.key, value: collectionValues.joined(separator: ","))) - } else { - for value in collectionValues { - result.append(URLQueryItem(name: item.key, value: value)) - } - } - - } else if let value = item.value.wrappedValue { - result.append(URLQueryItem(name: item.key, value: convertAnyToString(value))) - } - } - - if destination.isEmpty { - return nil - } - return destination.sorted { $0.name < $1.name } - } - - /// maps all values from source to query parameters - /// - /// collection values are always exploded - public 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 - .compactMap { value in convertAnyToString(value) } - .forEach { value in - result.append(URLQueryItem(name: item.key, value: value)) - } - - } else if let value = item.value { - result.append(URLQueryItem(name: item.key, value: convertAnyToString(value))) - } - } - - if destination.isEmpty { - return nil - } - return destination.sorted { $0.name < $1.name } - } -} diff --git a/Sources/GravatarOpenAPIClient/APIs.swift b/Sources/GravatarOpenAPIClient/APIs.swift deleted file mode 100644 index 5bbb200e..00000000 --- a/Sources/GravatarOpenAPIClient/APIs.swift +++ /dev/null @@ -1,65 +0,0 @@ -import Foundation -#if canImport(FoundationNetworking) -import FoundationNetworking -#endif -open class GravatarOpenAPIClientAPI { - public static var basePath = "https://api.gravatar.com/v3" - public static var customHeaders: [String: String] = [:] - public static var credential: URLCredential? - public static var requestBuilderFactory: RequestBuilderFactory = URLSessionRequestBuilderFactory() - public static var apiResponseQueue: DispatchQueue = .main -} - -open class RequestBuilder { - var credential: URLCredential? - var headers: [String: String] - public let parameters: [String: Any]? - public let method: String - public let URLString: String - public let requestTask: RequestTask = .init() - public let requiresAuthentication: Bool - - /// Optional block to obtain a reference to the request's progress instance when available. - public var onProgressReady: ((Progress) -> Void)? - - public required init(method: String, URLString: String, parameters: [String: Any]?, headers: [String: String] = [:], requiresAuthentication: Bool) { - self.method = method - self.URLString = URLString - self.parameters = parameters - self.headers = headers - self.requiresAuthentication = requiresAuthentication - - addHeaders(GravatarOpenAPIClientAPI.customHeaders) - } - - open func addHeaders(_ aHeaders: [String: String]) { - for (header, value) in aHeaders { - headers[header] = value - } - } - - @discardableResult - open func execute( - _: DispatchQueue = GravatarOpenAPIClientAPI.apiResponseQueue, - _: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void - ) -> RequestTask { - requestTask - } - - public func addHeader(name: String, value: String) -> Self { - if !value.isEmpty { - headers[name] = value - } - return self - } - - open func addCredential() -> Self { - credential = GravatarOpenAPIClientAPI.credential - return self - } -} - -public protocol RequestBuilderFactory { - func getNonDecodableBuilder() -> RequestBuilder.Type - func getBuilder() -> RequestBuilder.Type -} diff --git a/Sources/GravatarOpenAPIClient/CodableHelper.swift b/Sources/GravatarOpenAPIClient/CodableHelper.swift deleted file mode 100644 index e7c23d1d..00000000 --- a/Sources/GravatarOpenAPIClient/CodableHelper.swift +++ /dev/null @@ -1,44 +0,0 @@ -import Foundation - -open 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 - }() - - public static var dateFormatter: DateFormatter { - get { customDateFormatter ?? defaultDateFormatter } - set { customDateFormatter = newValue } - } - - public static var jsonDecoder: JSONDecoder { - get { customJSONDecoder ?? defaultJSONDecoder } - set { customJSONDecoder = newValue } - } - - public static var jsonEncoder: JSONEncoder { - get { customJSONEncoder ?? defaultJSONEncoder } - set { customJSONEncoder = newValue } - } - - open class func decode(_ type: T.Type, from data: Data) -> Swift.Result where T: Decodable { - Swift.Result { try jsonDecoder.decode(type, from: data) } - } - - open class func encode(_ value: some Encodable) -> Swift.Result { - Swift.Result { try jsonEncoder.encode(value) } - } -} diff --git a/Sources/GravatarOpenAPIClient/Configuration.swift b/Sources/GravatarOpenAPIClient/Configuration.swift deleted file mode 100644 index f66f68de..00000000 --- a/Sources/GravatarOpenAPIClient/Configuration.swift +++ /dev/null @@ -1,11 +0,0 @@ -import Foundation -#if canImport(FoundationNetworking) -import FoundationNetworking -#endif - -open class Configuration { - /// Configures the range of HTTP status codes that will result in a successful response - /// - /// If a HTTP status code is outside of this range the response will be interpreted as failed. - public static var successfulStatusCodeRange: Range = 200 ..< 300 -} diff --git a/Sources/GravatarOpenAPIClient/Extensions.swift b/Sources/GravatarOpenAPIClient/Extensions.swift deleted file mode 100644 index bb09d70f..00000000 --- a/Sources/GravatarOpenAPIClient/Extensions.swift +++ /dev/null @@ -1,222 +0,0 @@ -import Foundation -#if canImport(FoundationNetworking) -import FoundationNetworking -#endif -#if canImport(AnyCodable) -import AnyCodable -#endif - -extension Bool: JSONEncodable { - func encodeToJSON() -> Any { self } -} - -extension Float: JSONEncodable { - func encodeToJSON() -> Any { self } -} - -extension Int: JSONEncodable { - func encodeToJSON() -> Any { self } -} - -extension Int32: JSONEncodable { - func encodeToJSON() -> Any { self } -} - -extension Int64: JSONEncodable { - func encodeToJSON() -> Any { self } -} - -extension Double: JSONEncodable { - func encodeToJSON() -> Any { self } -} - -extension Decimal: JSONEncodable { - func encodeToJSON() -> Any { self } -} - -extension String: JSONEncodable { - func encodeToJSON() -> Any { self } -} - -extension URL: JSONEncodable { - func encodeToJSON() -> Any { self } -} - -extension UUID: JSONEncodable { - func encodeToJSON() -> Any { self } -} - -extension RawRepresentable where RawValue: JSONEncodable { - func encodeToJSON() -> Any { self.rawValue } -} - -private func encodeIfPossible(_ object: some Any) -> Any { - if let encodableObject = object as? JSONEncodable { - encodableObject.encodeToJSON() - } else { - object - } -} - -extension Array: JSONEncodable { - func encodeToJSON() -> Any { - self.map(encodeIfPossible) - } -} - -extension Set: JSONEncodable { - func encodeToJSON() -> Any { - Array(self).encodeToJSON() - } -} - -extension Dictionary: JSONEncodable { - func encodeToJSON() -> Any { - var dictionary = [AnyHashable: Any]() - for (key, value) in self { - dictionary[key] = encodeIfPossible(value) - } - return dictionary - } -} - -extension Data: JSONEncodable { - func encodeToJSON() -> Any { - self.base64EncodedString(options: Data.Base64EncodingOptions()) - } -} - -extension Date: JSONEncodable { - func encodeToJSON() -> Any { - CodableHelper.dateFormatter.string(from: self) - } -} - -extension JSONEncodable where Self: Encodable { - func encodeToJSON() -> Any { - guard let data = try? CodableHelper.jsonEncoder.encode(self) else { - fatalError("Could not encode to json: \(self)") - } - return data.encodeToJSON() - } -} - -extension String: CodingKey { - public var stringValue: String { - self - } - - public init?(stringValue: String) { - self.init(stringLiteral: stringValue) - } - - public var intValue: Int? { - nil - } - - public init?(intValue: Int) { - nil - } -} - -extension KeyedEncodingContainerProtocol { - public mutating func encodeArray(_ values: [some Encodable], forKey key: Self.Key) throws { - var arrayContainer = nestedUnkeyedContainer(forKey: key) - try arrayContainer.encode(contentsOf: values) - } - - public mutating func encodeArrayIfPresent(_ values: [some Encodable]?, forKey key: Self.Key) throws { - if let values { - try encodeArray(values, forKey: key) - } - } - - public mutating func encodeMap(_ pairs: [Self.Key: some Encodable]) throws { - for (key, value) in pairs { - try encode(value, forKey: key) - } - } - - public mutating func encodeMapIfPresent(_ pairs: [Self.Key: some Encodable]?) throws { - if let pairs { - try encodeMap(pairs) - } - } - - public mutating func encode(_ value: Decimal, forKey key: Self.Key) throws { - var mutableValue = value - let stringValue = NSDecimalString(&mutableValue, Locale(identifier: "en_US")) - try encode(stringValue, forKey: key) - } - - public mutating func encodeIfPresent(_ value: Decimal?, forKey key: Self.Key) throws { - if let value { - try encode(value, forKey: key) - } - } -} - -extension KeyedDecodingContainerProtocol { - public 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 - } - - public 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 - } - - public 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 - } - - public func decode(_ type: Decimal.Type, forKey key: Self.Key) throws -> Decimal { - let stringValue = try decode(String.self, forKey: key) - guard let decimalValue = Decimal(string: stringValue) else { - let context = DecodingError.Context(codingPath: [key], debugDescription: "The key \(key) couldn't be converted to a Decimal value") - throw DecodingError.typeMismatch(type, context) - } - - return decimalValue - } - - public func decodeIfPresent(_ type: Decimal.Type, forKey key: Self.Key) throws -> Decimal? { - guard let stringValue = try decodeIfPresent(String.self, forKey: key) else { - return nil - } - guard let decimalValue = Decimal(string: stringValue) else { - let context = DecodingError.Context(codingPath: [key], debugDescription: "The key \(key) couldn't be converted to a Decimal value") - throw DecodingError.typeMismatch(type, context) - } - - return decimalValue - } -} - -extension HTTPURLResponse { - var isStatusCodeSuccessful: Bool { - Configuration.successfulStatusCodeRange.contains(statusCode) - } -} diff --git a/Sources/GravatarOpenAPIClient/JSONDataEncoding.swift b/Sources/GravatarOpenAPIClient/JSONDataEncoding.swift deleted file mode 100644 index b0fecb5f..00000000 --- a/Sources/GravatarOpenAPIClient/JSONDataEncoding.swift +++ /dev/null @@ -1,47 +0,0 @@ -import Foundation -#if canImport(FoundationNetworking) -import FoundationNetworking -#endif - -public 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. - public 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 - } - - public static func encodingParameters(jsonData: Data?) -> [String: Any]? { - var returnedParams: [String: Any]? - if let jsonData, !jsonData.isEmpty { - var params: [String: Any] = [:] - params[jsonDataKey] = jsonData - returnedParams = params - } - return returnedParams - } -} diff --git a/Sources/GravatarOpenAPIClient/JSONEncodingHelper.swift b/Sources/GravatarOpenAPIClient/JSONEncodingHelper.swift deleted file mode 100644 index c7cbd646..00000000 --- a/Sources/GravatarOpenAPIClient/JSONEncodingHelper.swift +++ /dev/null @@ -1,36 +0,0 @@ -import Foundation - -open class JSONEncodingHelper { - open class func encodingParameters(forEncodableObject encodableObj: (some Encodable)?) -> [String: Any]? { - var params: [String: Any]? - - // Encode the Encodable object - if let encodableObj { - let encodeResult = CodableHelper.encode(encodableObj) - do { - let data = try encodeResult.get() - params = JSONDataEncoding.encodingParameters(jsonData: data) - } catch { - print(error.localizedDescription) - } - } - - return params - } - - open class func encodingParameters(forEncodableObject encodableObj: Any?) -> [String: Any]? { - var params: [String: Any]? - - if let 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/Sources/GravatarOpenAPIClient/Models.swift b/Sources/GravatarOpenAPIClient/Models.swift deleted file mode 100644 index 00d31cb2..00000000 --- a/Sources/GravatarOpenAPIClient/Models.swift +++ /dev/null @@ -1,123 +0,0 @@ -import Foundation -#if canImport(FoundationNetworking) -import FoundationNetworking -#endif - -protocol JSONEncodable { - func encodeToJSON() -> Any -} - -/// An enum where the last case value can be used as a default catch-all. -protocol CaseIterableDefaultsLast: Decodable & CaseIterable & RawRepresentable - where RawValue: Decodable, AllCases: BidirectionalCollection {} - -extension CaseIterableDefaultsLast { - /// Initializes an enum such that if a known raw value is found, then it is decoded. - /// Otherwise the last case is used. - /// - Parameter decoder: A decoder. - public init(from decoder: Decoder) throws { - if let value = try Self(rawValue: decoder.singleValueContainer().decode(RawValue.self)) { - self = value - } else if let lastValue = Self.allCases.last { - self = lastValue - } else { - throw DecodingError.valueNotFound( - Self.Type.self, - .init(codingPath: decoder.codingPath, debugDescription: "CaseIterableDefaultsLast") - ) - } - } -} - -/// A flexible type that can be encoded (`.encodeNull` or `.encodeValue`) -/// or not encoded (`.encodeNothing`). Intended for request payloads. -public enum NullEncodable: Hashable { - case encodeNothing - case encodeNull - case encodeValue(Wrapped) -} - -extension NullEncodable: Codable where Wrapped: Codable { - public init(from decoder: Decoder) throws { - let container = try decoder.singleValueContainer() - if let value = try? container.decode(Wrapped.self) { - self = .encodeValue(value) - } else if container.decodeNil() { - self = .encodeNull - } else { - self = .encodeNothing - } - } - - public func encode(to encoder: Encoder) throws { - var container = encoder.singleValueContainer() - switch self { - case .encodeNothing: return - case .encodeNull: try container.encodeNil() - case .encodeValue(let wrapped): try container.encode(wrapped) - } - } -} - -public enum ErrorResponse: Error { - case error(Int, Data?, URLResponse?, Error) -} - -public enum DownloadException: Error { - case responseDataMissing - case responseFailed - case requestMissing - case requestMissingPath - case requestMissingURL -} - -public enum DecodableRequestBuilderError: Error { - case emptyDataResponse - case nilHTTPResponse - case unsuccessfulHTTPStatusCode - case jsonDecoding(DecodingError) - case generalError(Error) -} - -open class Response { - public let statusCode: Int - public let header: [String: String] - public let body: T - public let bodyData: Data? - - public init(statusCode: Int, header: [String: String], body: T, bodyData: Data?) { - self.statusCode = statusCode - self.header = header - self.body = body - self.bodyData = bodyData - } - - public convenience init(response: HTTPURLResponse, body: T, bodyData: Data?) { - let rawHeader = response.allHeaderFields - var responseHeader = [String: String]() - for (key, value) in rawHeader { - if let key = key.base as? String, let value = value as? String { - responseHeader[key] = value - } - } - self.init(statusCode: response.statusCode, header: responseHeader, body: body, bodyData: bodyData) - } -} - -public final class RequestTask { - private var lock = NSRecursiveLock() - private var task: URLSessionTask? - - func set(task: URLSessionTask) { - lock.lock() - defer { lock.unlock() } - self.task = task - } - - public func cancel() { - lock.lock() - defer { lock.unlock() } - task?.cancel() - task = nil - } -} diff --git a/Sources/GravatarOpenAPIClient/OpenISO8601DateFormatter.swift b/Sources/GravatarOpenAPIClient/OpenISO8601DateFormatter.swift deleted file mode 100644 index 865b317c..00000000 --- a/Sources/GravatarOpenAPIClient/OpenISO8601DateFormatter.swift +++ /dev/null @@ -1,49 +0,0 @@ -import Foundation - -// https://stackoverflow.com/a/50281094/976628 -public 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 - }() - - static let withoutTime: 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" - 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 public func date(from string: String) -> Date? { - if let result = super.date(from: string) { - return result - } else if let result = OpenISO8601DateFormatter.withoutSeconds.date(from: string) { - return result - } - - return OpenISO8601DateFormatter.withoutTime.date(from: string) - } -} diff --git a/Sources/GravatarOpenAPIClient/SynchronizedDictionary.swift b/Sources/GravatarOpenAPIClient/SynchronizedDictionary.swift deleted file mode 100644 index b47892bd..00000000 --- a/Sources/GravatarOpenAPIClient/SynchronizedDictionary.swift +++ /dev/null @@ -1,29 +0,0 @@ -import Foundation - -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 - ) - - 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/Sources/GravatarOpenAPIClient/URLSessionImplementations.swift b/Sources/GravatarOpenAPIClient/URLSessionImplementations.swift deleted file mode 100644 index 2214597b..00000000 --- a/Sources/GravatarOpenAPIClient/URLSessionImplementations.swift +++ /dev/null @@ -1,650 +0,0 @@ -import Foundation -#if !os(macOS) -import MobileCoreServices -#endif -#if canImport(UniformTypeIdentifiers) -import UniformTypeIdentifiers -#endif - -public protocol URLSessionProtocol { - func dataTask(with request: URLRequest, completionHandler: @escaping @Sendable (Data?, URLResponse?, Error?) -> Void) -> URLSessionDataTask -} - -extension URLSession: URLSessionProtocol {} - -class URLSessionRequestBuilderFactory: RequestBuilderFactory { - func getNonDecodableBuilder() -> RequestBuilder.Type { - URLSessionRequestBuilder.self - } - - func getBuilder() -> RequestBuilder.Type { - URLSessionDecodableRequestBuilder.self - } -} - -public typealias GravatarOpenAPIClientAPIChallengeHandler = (URLSession, URLSessionTask, URLAuthenticationChallenge) -> ( - URLSession.AuthChallengeDisposition, - URLCredential? -) - -// Store the URLSession's delegate to retain its reference -private let sessionDelegate = SessionDelegate() - -// Store the URLSession to retain its reference -private let defaultURLSession = URLSession(configuration: .default, delegate: sessionDelegate, delegateQueue: nil) - -// Store current taskDidReceiveChallenge for every URLSessionTask -private var challengeHandlerStore = SynchronizedDictionary() - -// Store current URLCredential for every URLSessionTask -private var credentialStore = SynchronizedDictionary() - -open class URLSessionRequestBuilder: RequestBuilder { - /** - May be assigned if you want to control the authentication challenges. - */ - public var taskDidReceiveChallenge: GravatarOpenAPIClientAPIChallengeHandler? - - public required init(method: String, URLString: String, parameters: [String: Any]?, headers: [String: String] = [:], requiresAuthentication: Bool) { - super.init(method: method, URLString: URLString, parameters: parameters, headers: headers, requiresAuthentication: requiresAuthentication) - } - - /** - May be overridden by a subclass if you want to control the URLSession - configuration. - */ - open func createURLSession() -> URLSessionProtocol { - defaultURLSession - } - - /** - May be overridden by a subclass if you want to control the Content-Type - that is given to an uploaded form part. - - Return nil to use the default behavior (inferring the Content-Type from - the file extension). Return the desired Content-Type otherwise. - */ - open func contentTypeForFormPart(fileURL: URL) -> String? { - nil - } - - /** - May be overridden by a subclass if you want to control the URLRequest - configuration (e.g. to override the cache policy). - */ - open func createURLRequest( - urlSession: URLSessionProtocol, - method: HTTPMethod, - encoding: ParameterEncoding, - headers: [String: String] - ) throws -> URLRequest { - guard let url = URL(string: URLString) else { - throw DownloadException.requestMissingURL - } - - var originalRequest = URLRequest(url: url) - - originalRequest.httpMethod = method.rawValue - - for (key, value) in buildHeaders() { - originalRequest.setValue(value, forHTTPHeaderField: key) - } - - let modifiedRequest = try encoding.encode(originalRequest, with: parameters) - - return modifiedRequest - } - - @discardableResult - override open func execute( - _ apiResponseQueue: DispatchQueue = GravatarOpenAPIClientAPI.apiResponseQueue, - _ completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void - ) -> RequestTask { - let urlSession = createURLSession() - - guard let xMethod = HTTPMethod(rawValue: method) else { - fatalError("Unsupported Http method - \(method)") - } - - let encoding: ParameterEncoding - - switch xMethod { - case .get, .head: - encoding = URLEncoding() - - case .options, .post, .put, .patch, .delete, .trace, .connect: - let contentType = headers["Content-Type"] ?? "application/json" - - if contentType.hasPrefix("application/json") { - encoding = JSONDataEncoding() - } else if contentType.hasPrefix("multipart/form-data") { - encoding = FormDataEncoding(contentTypeForFormPart: contentTypeForFormPart(fileURL:)) - } else if contentType.hasPrefix("application/x-www-form-urlencoded") { - encoding = FormURLEncoding() - } else if contentType.hasPrefix("application/octet-stream") { - encoding = OctetStreamEncoding() - } else { - fatalError("Unsupported Media Type - \(contentType)") - } - } - - do { - let request = try createURLRequest(urlSession: urlSession, method: xMethod, encoding: encoding, headers: headers) - - var taskIdentifier: Int? - let cleanupRequest = { - if let taskIdentifier { - challengeHandlerStore[taskIdentifier] = nil - credentialStore[taskIdentifier] = nil - } - } - - let dataTask = urlSession.dataTask(with: request) { data, response, error in - apiResponseQueue.async { - self.processRequestResponse(urlRequest: request, data: data, response: response, error: error, completion: completion) - cleanupRequest() - } - } - - onProgressReady?(dataTask.progress) - - taskIdentifier = dataTask.taskIdentifier - challengeHandlerStore[dataTask.taskIdentifier] = taskDidReceiveChallenge - credentialStore[dataTask.taskIdentifier] = credential - - dataTask.resume() - - requestTask.set(task: dataTask) - } catch { - apiResponseQueue.async { - completion(.failure(ErrorResponse.error(415, nil, nil, error))) - } - } - - return requestTask - } - - fileprivate func processRequestResponse( - urlRequest: URLRequest, - data: Data?, - response: URLResponse?, - error: Error?, - completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void - ) { - if let error { - completion(.failure(ErrorResponse.error(-1, data, response, error))) - return - } - - guard let httpResponse = response as? HTTPURLResponse else { - completion(.failure(ErrorResponse.error(-2, data, response, DecodableRequestBuilderError.nilHTTPResponse))) - return - } - - guard httpResponse.isStatusCodeSuccessful else { - completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, response, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode))) - return - } - - switch T.self { - case is Void.Type: - - completion(.success(Response(response: httpResponse, body: () as! T, bodyData: data))) - - default: - fatalError("Unsupported Response Body Type - \(String(describing: T.self))") - } - } - - open func buildHeaders() -> [String: String] { - var httpHeaders: [String: String] = [:] - for (key, value) in GravatarOpenAPIClientAPI.customHeaders { - httpHeaders[key] = value - } - for (key, value) in headers { - httpHeaders[key] = value - } - return httpHeaders - } - - fileprivate func getFileName(fromContentDisposition contentDisposition: String?) -> String? { - guard let contentDisposition else { - return nil - } - - let items = contentDisposition.components(separatedBy: ";") - - var filename: String? - - for contentItem in items { - let filenameKey = "filename=" - guard let range = contentItem.range(of: filenameKey) else { - continue - } - - filename = contentItem - return filename? - .replacingCharacters(in: range, with: "") - .replacingOccurrences(of: "\"", with: "") - .trimmingCharacters(in: .whitespacesAndNewlines) - } - - return filename - } - - fileprivate func getPath(from url: URL) throws -> String { - guard var path = URLComponents(url: url, resolvingAgainstBaseURL: true)?.path else { - throw DownloadException.requestMissingPath - } - - if path.hasPrefix("/") { - path.remove(at: path.startIndex) - } - - return path - } - - fileprivate func getURL(from urlRequest: URLRequest) throws -> URL { - guard let url = urlRequest.url else { - throw DownloadException.requestMissingURL - } - - return url - } -} - -open class URLSessionDecodableRequestBuilder: URLSessionRequestBuilder { - override fileprivate func processRequestResponse( - urlRequest: URLRequest, - data: Data?, - response: URLResponse?, - error: Error?, - completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void - ) { - if let error { - completion(.failure(ErrorResponse.error(-1, data, response, error))) - return - } - - guard let httpResponse = response as? HTTPURLResponse else { - completion(.failure(ErrorResponse.error(-2, data, response, DecodableRequestBuilderError.nilHTTPResponse))) - return - } - - guard httpResponse.isStatusCodeSuccessful else { - completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, response, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode))) - return - } - - switch T.self { - case is String.Type: - - let body = data.flatMap { String(data: $0, encoding: .utf8) } ?? "" - - completion(.success(Response(response: httpResponse, body: body as! T, bodyData: data))) - - case is URL.Type: - do { - guard error == nil else { - throw DownloadException.responseFailed - } - - guard let data else { - throw DownloadException.responseDataMissing - } - - let fileManager = FileManager.default - let cachesDirectory = fileManager.urls(for: .cachesDirectory, in: .userDomainMask)[0] - let requestURL = try getURL(from: urlRequest) - - var requestPath = try getPath(from: requestURL) - - if let headerFileName = getFileName(fromContentDisposition: httpResponse.allHeaderFields["Content-Disposition"] as? String) { - requestPath = requestPath.appending("/\(headerFileName)") - } else { - requestPath = requestPath.appending("/tmp.GravatarOpenAPIClient.\(UUID().uuidString)") - } - - let filePath = cachesDirectory.appendingPathComponent(requestPath) - let directoryPath = filePath.deletingLastPathComponent().path - - try fileManager.createDirectory(atPath: directoryPath, withIntermediateDirectories: true, attributes: nil) - try data.write(to: filePath, options: .atomic) - - completion(.success(Response(response: httpResponse, body: filePath as! T, bodyData: data))) - - } catch let requestParserError as DownloadException { - completion(.failure(ErrorResponse.error(400, data, response, requestParserError))) - } catch { - completion(.failure(ErrorResponse.error(400, data, response, error))) - } - - case is Void.Type: - - completion(.success(Response(response: httpResponse, body: () as! T, bodyData: data))) - - case is Data.Type: - - completion(.success(Response(response: httpResponse, body: data as! T, bodyData: data))) - - default: - - guard let unwrappedData = data, !unwrappedData.isEmpty else { - if let expressibleByNilLiteralType = T.self as? ExpressibleByNilLiteral.Type { - completion(.success(Response(response: httpResponse, body: expressibleByNilLiteralType.init(nilLiteral: ()) as! T, bodyData: data))) - } else { - completion(.failure(ErrorResponse.error(httpResponse.statusCode, nil, response, DecodableRequestBuilderError.emptyDataResponse))) - } - return - } - - let decodeResult = CodableHelper.decode(T.self, from: unwrappedData) - - switch decodeResult { - case .success(let decodableObj): - completion(.success(Response(response: httpResponse, body: decodableObj, bodyData: unwrappedData))) - case .failure(let error): - completion(.failure(ErrorResponse.error(httpResponse.statusCode, unwrappedData, response, error))) - } - } - } -} - -private class SessionDelegate: NSObject, URLSessionTaskDelegate { - func urlSession( - _ session: URLSession, - task: URLSessionTask, - didReceive challenge: URLAuthenticationChallenge, - completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void - ) { - var disposition: URLSession.AuthChallengeDisposition = .performDefaultHandling - - var credential: URLCredential? - - if let taskDidReceiveChallenge = challengeHandlerStore[task.taskIdentifier] { - (disposition, credential) = taskDidReceiveChallenge(session, task, challenge) - } else { - if challenge.previousFailureCount > 0 { - disposition = .rejectProtectionSpace - } else { - credential = credentialStore[task.taskIdentifier] ?? session.configuration.urlCredentialStorage? - .defaultCredential(for: challenge.protectionSpace) - - if credential != nil { - disposition = .useCredential - } - } - } - - completionHandler(disposition, credential) - } -} - -public enum HTTPMethod: String { - case options = "OPTIONS" - case get = "GET" - case head = "HEAD" - case post = "POST" - case put = "PUT" - case patch = "PATCH" - case delete = "DELETE" - case trace = "TRACE" - case connect = "CONNECT" -} - -public protocol ParameterEncoding { - func encode(_ urlRequest: URLRequest, with parameters: [String: Any]?) throws -> URLRequest -} - -private class URLEncoding: ParameterEncoding { - func encode(_ urlRequest: URLRequest, with parameters: [String: Any]?) throws -> URLRequest { - var urlRequest = urlRequest - - guard let parameters else { return urlRequest } - - guard let url = urlRequest.url else { - throw DownloadException.requestMissingURL - } - - if var urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: false), !parameters.isEmpty { - urlComponents.queryItems = APIHelper.mapValuesToQueryItems(parameters) - urlRequest.url = urlComponents.url - } - - return urlRequest - } -} - -private class FormDataEncoding: ParameterEncoding { - let contentTypeForFormPart: (_ fileURL: URL) -> String? - - init(contentTypeForFormPart: @escaping (_ fileURL: URL) -> String?) { - self.contentTypeForFormPart = contentTypeForFormPart - } - - func encode(_ urlRequest: URLRequest, with parameters: [String: Any]?) throws -> URLRequest { - var urlRequest = urlRequest - - guard let parameters, !parameters.isEmpty else { - return urlRequest - } - - let boundary = "Boundary-\(UUID().uuidString)" - - urlRequest.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type") - - for (key, value) in parameters { - for value in value as? Array ?? [value] { - switch value { - case let fileURL as URL: - - urlRequest = try configureFileUploadRequest( - urlRequest: urlRequest, - boundary: boundary, - name: key, - fileURL: fileURL - ) - - case let string as String: - - if let data = string.data(using: .utf8) { - urlRequest = configureDataUploadRequest( - urlRequest: urlRequest, - boundary: boundary, - name: key, - data: data - ) - } - - case let number as NSNumber: - - if let data = number.stringValue.data(using: .utf8) { - urlRequest = configureDataUploadRequest( - urlRequest: urlRequest, - boundary: boundary, - name: key, - data: data - ) - } - - case let data as Data: - - urlRequest = configureDataUploadRequest( - urlRequest: urlRequest, - boundary: boundary, - name: key, - data: data - ) - - case let uuid as UUID: - - if let data = uuid.uuidString.data(using: .utf8) { - urlRequest = configureDataUploadRequest( - urlRequest: urlRequest, - boundary: boundary, - name: key, - data: data - ) - } - - default: - fatalError("Unprocessable value \(value) with key \(key)") - } - } - } - - var body = urlRequest.httpBody.orEmpty - - body.append("\r\n--\(boundary)--\r\n") - - urlRequest.httpBody = body - - return urlRequest - } - - private func configureFileUploadRequest(urlRequest: URLRequest, boundary: String, name: String, fileURL: URL) throws -> URLRequest { - var urlRequest = urlRequest - - var body = urlRequest.httpBody.orEmpty - - let fileData = try Data(contentsOf: fileURL) - - let mimetype = contentTypeForFormPart(fileURL) ?? mimeType(for: fileURL) - - let fileName = fileURL.lastPathComponent - - // If we already added something then we need an additional newline. - if body.count > 0 { - body.append("\r\n") - } - - // Value boundary. - body.append("--\(boundary)\r\n") - - // Value headers. - body.append("Content-Disposition: form-data; name=\"\(name)\"; filename=\"\(fileName)\"\r\n") - body.append("Content-Type: \(mimetype)\r\n") - - // Separate headers and body. - body.append("\r\n") - - // The value data. - body.append(fileData) - - urlRequest.httpBody = body - - return urlRequest - } - - private func configureDataUploadRequest(urlRequest: URLRequest, boundary: String, name: String, data: Data) -> URLRequest { - var urlRequest = urlRequest - - var body = urlRequest.httpBody.orEmpty - - // If we already added something then we need an additional newline. - if body.count > 0 { - body.append("\r\n") - } - - // Value boundary. - body.append("--\(boundary)\r\n") - - // Value headers. - body.append("Content-Disposition: form-data; name=\"\(name)\"\r\n") - - // Separate headers and body. - body.append("\r\n") - - // The value data. - body.append(data) - - urlRequest.httpBody = body - - return urlRequest - } - - func mimeType(for url: URL) -> String { - let pathExtension = url.pathExtension - - if #available(iOS 15, macOS 11, *) { - #if canImport(UniformTypeIdentifiers) - if let utType = UTType(filenameExtension: pathExtension) { - return utType.preferredMIMEType ?? "application/octet-stream" - } - #else - return "application/octet-stream" - #endif - } else { - if let uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, pathExtension as NSString, nil)?.takeRetainedValue(), - let mimetype = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType)?.takeRetainedValue() - { - return mimetype as String - } - return "application/octet-stream" - } - return "application/octet-stream" - } -} - -private class FormURLEncoding: ParameterEncoding { - func encode(_ urlRequest: URLRequest, with parameters: [String: Any]?) throws -> URLRequest { - var urlRequest = urlRequest - - var requestBodyComponents = URLComponents() - requestBodyComponents.queryItems = APIHelper.mapValuesToQueryItems(parameters ?? [:]) - - if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil { - urlRequest.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type") - } - - urlRequest.httpBody = requestBodyComponents.query?.data(using: .utf8) - - return urlRequest - } -} - -private class OctetStreamEncoding: ParameterEncoding { - func encode(_ urlRequest: URLRequest, with parameters: [String: Any]?) throws -> URLRequest { - var urlRequest = urlRequest - - guard let body = parameters?["body"] else { return urlRequest } - - if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil { - urlRequest.setValue("application/octet-stream", forHTTPHeaderField: "Content-Type") - } - - switch body { - case let fileURL as URL: - urlRequest.httpBody = try Data(contentsOf: fileURL) - case let data as Data: - urlRequest.httpBody = data - default: - fatalError("Unprocessable body \(body)") - } - - return urlRequest - } -} - -extension Data { - /// Append string to Data - /// - /// Rather than littering my code with calls to `dataUsingEncoding` to convert strings to Data, and then add that data to the Data, this wraps it in a nice - /// convenient little extension to Data. This converts using UTF-8. - /// - /// - parameter string: The string to be added to the `Data`. - - fileprivate mutating func append(_ string: String) { - if let data = string.data(using: .utf8) { - append(data) - } - } -} - -extension Data? { - fileprivate var orEmpty: Data { - self ?? Data() - } -} - -extension JSONDataEncoding: ParameterEncoding {} diff --git a/Sources/GravatarOpenAPIClient/Validation.swift b/Sources/GravatarOpenAPIClient/Validation.swift deleted file mode 100644 index 5ae7e28c..00000000 --- a/Sources/GravatarOpenAPIClient/Validation.swift +++ /dev/null @@ -1,120 +0,0 @@ -import Foundation - -public struct StringRule { - public var minLength: Int? - public var maxLength: Int? - public var pattern: String? -} - -public struct NumericRule { - public var minimum: T? - public var exclusiveMinimum = false - public var maximum: T? - public var exclusiveMaximum = false - public var multipleOf: T? -} - -public enum StringValidationErrorKind: Error { - case minLength, maxLength, pattern -} - -public enum NumericValidationErrorKind: Error { - case minimum, maximum, multipleOf -} - -public struct ValidationError: Error { - public fileprivate(set) var kinds: Set -} - -public enum Validator { - /// Validate a string against a rule. - /// - Parameter string: The String you wish to validate. - /// - Parameter rule: The StringRule you wish to use for validation. - /// - Returns: A validated string. - /// - Throws: `ValidationError` if the string is invalid against the rule, - /// `NSError` if the rule.pattern is invalid. - public static func validate(_ string: String, against rule: StringRule) throws -> String { - var error = ValidationError(kinds: []) - if let minLength = rule.minLength, !(minLength <= string.count) { - error.kinds.insert(.minLength) - } - if let maxLength = rule.maxLength, !(string.count <= maxLength) { - error.kinds.insert(.maxLength) - } - if let pattern = rule.pattern { - let matches = try NSRegularExpression(pattern: pattern, options: .caseInsensitive) - .matches(in: string, range: .init(location: 0, length: string.utf16.count)) - if matches.isEmpty { - error.kinds.insert(.pattern) - } - } - guard error.kinds.isEmpty else { - throw error - } - return string - } - - /// Validate a integer against a rule. - /// - Parameter numeric: The integer you wish to validate. - /// - Parameter rule: The NumericRule you wish to use for validation. - /// - Returns: A validated integer. - /// - Throws: `ValidationError` if the numeric is invalid against the rule. - public static func validate(_ numeric: T, against rule: NumericRule) throws -> T { - var error = ValidationError(kinds: []) - if let minium = rule.minimum { - if !rule.exclusiveMinimum, minium > numeric { - error.kinds.insert(.minimum) - } - if rule.exclusiveMinimum, minium >= numeric { - error.kinds.insert(.minimum) - } - } - if let maximum = rule.maximum { - if !rule.exclusiveMaximum, numeric > maximum { - error.kinds.insert(.maximum) - } - if rule.exclusiveMaximum, numeric >= maximum { - error.kinds.insert(.maximum) - } - } - if let multipleOf = rule.multipleOf, !numeric.isMultiple(of: multipleOf) { - error.kinds.insert(.multipleOf) - } - guard error.kinds.isEmpty else { - throw error - } - return numeric - } - - /// Validate a fractional number against a rule. - /// - Parameter numeric: The fractional number you wish to validate. - /// - Parameter rule: The NumericRule you wish to use for validation. - /// - Returns: A validated fractional number. - /// - Throws: `ValidationError` if the numeric is invalid against the rule. - public static func validate(_ numeric: T, against rule: NumericRule) throws -> T { - var error = ValidationError(kinds: []) - if let minium = rule.minimum { - if !rule.exclusiveMinimum, minium > numeric { - error.kinds.insert(.minimum) - } - if rule.exclusiveMinimum, minium >= numeric { - error.kinds.insert(.minimum) - } - } - if let maximum = rule.maximum { - if !rule.exclusiveMaximum, numeric > maximum { - error.kinds.insert(.maximum) - } - if rule.exclusiveMaximum, numeric >= maximum { - error.kinds.insert(.maximum) - } - } - if let multipleOf = rule.multipleOf, numeric.remainder(dividingBy: multipleOf) != 0 { - error.kinds.insert(.multipleOf) - } - guard error.kinds.isEmpty else { - throw error - } - return numeric - } -} diff --git a/openapi/GravatarOpenAPIClient/.openapi-generator-ignore b/openapi/GravatarOpenAPIClient/.openapi-generator-ignore index 146d6f12..960c8197 100644 --- a/openapi/GravatarOpenAPIClient/.openapi-generator-ignore +++ b/openapi/GravatarOpenAPIClient/.openapi-generator-ignore @@ -26,4 +26,5 @@ .swiftformat Cartfile git_push.sh -Sources/GravatarOpenAPIClient/APIs/ \ No newline at end of file +Sources/GravatarOpenAPIClient/ +!Sources/GravatarOpenAPIClient/Models/ diff --git a/openapi/GravatarOpenAPIClient/.openapi-generator/FILES b/openapi/GravatarOpenAPIClient/.openapi-generator/FILES index cbf23778..f54bbde5 100644 --- a/openapi/GravatarOpenAPIClient/.openapi-generator/FILES +++ b/openapi/GravatarOpenAPIClient/.openapi-generator/FILES @@ -1,14 +1,6 @@ GravatarOpenAPIClient.podspec Package.swift README.md -Sources/GravatarOpenAPIClient/APIHelper.swift -Sources/GravatarOpenAPIClient/APIs.swift -Sources/GravatarOpenAPIClient/CodableHelper.swift -Sources/GravatarOpenAPIClient/Configuration.swift -Sources/GravatarOpenAPIClient/Extensions.swift -Sources/GravatarOpenAPIClient/JSONDataEncoding.swift -Sources/GravatarOpenAPIClient/JSONEncodingHelper.swift -Sources/GravatarOpenAPIClient/Models.swift Sources/GravatarOpenAPIClient/Models/AssociatedResponse.swift Sources/GravatarOpenAPIClient/Models/Avatar.swift Sources/GravatarOpenAPIClient/Models/CryptoWalletAddress.swift @@ -22,10 +14,6 @@ Sources/GravatarOpenAPIClient/Models/ProfileContactInfo.swift Sources/GravatarOpenAPIClient/Models/ProfilePayments.swift Sources/GravatarOpenAPIClient/Models/SetEmailAvatarRequest.swift Sources/GravatarOpenAPIClient/Models/VerifiedAccount.swift -Sources/GravatarOpenAPIClient/OpenISO8601DateFormatter.swift -Sources/GravatarOpenAPIClient/SynchronizedDictionary.swift -Sources/GravatarOpenAPIClient/URLSessionImplementations.swift -Sources/GravatarOpenAPIClient/Validation.swift docs/AssociatedResponse.md docs/Avatar.md docs/AvatarsAPI.md