Introduce APIClient/AuthAPI, complete login with multi-account selection, and polish the login card UI with shadow and keyboard dismiss. Co-authored-by: Cursor <cursoragent@cursor.com>
54 lines
1.4 KiB
Swift
54 lines
1.4 KiB
Swift
//
|
||
// APIRequest.swift
|
||
// suixinkan
|
||
//
|
||
|
||
import Foundation
|
||
|
||
/// HTTP 方法实体,限制网络层支持的请求方法。
|
||
enum HTTPMethod: String {
|
||
case get = "GET"
|
||
case post = "POST"
|
||
case put = "PUT"
|
||
case delete = "DELETE"
|
||
}
|
||
|
||
/// 强类型 API 请求实体,描述一次请求的方法、路径、参数、Header 和响应类型。
|
||
nonisolated struct APIRequest<Response: Decodable> {
|
||
var method: HTTPMethod
|
||
var path: String
|
||
var queryItems: [URLQueryItem]
|
||
var headers: [String: String]
|
||
var body: AnyEncodable?
|
||
|
||
/// 创建一个 API 请求,并把可编码请求体擦除为统一的 AnyEncodable。
|
||
init<Body: Encodable>(
|
||
method: HTTPMethod,
|
||
path: String,
|
||
queryItems: [URLQueryItem] = [],
|
||
headers: [String: String] = [:],
|
||
body: Body? = Optional<EmptyPayload>.none
|
||
) {
|
||
self.method = method
|
||
self.path = path
|
||
self.queryItems = queryItems
|
||
self.headers = headers
|
||
self.body = body.map(AnyEncodable.init)
|
||
}
|
||
}
|
||
|
||
/// Encodable 类型擦除包装器,用于在 APIRequest 中保存任意请求体。
|
||
nonisolated struct AnyEncodable: Encodable, Sendable {
|
||
private let encodeValue: @Sendable (Encoder) throws -> Void
|
||
|
||
init<Value: Encodable>(_ value: Value) {
|
||
encodeValue = { encoder in
|
||
try value.encode(to: encoder)
|
||
}
|
||
}
|
||
|
||
func encode(to encoder: Encoder) throws {
|
||
try encodeValue(encoder)
|
||
}
|
||
}
|