import Dependencies import DependenciesMacros import Foundation import ShellClient public extension DependencyValues { var cliClient: CliClient { get { self[CliClient.self] } set { self[CliClient.self] = newValue } } } @DependencyClient public struct CliClient: Sendable { public var runCommand: @Sendable ([String], Bool, ShellCommand.Shell) async throws -> Void public func runCommand( quiet: Bool, shell: ShellCommand.Shell, _ args: [String] ) async throws { try await runCommand(args, quiet, shell) } public func runCommand( quiet: Bool, shell: ShellCommand.Shell, _ args: String... ) async throws { try await runCommand(args, quiet, shell) } } extension CliClient: DependencyKey { public static func live( env: [String: String] ) -> Self { @Dependency(\.logger) var logger return .init { args, quiet, shell in @Dependency(\.asyncShellClient) var shellClient if !quiet { try await shellClient.foreground(.init( shell: shell, environment: ProcessInfo.processInfo.environment, in: nil, args )) } else { try await shellClient.background(.init( shell: shell, environment: ProcessInfo.processInfo.environment, in: nil, args )) } } } public static var liveValue: CliClient { .live(env: ProcessInfo.processInfo.environment) } public static let testValue: CliClient = Self() } enum CliClientError: Error { case fileExistsAtPath(String) case vaultFileNotFound } private let jsonEncoder: JSONEncoder = { var encoder = JSONEncoder() encoder.outputFormatting = [.prettyPrinted, .withoutEscapingSlashes] return encoder }()