summaryrefslogtreecommitdiffhomepage
path: root/ios/MullvadVPN/JSONRequestProcedure.swift
blob: 6b6527b6f172f4bbe2641c70274d73889f79ca16 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
//
//  JSONRequestProcedure.swift
//  MullvadVPN
//
//  Created by pronebird on 14/05/2019.
//  Copyright © 2019 Amagicom AB. All rights reserved.
//

import Foundation
import ProcedureKit

final class JSONRequestProcedure<Input, Output: Decodable>: GroupProcedure, InputProcedure, OutputProcedure {

    typealias URLRequestBuilder = (Input) throws -> URLRequest

    var input: Pending<Input>
    var output: Pending<ProcedureResult<Output>> = .pending

    init(dispatchQueue underlyingQueue: DispatchQueue? = nil, input: Input? = nil, requestBuilder: @escaping URLRequestBuilder) {
        self.input = input.flatMap { .ready($0) } ?? .pending

        let createRequest = TransformProcedure { try requestBuilder($0) }

        let networkRequest = NetworkProcedure {
            NetworkDataProcedure(session: URLSession.shared)
            }.injectResult(from: createRequest)

        let payloadParsing = DecodeJSONProcedure<Output>(
            dateDecodingStrategy: .iso8601,
            keyDecodingStrategy: .convertFromSnakeCase
            ).injectPayload(fromNetwork: networkRequest)

        super.init(dispatchQueue: underlyingQueue, operations: [createRequest, networkRequest, payloadParsing])

        bind(from: payloadParsing)

        addWillExecuteBlockObserver { (procedure, _) in
            createRequest.input = procedure.input
        }
    }
}

extension JSONRequestProcedure where Input == Void {
    convenience init(requestBuilder: @escaping URLRequestBuilder) {
        self.init(input: (), requestBuilder: requestBuilder)
    }
}