This library provides the approach to API contract definition in the Retrofit-like fashion on Swift.
It gives possibility to define API in this way:
finalclassSchedulesApi:ApiDomain{@Get("/api/v1/schedule")vargetSchedules:(GetSchedulesRequest)asyncthrows->GetSchedulesResponse@Put("/api/v1/schedule")varcreateSchedule:(CreateScheduleRequest)asyncthrows->Empty@Post("/api/v1/schedule/{schedule_id}")varupdateSchedule:(UpdateScheduleRequest)asyncthrows->UpdateScheduleResponse@Delete("/api/v1/schedule/{schedule_id}")vardeleteSchedule:(DeleteScheduleRequest)asyncthrows->Either<DeleteScheduleResponse,DeleteScheduleErrorResponse>}*Request types provide more details on endpoints contracts, namely define parameters and their mapping to the HTTP params - Query, Header, Path, JsonBody, FormParam, FormFile:
structGetSchedulesRequest{@Queryvarpage:Int@Query("limit")varschedulesPerPage:Int=0@Header("X-Account-Id")varaccountId:String=""}structCreateScheduleRequest{@Header("X-Account-Id")varaccountId:String=""@JsonBodyvarscheduleBody:Schedule}structDeleteScheduleRequest{@Path("schedule_id")varScheduleId:String=""@Header("X-Account-Id")varaccountId:String=""}structSpeechToTextApiRequest{@FormParam("model_id")varmodelId=""@FormParam("language_code")varlanguageCode=""@FormParam("tag_audio_events")vartagAudioEvents=false@FormParam("num_speakers")varnumSpeakers=1@FormFile("file")varrecording=.empty
}Usage is quite simple:
lettransport:HttpTransport=....letapi=SchedulesApi(transport: transport)letrequest=GetSchedulesRequest(page:1, schedulesPerPage:30, accountId:"acc_id")letresponse=tryawait api.getSchedules(request)Sending multipart form:
letrequest=ElevenLabsApi.SpeechToTextApiRequest(
modelId:"scribe_v1",
languageCode: languageCode,
tagAudioEvents:false,
numSpeakers:1,
recording:.init(fileName:"recording.caf", mimeType:"audio/x-caf", content: recording))lettranscribedText=tryawait api.speechToText(request).textAdditionally responses can be mocked in a straightforward and self-describing way:
api.getSchedules ={ _ inGetSchedulesResponse(....)}
api.deleteSchedule ={ _ inthrowURLError(.userAuthenticationRequired)}
api.deleteSchedule ={ _ in.errorResponse(DeleteScheduleErrorResponse(errorMessage:"Schedule not found"))}ApiDomain in the simplest case can be implemented as follow:
classApiDomain:Domain{overrideinit(transport:HttpTransport){
super.init(transport: transport)
transport.setConfiguration(scheme:"https", host:"rest.bandsintown.com", sharedHeaders:nil)}}More complex solutions can include, for example, session token management.
HttpTransport is the protocol describing HTTP network communication layer.
publicprotocolHttpTransport{func setConfiguration(scheme:String, host:String, sharedHeaders:[String:String]?)func sendRequest(with params:HttpRequestParams)asyncthrows->HttpOperationResult}DemoProject contains simple implementation based on the UrlSession, but you can provide yours depending on your needs.
Supported HTTP methods:
@Delete@Get@Head@Patch@Post@Put
Supported parameter types:
@Header@Path@Query@JsonBody@FormParam@FormFile
By default parameter name is derived from the variable name, but it can be customized:
@Header("X-Account-Id")varaccountId:String=""Supported response types:
- any type conforming to
Decodable Either<Response: Decodable, ErrorResponse: Decodable>Empty
Either type allows to get either success or error response.
Response mocking. You can easily mock response by assigning directly to the api's endpoint definition:
api.deleteSchedule ={ _ in.errorResponse(DeleteScheduleErrorResponse(errorMessage:"Schedule not found"))}If you're working with a project in Xcode RetroSwift can be easily integrated:
- In Xcode, select
File > Add Packages... - Or go to the project's settings, select your project from the list, go to the
Package Dependenciesand click+button - Specify the Repository:
https://github.com/level-two/RetroSwift - Go to the Target, on
Generaltab findFrameworks, Libraries and Embedded contentsection, click '+' and add RetroSwift library as a dependency
To use this library in a SwiftPM project, add the following line to the dependencies in your Package.swift file:
.package(url:"https://github.com/level-two/RetroSwift", from:"0.0.1"),and include it as a dependency for your target:
.target(...
dependencies:["RetroSwift",],...),Finally, add import RetroSwift to your source code.