Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SplitMode for SPM Package #232

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

### Added
- MediaItem schema is now defined as a possible reference in order to generate models of each server response. #239 @alexruperez
- Added ability to use only some part of the generated code when using SPM #232

### Fixed
- Fixed inline allOf group generation
Expand Down
17 changes: 13 additions & 4 deletions Templates/Swift/Package.swift
Original file line number Diff line number Diff line change
@@ -1,22 +1,31 @@
// swift-tools-version:4.0
// swift-tools-version:5.1

import PackageDescription

let package = Package(
name: "{{ options.name }}",
products: [
.library(name: "{{ options.name }}", targets: ["{{ options.name }}"])
.library(name: "{{ options.name }}", targets: ["{{ options.name }}Client"]),
.library(name: "{{ options.name }}Dynamic", type: .dynamic, targets: ["{{ options.name }}Client"]),
.library(name: "{{ options.name }}Requests", targets: ["{{ options.name }}Requests"]),
.library(name: "{{ options.name }}DynamicRequests", type: .dynamic, targets: ["{{ options.name }}Requests"]),
.library(name: "{{ options.name }}Models", targets: ["{{ options.name }}Models"]),
.library(name: "{{ options.name }}DynamicModels", type: .dynamic, targets: ["{{ options.name }}Models"]),
],
dependencies: [
{% for dependency in options.dependencies %}
.package(url: "https://github.com/{{ dependency.github }}.git", .exact("{{ dependency.version }}")),
{% endfor %}
],
targets: [
.target(name: "{{ options.name }}", dependencies: [
.target(name: "{{ options.name }}SharedCode", path: "Sources/SharedCode"),
.target(name: "{{ options.name }}Models", path: "Sources/Models", swiftSettings: [SwiftSetting.define("SPM_SPLIT_MODE_ON")]),
.target(name: "{{ options.name }}Requests", dependencies: [ "{{ options.name }}Models", "{{ options.name }}SharedCode"], path: "Sources/Requests", swiftSettings: [SwiftSetting.define("SPM_SPLIT_MODE_ON")]),
.target(name: "{{ options.name }}Client", dependencies: [
"{{ options.name }}Requests",
{% for dependency in options.dependencies %}
"{{ dependency.pod }}",
{% endfor %}
], path: "Sources")
], path: "Sources/Client", swiftSettings: [SwiftSetting.define("SPM_SPLIT_MODE_ON")])
]
)
1 change: 0 additions & 1 deletion Templates/Swift/Podspec.podspec
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
Pod::Spec.new do |s|
s.source_files = '*.swift'
s.name = '{{ options.name }}'
s.authors = '{{ options.authors|default:"Yonas Kolb" }}'
s.summary = '{{ info.description|default:"A generated API" }}'
Expand Down
86 changes: 0 additions & 86 deletions Templates/Swift/Sources/APIRequest.swift

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
import Foundation
import Alamofire

#if SPM_SPLIT_MODE_ON
import {{ options.name }}Requests
import {{ options.name }}Models
import {{ options.name }}SharedCode
#endif

/// Manages and sends APIRequests
public class APIClient {

Expand Down Expand Up @@ -175,7 +181,7 @@ public class APIClient {
result = .failure(apiError)
requestBehaviour.onFailure(error: apiError)
}
let response = APIResponse<T>(request: request, result: result, urlRequest: dataResponse.request, urlResponse: dataResponse.response, data: dataResponse.data, timeline: dataResponse.timeline)
let response = APIResponse<T>(request: request, result: result, urlRequest: dataResponse.request, urlResponse: dataResponse.response, data: dataResponse.data, timeline: Timeline(requestStartTime: dataResponse.timeline.requestStartTime, initialResponseTime: dataResponse.timeline.initialResponseTime, requestCompletedTime: dataResponse.timeline.requestCompletedTime, serializationCompletedTime: dataResponse.timeline.serializationCompletedTime))
requestBehaviour.onResponse(response: response.asAny())

completionQueue.async {
Expand Down Expand Up @@ -209,41 +215,3 @@ extension APIRequest {
APIClient.default.makeRequest(self, complete: complete)
}
}

// Create URLRequest
extension APIRequest {

/// pass in an optional baseURL, otherwise URLRequest.url will be relative
public func createURLRequest(baseURL: String = "", encoder: RequestEncoder = JSONEncoder()) throws -> URLRequest {
let url = URL(string: "\(baseURL)\(path)")!
var urlRequest = URLRequest(url: url)
urlRequest.httpMethod = service.method
urlRequest.allHTTPHeaderFields = headers

// filter out parameters with empty string value
var queryParams: [String: Any] = [:]
for (key, value) in queryParameters {
if String.init(describing: value) != "" {
queryParams[key] = value
}
}
if !queryParams.isEmpty {
urlRequest = try URLEncoding.queryString.encode(urlRequest, with: queryParams)
}

var formParams: [String: Any] = [:]
for (key, value) in formParameters {
if String.init(describing: value) != "" {
formParams[key] = value
}
}
if !formParams.isEmpty {
urlRequest = try URLEncoding.httpBody.encode(urlRequest, with: formParams)
}
if let encodeBody = encodeBody {
urlRequest.httpBody = try encodeBody(encoder)
urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
}
return urlRequest
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

import Foundation

#if SPM_SPLIT_MODE_ON
import {{ options.name }}Requests
import {{ options.name }}SharedCode
#endif

public protocol RequestBehaviour {

/// runs first and allows the requests to be modified. If modifying asynchronously use validate
Expand Down Expand Up @@ -111,79 +116,3 @@ struct RequestBehaviourGroup {
return urlRequest
}
}

//MARK: Type erased Requests and Responses

public typealias AnyResponse = APIResponse<AnyResponseValue>

public class AnyRequest: APIRequest<AnyResponseValue> {
private let requestPath: String

override public var path: String {
return requestPath
}

init<T>(request: APIRequest<T>) {
requestPath = request.path
super.init(service: request.service.asAny(), queryParameters: request.queryParameters, formParameters: request.formParameters, headers: request.headers, encodeBody: request.encodeBody)
}
}

public struct AnyResponseValue: APIResponseValue, CustomDebugStringConvertible, CustomStringConvertible {

public typealias SuccessType = {% if options.codableResponses %}AnyCodable{% else %}Any{% endif %}

public let statusCode: Int
public let successful: Bool
public let response: Any
public let responseEnum: Any
public let success: {% if options.codableResponses %}AnyCodable{% else %}Any{% endif %}?

public init(statusCode: Int, successful: Bool, response: Any, responseEnum: Any, success: {% if options.codableResponses %}AnyCodable{% else %}Any{% endif %}?) {
self.statusCode = statusCode
self.successful = successful
self.response = response
self.responseEnum = responseEnum
self.success = success
}

public init(statusCode: Int, data: Data, decoder: ResponseDecoder) throws {
fatalError()
}

public var description:String {
return "\(responseEnum)"
}

public var debugDescription: String {
if let debugDescription = responseEnum as? CustomDebugStringConvertible {
return debugDescription.debugDescription
} else {
return "\(responseEnum)"
}
}
}

extension APIResponseValue {
public func asAny() -> AnyResponseValue {
return AnyResponseValue(statusCode: statusCode, successful: successful, response: response, responseEnum: self, success: {% if options.codableResponses %}AnyCodable(success){% else %}success{% endif %})
}
}

extension APIResponse {
public func asAny() -> APIResponse<AnyResponseValue> {
return APIResponse<AnyResponseValue>(request: request.asAny(), result: result.map{ $0.asAny() }, urlRequest: urlRequest, urlResponse: urlResponse, data: data, timeline: timeline)
}
}

extension APIRequest {
public func asAny() -> AnyRequest {
return AnyRequest(request: self)
}
}

extension APIService {
public func asAny() -> APIService<AnyResponseValue> {
return APIService<AnyResponseValue>(id: id, tag: tag, method: method, path: path, hasBody: hasBody, securityRequirement: securityRequirement)
}
}
19 changes: 19 additions & 0 deletions Templates/Swift/Sources/Models/APIModel.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{% include "Includes/Header.stencil" %}

import Foundation

{% if options.modelProtocol %}
public protocol {{ options.modelProtocol }}: Codable, Equatable { }

extension {{ options.modelProtocol }} {
func encode() -> [String: Any] {
guard
let jsonData = try? JSONEncoder().encode(self),
let jsonValue = try? JSONSerialization.jsonObject(with: jsonData),
let jsonDictionary = jsonValue as? [String: Any] else {
return [:]
}
return jsonDictionary
}
}
{% endif %}
Loading