New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
APIInterface
Protocol
#49
Conversation
Hey @LePips. I have a couple of potential options on how to design it. 1. Using a factory method: extension APIClient {
// Returns an API client preconfigured to work with JellyfinAPI
static func jellyfin() -> APIClient {
}
} 2. Creating a custom client class that use As to the protocol, I'm not sure I fully understand how it helps in your case. I don't think it belongs to |
Hi 👋 , My basic wrapper is option 2 with an These wrappers with an underlying This is not necessary (after all, there are only 5 methods) but I thought to pitch it as I will be implementing this pattern anyways. The "evolution of the project" might not also foresee much networking interfacing changes. This can of course be ignored. actor JellyfinClient: APIInterface {
private var _apiClient: APIClient
init() {
// manually control the APIClientDelegate on the underlying APIClient
// per developer reasons
_apiClient = APIClient( ... )
}
@discardableResult
func send<T>(
_ request: Request<T>,
delegate: URLSessionDataDelegate? = nil,
configure: ((inout URLRequest) throws -> Void)? = nil
) async throws -> Response<T> where T : Decodable {
try _apiClient.send(request, delegate: delegate, configure: configure)
}
// Continue all other method wrappers that send to underlying _apiClient below.
// APIInterface conformance ensures that I will match all APIClient methods
// now and in the future.
}
// Usage
let jellyfinClient = JellyfinClient()
// Assuming CreateAPI generation
let itemsRequest = Paths.Items.getItems( ... )
jellyfinClient.send(itemsRequest) |
What about the "factory method" approach? It will ensure compatibility and there will be less maintenance for you in the long run.
Is there something missing in the existing configuration/delegate API? |
A wrapper allows developers to specify behavior with their API via additional properties or methods. Using my case as example: additional headers that include a unique device name, device identifier, and app version are required alongside the access token: Example excerpt of header dictionary creation: var header = "MediaBrowser "
header.append("Client=\"Jellyfin \(platform)\", ")
header.append("Device=\"\(deviceName)\", ")
header.append("DeviceId=\"\(platform)_\(UIDevice.vendorUUIDString)_\(String(Date().timeIntervalSince1970))\", ")
header.append("Version=\"\(appVersion ?? "0.0.1")\", ")
header.append("Token=\"\(accessToken)\"") Per my API, these headers are required for proper usage. To create this, I would have the property I haven't thought out the full architecture yet, but I could also add
No, as I am simply creating another layer above The layers are as such: This comment is probably longer than it should be and moreso justifies wrapper implementations for an underlying However again: this is a very small protocol and not necessary. Later addition: the most "ideal" way to achieve what I desire would have been the ability to have |
I think the approach with a wrapper makes total sense, especially if you want to add more APIs to it, such as As for the protocol, as you said yourself, I don't see how it's necessary. I'm going to close this MR if you don't mind. |
I don't mind at all, thank you for your time. |
Original issue with proposal:
APIInterface
name is open for a great improvement. I'm not too familiar with Swift on linux so I don't know if the OS check is appropriate, but included anyway.