Skip to content

Commit

Permalink
fixing an init
Browse files Browse the repository at this point in the history
  • Loading branch information
leogdion committed Aug 15, 2024
1 parent 7811b4b commit bb0b629
Show file tree
Hide file tree
Showing 14 changed files with 164 additions and 51 deletions.
1 change: 1 addition & 0 deletions Packages/Ngrokit/Sources/Ngrokit/NgrokError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ public enum NgrokError: Int, LocalizedError {
case websiteVisitWarning = 6_024
case tunnelConnectionFailed = 8_012

/// A localized message describing what error occurred.
public var errorDescription: String? {
switch self { case .invalidMetadataLength: "Invalid metadata length" case .accountLimitExceeded:
"You've hit your account limit for simultaneous ngrok agent sessions. Try stopping an existing agent or upgrading your account."
Expand Down
11 changes: 4 additions & 7 deletions Packages/Ngrokit/Sources/Ngrokit/NgrokMacProcess.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,7 @@ public actor NgrokMacProcess<ProcessType: Processable>: NgrokProcess {
/// - Parameters:
/// - ngrokPath: The path to the Ngrok executable.
/// - httpPort: The port to use for the HTTP connection.
/// - processType: The type of process to use.
///
/// - Returns: A new instance of `NgrokMacProcess`.
/// - _: The type of process to use.
public init(ngrokPath: String, httpPort: Int, processType _: ProcessType.Type) {
self.init(process: .init(executableFilePath: ngrokPath, scheme: "http", port: httpPort))
}
Expand All @@ -78,8 +76,7 @@ public actor NgrokMacProcess<ProcessType: Processable>: NgrokProcess {

/// A private method that handles the termination of the process.
///
/// - Parameters:
/// - forProcess: The process that has terminated.
/// - Parameter _: The process that has terminated.
@Sendable private nonisolated func terminationHandler(forProcess _: any Processable) {
Task {
let error: any Error
Expand All @@ -91,14 +88,14 @@ public actor NgrokMacProcess<ProcessType: Processable>: NgrokProcess {

/// Runs the Ngrok process.
///
/// - Parameters:
/// - onError: A closure that handles any errors that occur during the process.
/// - Parameter onError: A closure that handles any errors that occur during the process.
///
/// - Throws: An error if the process fails to run.
public func run(onError: @Sendable @escaping (any Error) -> Void) async throws {
process.setTerminationHandler(terminationHandler(forProcess:))
terminationHandler = onError
try process.run()
}
/// Terminates the current process.
nonisolated public func terminate() { self.process.terminate() }
}
1 change: 1 addition & 0 deletions Packages/Ngrokit/Sources/Ngrokit/NgrokProcess.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public protocol NgrokProcess: Sendable {
/// Runs the Ngrok process.
///
/// - Parameter onError: A closure to handle any errors that occur during the process.
/// - Throws: If there's an issue with running the process.
func run(onError: @Sendable @escaping (any Error) -> Void) async throws
func terminate()
}
8 changes: 4 additions & 4 deletions Packages/Ngrokit/Sources/Ngrokit/Processable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,12 @@ public protocol Processable: Sendable, AnyObject {
/// - Requires: This initializer must be implemented.
init(executableFilePath: String, scheme: String, port: Int)

/// Sets a closure to be called when the process terminates.
/// Sets a closure to be called when the process terminates.
///
/// - Parameters:
/// - closure: The closure to be called.
/// - Requires: This method must be implemented.
///
/// - Requires: This method must be implemented.
/// - Parameter closure: The closure to be called.

func setTerminationHandler(_ closure: @escaping @Sendable (Self) -> Void)

/// Creates a new pipe.
Expand Down
3 changes: 1 addition & 2 deletions Packages/Ngrokit/Sources/Ngrokit/TunnelRequest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,7 @@ public struct TunnelRequest: Sendable {
extension Components.Schemas.TunnelRequest {
/// Initializes a new `Components.Schemas.TunnelRequest` instance.
///
/// - Parameters:
/// - request: The `TunnelRequest` instance to initialize from.
/// - Parameter request: The `TunnelRequest` instance to initialize from.
internal init(request: TunnelRequest) {
self.init(addr: request.addr, proto: request.proto, name: request.name)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,14 +85,14 @@
browser.browseResultsChangedHandler = { results, _ in self.parseResults(results) }
}

private static func descriptionFor(state: NWConnection.State) -> String {
switch state { case .setup: "setup" case .waiting: "waiting" case .preparing: "preparing"
case .ready: "ready"
case .failed: "failed"
case .cancelled: "cancelled"
default: "unknown"
}
}
// private static func descriptionFor(state: NWConnection.State) -> String {
// switch state { case .setup: "setup" case .waiting: "waiting" case .preparing: "preparing"
// case .ready: "ready"
// case .failed: "failed"
// case .cancelled: "cancelled"
// default: "unknown"
// }
// }

private func append(urls: [URL]) async { await self.streams.yield(urls, logger: self.logger) }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@
/// Initializes a `Sublimation` instance with the provided parameters.
///
/// - Parameters:
/// - bindingConfiguration: A configuration with addresses, port and tls configuration.
/// - name: Service name.
/// - type: Service type.
/// - listenerParameters: The network parameters to use for the listener. Default is `.tcp`.
/// - serviceType: The Bonjour service type. Default is `BonjourSublimatory.httpTCPServiceType`.
/// - maximumCount: The maximum number of connections. Default is `nil`.
/// - addresses: A closure that asynchronously returns a list of addresses.
/// - addressFilter: A closure that filters the addresses. Default is `String.isIPv4NotLocalhost(_:)`.
///
public convenience init(
bindingConfiguration: BindingConfiguration,
name: String = BonjourSublimatory.defaultName,
Expand Down
1 change: 1 addition & 0 deletions Packages/SublimationNgrok/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ let package = Package(
name: "SublimationNgrok",
dependencies: [
"SublimationTunnel",
"SublimationKVdb",
.product(name: "Ngrokit", package: "Ngrokit")
],
swiftSettings: swiftSettings
Expand Down
13 changes: 7 additions & 6 deletions Packages/SublimationNgrok/Sources/SublimationKVdb/KVdb.swift
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,15 @@ public enum KVdb {
"/\(bucketName)/\(key)"
}

/// Constructs a URL for a given key in a bucket.
/// Constructs a URL for a given key in a bucket.
///
/// - Parameters:
/// - URLType: The type of URL to construct.
/// - key: The key for the value.
/// - bucketName: The name of the bucket.
/// - Parameters:
/// - _: The type of URL to construct.
/// - key: The key for the value.
/// - bucketName: The name of the bucket.
///
/// - Returns: The constructed URL.
///
/// - Returns: The constructed URL.
public static func construct<URLType: KVdbURLConstructable>(
_: URLType.Type,
forKey key: some Any,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,9 @@ public struct KVdbTunnelClient<Key: Sendable>: Sendable {

/// Retrieves the value associated with a key from a specific bucket.
///
/// - Parameter key: The key used to access the value.
/// - Parameter bucketName: The name of the bucket where the value is stored.
/// - Parameters:
/// - key: The key used to access the value.
/// - bucketName: The name of the bucket where the value is stored.
///
/// - Throws: `NgrokServerError.invalidURL` if the retrieved URL is invalid.
///
Expand All @@ -76,9 +77,10 @@ public struct KVdbTunnelClient<Key: Sendable>: Sendable {

/// Saves a value with a key in a specific bucket.
///
/// - Parameter value: The URL value to save.
/// - Parameter key: The key used to associate the value.
/// - Parameter bucketName: The name of the bucket where the value will be stored.
/// - Parameters:
/// - value: The URL value to save.
/// - key: The key used to associate the value.
/// - bucketName: The name of the bucket where the value will be stored.
///
/// - Throws: `NgrokServerError.cantSaveTunnel` if the tunnel cannot be saved.
public func saveValue(_ value: URL, withKey key: Key, inBucket bucketName: String) async throws {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,5 @@ public protocol KVdbURLConstructable {
/// - Parameters:
/// - kvDBBase: The base URL of the key-value database.
/// - keyBucketPath: The path to the key bucket.
///
/// - Returns: An instance of the conforming type.
init(kvDBBase: String, keyBucketPath: String)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
//
// TunnelSublimatory.swift
// SublimationNgrok
//
// Created by Leo Dion.
// Copyright © 2024 BrightDigit.
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the “Software”), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//

public import Foundation
public import Ngrokit
public import OpenAPIRuntime
public import SublimationCore
import SublimationKVdb
public import SublimationTunnel

#if os(macOS)
extension TunnelSublimatory {
/// Initializes the Sublimation lifecycle handler with default values for macOS.
///
/// - Parameters:
/// - ngrokPath: The path to the Ngrok executable.
/// - bucketName: The name of the bucket for the tunnel repository.
/// - key: The key for the tunnel repository.
///
/// - Note: This initializer is only available on macOS.
///
/// - SeeAlso: `KVdbTunnelRepositoryFactory`
/// - SeeAlso: `NgrokCLIAPIServerFactory`
public init<Key>(
ngrokPath: String,
bucketName: String,
key: Key,
application: @Sendable @escaping () -> any Application,
isConnectionRefused: @escaping @Sendable (ClientError) -> Bool,
ngrokClient: @escaping @Sendable () -> NgrokClient
) async
where
WritableTunnelRepositoryFactoryType == TunnelBucketRepositoryFactory<Key>,
TunnelServerFactoryType == NgrokCLIAPIServerFactory<ProcessableProcess>,
WritableTunnelRepositoryFactoryType.TunnelRepositoryType.Key == Key
{
await self.init(
factory: NgrokCLIAPIServerFactory(ngrokPath: ngrokPath, ngrokClient: ngrokClient),
repoFactory: TunnelBucketRepositoryFactory(bucketName: bucketName),
key: key,
application: application,
repoClientFactory: { application in
KVdbTunnelClient(
keyType: WritableTunnelRepositoryFactoryType.TunnelRepositoryType.Key.self,
get: { try await application().get(from: $0) },
post: { try await application().post(to: $0, body: $1) }
)
},
isConnectionRefused: isConnectionRefused
)
}

/// Initializes the Sublimation lifecycle handler with default values for macOS.
///
/// - Parameters:
/// - ngrokPath: The path to the Ngrok executable.
/// - bucketName: The name of the bucket for the tunnel repository.
/// - key: The key for the tunnel repository.
///
/// - Note: This initializer is only available on macOS.
///
/// - SeeAlso: `KVdbTunnelRepositoryFactory`
/// - SeeAlso: `NgrokCLIAPIServerFactory`
public init<Key>(
ngrokPath: String,
bucketName: String,
key: Key,
application: @Sendable @escaping () -> any Application,
isConnectionRefused: @escaping @Sendable (ClientError) -> Bool,
transport: any ClientTransport,
serverURL: URL? = nil
) async
where
TunnelServerFactoryType == NgrokCLIAPIServerFactory<ProcessableProcess>,
WritableTunnelRepositoryFactoryType == TunnelBucketRepositoryFactory<Key>
{
await self.init(
ngrokPath: ngrokPath,
bucketName: bucketName,
key: key,
application: application,
isConnectionRefused: isConnectionRefused,
ngrokClient: { NgrokClient(transport: transport, serverURL: serverURL) }
)
}
}

#endif
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,6 @@ public protocol TunnelRepositoryFactory: Sendable {
///
/// - Returns: A tunnel repository.
///
/// - Throws: An error if the setup fails.
///
/// - Note: The `TunnelClientType` must have a `Key` type
/// that matches the `Key` type of the `TunnelRepositoryType`.
func setupClient<TunnelClientType: TunnelClient>(_ client: TunnelClientType)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,15 @@ public actor TunnelSublimatory<
private var server: TunnelServerFactoryType.Configuration.Server!

private nonisolated let isConnectionRefused: @Sendable (ConnectionErrorType) -> Bool
/// Initializes the Sublimation lifecycle handler.
/// Initializes the Sublimation lifecycle handler.
///
/// - Parameters:
/// - factory: The factory for creating an Ngrok server.
/// - repoFactory: The factory for creating a writable tunnel repository.
/// - key: The key for the tunnel repository.
/// - Parameters:
/// - factory: The factory for creating an Ngrok server.
/// - repoFactory: The factory for creating a writable tunnel repository.
/// - key: The key for the tunnel repository.
/// - application: Returns the Application to use.
/// - repoClientFactory: Takes an Application and returns a client for the tunnel.
/// - isConnectionRefused: Whether the error is just connection refused because it's not active.
public init(
factory: TunnelServerFactoryType,
repoFactory: WritableTunnelRepositoryFactoryType,
Expand Down Expand Up @@ -110,8 +113,7 @@ public actor TunnelSublimatory<

/// Saves the tunnel URL to the tunnel repository.
///
/// - Parameters:
/// - tunnel: The tunnel to save.
/// - Parameter tunnel: The tunnel to save.
///
/// - Note: This method is asynchronous.
///
Expand All @@ -129,8 +131,7 @@ public actor TunnelSublimatory<

/// Handles an error that occurred during tunnel operation.
///
/// - Parameters:
/// - error: The error that occurred.
/// - Parameter error: The error that occurred.
///
/// - Note: This method is asynchronous.
private func onError(_ error: any Error) async {
Expand All @@ -140,7 +141,7 @@ public actor TunnelSublimatory<
/// Called when an Ngrok server updates a tunnel.
///
/// - Parameters:
/// - server: The Ngrok server.
/// - _: The Ngrok server.
/// - tunnel: The updated tunnel.
///
/// - Note: This method is nonisolated.
Expand All @@ -154,7 +155,7 @@ public actor TunnelSublimatory<
/// Called when an error occurs in the Ngrok server.
///
/// - Parameters:
/// - server: The Ngrok server.
/// - _: The Ngrok server.
/// - error: The error that occurred.
///
/// - Note: This method is nonisolated.
Expand Down

0 comments on commit bb0b629

Please sign in to comment.