<commit_before>import Foundation

public protocol Cancellable {
    func cancelAll()
}

public typealias AuthTokens = (accessToken: String?, refreshToken: String?)

public protocol Client: RequestSender, Cancellable {
    var baseUrl: String { get }
    var authHandler: AuthHandler { get }
    var authTokens: AuthTokens { get }
    var sessionConfiguration: URLSessionConfiguration { get }
}

public typealias RequestCompletion<SerializedObject> = (_ result: Result<SerializedObject>) -> ()

open class GlobalLifeCycle {
    open func willSend<R: Request>(request: R) throws { }
    open func didFinish<SerializedObject>(result: Result<SerializedObject>) throws { }
}

open class AutoGraph {
    public var baseUrl: String {
        return self.client.baseUrl
    }
    
    public var authHandler: AuthHandler {
        return self.client.authHandler
    }
    
    public var networkErrorParser: NetworkErrorParser? {
        get {
            return self.dispatcher.responseHandler.networkErrorParser
        }
        set {
            self.dispatcher.responseHandler.networkErrorParser = newValue
        }
    }
    
    public let client: Client
    public let dispatcher: Dispatcher
    public var lifeCycle: GlobalLifeCycle?
    
    public static let localHost = "http://localhost:8080/graphql"
    
    public required init(client: Client = AlamofireClient(baseUrl: localHost)) {
        self.client = client
        self.dispatcher = Dispatcher(url: client.baseUrl, requestSender: client, responseHandler: ResponseHandler())
        self.client.authHandler.delegate = self
    }
    
    internal convenience init() {
        let client = AlamofireClient(baseUrl: AutoGraph.localHost)
        let dispatcher = Dispatcher(url: client.baseUrl, requestSender: client, responseHandler: ResponseHandler())
        self.init(client: client, dispatcher: dispatcher)
    }
    
    public init(client: Client, dispatcher: Dispatcher) {
        self.client = client
        self.dispatcher = dispatcher
        self.client.authHandler.delegate = self
    }
    
    public func send<R: Request>(_ request: R, completion: @escaping RequestCompletion<R.SerializedObject>)
    where R.SerializedObject == R.Mapping.MappedObject {
        
        let objectBindingPromise = { sendable in
            return request.generateBinding { [weak self] result in
                self?.complete(result: result, sendable: sendable, requestDidFinish: request.didFinish, completion: completion)
            }
        }
        
        let sendable = Sendable(dispatcher: self.dispatcher, request: request, objectBindingPromise: objectBindingPromise) { [weak self] request in
            try self?.lifeCycle?.willSend(request: request)
        }
        
        self.dispatcher.send(sendable: sendable)
    }
    
    private func complete<SerializedObject>(result: Result<SerializedObject>, sendable: Sendable, requestDidFinish: (Result<SerializedObject>) throws -> (), completion: @escaping RequestCompletion<SerializedObject>) {
        
        do {
            try self.raiseAuthenticationError(from: result)
        }
        catch {
            self.triggerReauthentication()<commit_msg>[open-send] mark send as open so you can use it for mocking<commit_after>import Foundation

public protocol Cancellable {
    func cancelAll()
}

public typealias AuthTokens = (accessToken: String?, refreshToken: String?)

public protocol Client: RequestSender, Cancellable {
    var baseUrl: String { get }
    var authHandler: AuthHandler { get }
    var authTokens: AuthTokens { get }
    var sessionConfiguration: URLSessionConfiguration { get }
}

public typealias RequestCompletion<SerializedObject> = (_ result: Result<SerializedObject>) -> ()

open class GlobalLifeCycle {
    open func willSend<R: Request>(request: R) throws { }
    open func didFinish<SerializedObject>(result: Result<SerializedObject>) throws { }
}

open class AutoGraph {
    public var baseUrl: String {
        return self.client.baseUrl
    }
    
    public var authHandler: AuthHandler {
        return self.client.authHandler
    }
    
    public var networkErrorParser: NetworkErrorParser? {
        get {
            return self.dispatcher.responseHandler.networkErrorParser
        }
        set {
            self.dispatcher.responseHandler.networkErrorParser = newValue
        }
    }
    
    public let client: Client
    public let dispatcher: Dispatcher
    public var lifeCycle: GlobalLifeCycle?
    
    public static let localHost = "http://localhost:8080/graphql"
    
    public required init(client: Client = AlamofireClient(baseUrl: localHost)) {
        self.client = client
        self.dispatcher = Dispatcher(url: client.baseUrl, requestSender: client, responseHandler: ResponseHandler())
        self.client.authHandler.delegate = self
    }
    
    internal convenience init() {
        let client = AlamofireClient(baseUrl: AutoGraph.localHost)
        let dispatcher = Dispatcher(url: client.baseUrl, requestSender: client, responseHandler: ResponseHandler())
        self.init(client: client, dispatcher: dispatcher)
    }
    
    public init(client: Client, dispatcher: Dispatcher) {
        self.client = client
        self.dispatcher = dispatcher
        self.client.authHandler.delegate = self
    }
    
    open func send<R: Request>(_ request: R, completion: @escaping RequestCompletion<R.SerializedObject>)
    where R.SerializedObject == R.Mapping.MappedObject {
        
        let objectBindingPromise = { sendable in
            return request.generateBinding { [weak self] result in
                self?.complete(result: result, sendable: sendable, requestDidFinish: request.didFinish, completion: completion)
            }
        }
        
        let sendable = Sendable(dispatcher: self.dispatcher, request: request, objectBindingPromise: objectBindingPromise) { [weak self] request in
            try self?.lifeCycle?.willSend(request: request)
        }
        
        self.dispatcher.send(sendable: sendable)
    }
    
    private func complete<SerializedObject>(result: Result<SerializedObject>, sendable: Sendable, requestDidFinish: (Result<SerializedObject>) throws -> (), completion: @escaping RequestCompletion<SerializedObject>) {
        
        do {
            try self.raiseAuthenticationError(from: result)
        }
        catch {
            self.triggerReauthentication()
{'fraction_non_alphanumeric': 0.08372310570626754, 'fraction_numerical': 0.0012472715933894605, 'mean_word_length': 2.9919103920348475, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '780785', 'n_tokens_mistral': 1683, 'n_tokens_neox': 1656, 'n_words': 426}