A Kotlin MPP library that can be used as a foundation to build clients (SDKs) for HTTP based APIs.
📝 | This library is still in active development and may break compatibility in future releases |
---|
Include in your dependencies
dependencies {
implementation "com.github.RedCrewOS.api-sdk-creator-mpp:http-api-client:http-api-client_v0.5.0"
}
TODO
To understand the motivation behind building this library, and the design decisions, see the original motivation doc
This is a Kotlin port of the JS library. A lot of the type and function names have been carried over, however there are some important implementation differences.
In order to have the ability to return errors and data from functions, and having access to ADTs in Kotlin, a library called Arrow is used. The Arrow docs have a good intro to Monads and error handling with Arrow.
Arrow and thus this library uses Kotlin Coroutines to achieve concurrency. Because of that, most of the functions in this library are suspendable which allows non-blocking functions to be composed together. That means that users of the functions in this library will either have to be suspending functions, or launch a new Coroutine in order to use the functions.
SDK developers will have to decide how to allow client applications to decide the Dispatcher that the Coroutines use in order to be executed on the correct thread.
This is very important in UI applications (eg: Android apps) where IO work should be performed on the IO Dispatcher so that a background thread is used, to prevent the UI being blocked on IO.
It's worth noting that because the functions in this library never throw, exceptions in Coroutines can't be
silently dropped
and will always be returned in an Either.Left
However if SDK developers choose the throw an exception, application
developers will still have to make sure that they can handle exceptions thrown within Coroutines properly.
While Crocks (in Javascript) has the Async
monad to represent chainable units of concurrent work, Arrow uses Kotlin
suspend
functions instead of a Monad. As a result, ideas from the JS version
of api-sdk-creator had to be reworked to fit with this paradigm.
One of the consequences of using suspend
functions is that the orthodox Monad methods of map
chain
/flatMap
etc
can't be used. Thankfully Arrow offers monad comprehensions
which allow us to write code that composes monads together (like Crock's chain
ing). While the code reads like imperative
code, monad comprehensions will exit early if the result of bind
ing a result is not mappable, etc. This preserves the
monad semantics we want (Option
, Either
, etc) in code that has a lot less boilerplate, which is nice in a statically
typed language.
Because Kotlin is a statically typed language it is does not support currying lambdas with generic type parameters where
the generic type is not part of the entire function signature. For example,
fun gsonUnmarshaller(gson: Gson): (KClass<T>) -> Unmarshaller<T>
does not compile.
We overcome this by using invoke operator overloading.
See the docs on GenericTypeCurriedFunction
for more details on the implementation.
Read the 📘 reference docs
See the platform examples