From 32ad6cab8d58d99ebd8a28e8fa6e6f4e587cb1e5 Mon Sep 17 00:00:00 2001 From: Christian Cleberg Date: Tue, 17 Mar 2026 23:19:43 -0500 Subject: v1.0 --- Hutch/Networking/GraphQLRequest.swift | 45 +++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 Hutch/Networking/GraphQLRequest.swift (limited to 'Hutch/Networking/GraphQLRequest.swift') diff --git a/Hutch/Networking/GraphQLRequest.swift b/Hutch/Networking/GraphQLRequest.swift new file mode 100644 index 0000000..bce7b40 --- /dev/null +++ b/Hutch/Networking/GraphQLRequest.swift @@ -0,0 +1,45 @@ +import Foundation + +/// The JSON body sent with every GraphQL request. +struct GraphQLRequestBody: Encodable, Sendable { + let query: String + let variables: [String: AnyCodable]? +} + +/// The top-level shape of every GraphQL response. +struct GraphQLResponse: Decodable { + let data: T? + let errors: [GraphQLError]? +} + +// MARK: - AnyCodable + +/// A type-erased `Codable` wrapper so callers can pass `[String: Any]` variables +/// without losing type information at the encoding boundary. +struct AnyCodable: Sendable, Encodable { + let value: any Sendable + + init(_ value: any Sendable) { + self.value = value + } + + func encode(to encoder: any Encoder) throws { + var container = encoder.singleValueContainer() + switch value { + case let v as String: + try container.encode(v) + case let v as Int: + try container.encode(v) + case let v as Double: + try container.encode(v) + case let v as Bool: + try container.encode(v) + case let v as [any Sendable]: + try container.encode(v.map { AnyCodable($0) }) + case let v as [String: any Sendable]: + try container.encode(v.mapValues { AnyCodable($0) }) + default: + try container.encodeNil() + } + } +} -- cgit v1.2.3