Skip to content

Commit 8217b5e

Browse files
authored
Merge pull request #24 from haroldadmin/docs
Add project documentation website
2 parents fb24fe6 + beb5b0d commit 8217b5e

File tree

10 files changed

+419
-4
lines changed

10 files changed

+419
-4
lines changed

.github/workflows/docs.yml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
name: Docs
2+
3+
on: [release]
4+
5+
jobs:
6+
build:
7+
runs-on: ubuntu-latest
8+
steps:
9+
- uses: actions/checkout@v2
10+
11+
- name: Setup JDK 1.8
12+
uses: actions/setup-java@v1
13+
with:
14+
java-version: 1.8
15+
16+
- name: Set up Python
17+
uses: actions/setup-python@v2
18+
with:
19+
python-version: '3.8'
20+
21+
- name: Setup Python dependencies
22+
run: pip3 install --upgrade pip && pip3 install -r ./docs/requirements.txt
23+
24+
- name: Generate Docs
25+
run: gradle dokkaGfm
26+
27+
- name: Cleanup existing docs
28+
run: rm -rf docs/docs/docs/api && mkdir docs/docs/docs/api
29+
30+
- name: Copy generated docs
31+
run: cp -r build/dokka/coroutines-network-response-adapter/* docs/docs/docs/api
32+
33+
- name: Build mkdocs website
34+
run: cd ./docs/docs && mkdocs build --clean --verbose
35+
36+
- name: Deploy mkdocs website
37+
uses: peaceiris/actions-gh-pages@v3
38+
with:
39+
github_token: ${{ secrets.GITHUB_TOKEN }}
40+
publish_dir: docs/docs/site
41+
publish_branch: gh-pages

build.gradle.kts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
plugins {
2-
id("org.jetbrains.kotlin.jvm").version("1.3.72")
2+
id("org.jetbrains.kotlin.jvm").version("1.4.10")
3+
id("org.jetbrains.dokka") version "1.4.10"
34
maven
45
}
56

@@ -19,9 +20,9 @@ tasks.wrapper {
1920

2021
dependencies {
2122

22-
val coroutinesVersion = "1.3.6"
23-
val retrofitVersion = "2.8.1"
24-
val okHttpVersion = "4.6.0"
23+
val coroutinesVersion = "1.3.9"
24+
val retrofitVersion = "2.9.0"
25+
val okHttpVersion = "4.8.1"
2526

2627
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
2728
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion")
@@ -34,3 +35,7 @@ dependencies {
3435
testImplementation("com.squareup.moshi:moshi-kotlin:1.9.2")
3536
testImplementation("com.squareup.retrofit2:converter-moshi:$retrofitVersion")
3637
}
38+
39+
tasks.dokkaGfm.configure {
40+
outputDirectory.set(buildDir.resolve("dokka"))
41+
}

docs/.gitignore

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
# Byte-compiled / optimized / DLL files
2+
__pycache__/
3+
*.py[cod]
4+
*$py.class
5+
6+
# C extensions
7+
*.so
8+
9+
# Distribution / packaging
10+
.Python
11+
build/
12+
develop-eggs/
13+
dist/
14+
downloads/
15+
eggs/
16+
.eggs/
17+
lib/
18+
lib64/
19+
parts/
20+
sdist/
21+
var/
22+
wheels/
23+
share/python-wheels/
24+
*.egg-info/
25+
.installed.cfg
26+
*.egg
27+
MANIFEST
28+
29+
# PyInstaller
30+
# Usually these files are written by a python script from a template
31+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
32+
*.manifest
33+
*.spec
34+
35+
# Installer logs
36+
pip-log.txt
37+
pip-delete-this-directory.txt
38+
39+
# Unit test / coverage reports
40+
htmlcov/
41+
.tox/
42+
.nox/
43+
.coverage
44+
.coverage.*
45+
.cache
46+
nosetests.xml
47+
coverage.xml
48+
*.cover
49+
*.py,cover
50+
.hypothesis/
51+
.pytest_cache/
52+
cover/
53+
54+
# Translations
55+
*.mo
56+
*.pot
57+
58+
# Django stuff:
59+
*.log
60+
local_settings.py
61+
db.sqlite3
62+
db.sqlite3-journal
63+
64+
# Flask stuff:
65+
instance/
66+
.webassets-cache
67+
68+
# Scrapy stuff:
69+
.scrapy
70+
71+
# Sphinx documentation
72+
docs/_build/
73+
74+
# PyBuilder
75+
.pybuilder/
76+
target/
77+
78+
# Jupyter Notebook
79+
.ipynb_checkpoints
80+
81+
# IPython
82+
profile_default/
83+
ipython_config.py
84+
85+
# pyenv
86+
# For a library or package, you might want to ignore these files since the code is
87+
# intended to run in multiple environments; otherwise, check them in:
88+
# .python-version
89+
90+
# pipenv
91+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
93+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
94+
# install all needed dependencies.
95+
#Pipfile.lock
96+
97+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
98+
__pypackages__/
99+
100+
# Celery stuff
101+
celerybeat-schedule
102+
celerybeat.pid
103+
104+
# SageMath parsed files
105+
*.sage.py
106+
107+
# Environments
108+
.env
109+
.venv
110+
env/
111+
venv/
112+
ENV/
113+
env.bak/
114+
venv.bak/
115+
116+
# Spyder project settings
117+
.spyderproject
118+
.spyproject
119+
120+
# Rope project settings
121+
.ropeproject
122+
123+
# mkdocs documentation
124+
/site
125+
126+
# mypy
127+
.mypy_cache/
128+
.dmypy.json
129+
dmypy.json
130+
131+
# Pyre type checker
132+
.pyre/
133+
134+
# pytype static type analyzer
135+
.pytype/
136+
137+
# Cython debug symbols
138+
cython_debug/

docs/docs/docs/benefits.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Benefits
2+
3+
Modelling errors as a part of your state is a recommended practice. This library helps you deal with scenarios where you can successfully recover from errors, and extract meaningful information from them too!
4+
5+
- `NetworkResponseAdapter` provides a much cleaner solution than Retrofit's built in `Call` type for dealing with errors.`Call` throws an exception on any kind of an error, leaving it up to you to catch it and parse it manually to figure out what went wrong. `NetworkResponseAdapter` does all of that for you and returns the result in an easily consumable `NetworkResponse` subtype.
6+
7+
- The RxJava retrofit adapter treats non 2xx response codes as errors, which seems silly in the context of Rx where errors terminate streams. Also, just like the `Call<T>` type, it makes you deal with all types of errors in an `onError` callback, where you have to manually parse it to find out exactly what went wrong.
8+
9+
- Using the `Response` class provided by Retrofit is cumbersome, as you have to manually parse error bodies with it.

docs/docs/docs/extensions.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Extensions
2+
3+
## Overloaded Invoke operator
4+
5+
`NetworkResponse` also has an overloaded `invoke` operator. It returns the underlying data if the response is `NetworkResponse.Success`, or null otherwise.
6+
7+
```kotlin
8+
val usersResponse = usersRepo.getUsers().await()
9+
println(usersResponse() ?: "No users were found")
10+
```
11+
12+
## Retrying network requests
13+
14+
The `executeWithRetry` method shipped with this library can help you retry a network request without any boilerplate:
15+
16+
```kotlin
17+
suspend fun fetchDetails() {
18+
val response = executeWithRetry(times = 5) {
19+
api.getDetails()
20+
}
21+
}
22+
```

docs/docs/docs/index.md

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# NetworkResponseAdapter
2+
3+
[![Release Version](https://jitpack.io/v/haroldadmin/NetworkResponseAdapter.svg)](https://jitpack.io/#haroldadmin/NetworkResponseAdapter)
4+
[![Build Status](https://github.com/haroldadmin/networkresponseadapter/workflows/CI/badge.svg)](https://github.com/haroldadmin/networkresponseadapter/actions)
5+
6+
## Introduction
7+
8+
This library provides a Retrofit call adapter to handle errors as a part of state. It helps you write cleaner code for network requests by treating errors as values, instead of exceptions.
9+
10+
## Network Response
11+
12+
`NetworkResponse<S, E>` is a Kotlin sealed class with the following states:
13+
14+
1. Success: Represents successful responses (2xx response codes)
15+
2. ServerError: Represents Server errors
16+
3. NetworkError: Represents connectivity errors
17+
4. UnknownError: Represents every other kind of error which can not be classified as an API error or a network problem (eg JSON deserialization exceptions)
18+
19+
It is generic on two types: a response (`S`), and an error (`E`). The response type is your Java/Kotlin representation of the API response, while the error type represents the error response sent by the API.
20+
21+
## Example
22+
23+
```kotlin
24+
data class DetailsResponse(
25+
val details: String
26+
)
27+
28+
data class DetailsError(
29+
val errorMessage: String
30+
)
31+
32+
interface Api {
33+
@Get("/details)
34+
suspend fun details(): NetworkResponse<DetailsResponse, DetailsError>
35+
}
36+
37+
class ViewModel {
38+
suspend fun fetchDetails() {
39+
when (val response = api.details()) {
40+
is NetworkResponse.Success -> handleSuccess(response.body)
41+
is NetworkResponse.ServerError -> handleServerError(response.code)
42+
is NetworkResponse.NetworkError -> handleNetworkError(response.error)
43+
is NetworkResponse.UnknownError -> handleUnknownError(response.error)
44+
}
45+
}
46+
}
47+
```
48+
49+
## Installation
50+
51+
Add the Jitpack repository to your list of repositories:
52+
53+
```groovy
54+
allprojects {
55+
repositories {
56+
maven { url 'https://jitpack.io' }
57+
}
58+
}
59+
```
60+
61+
And then add the dependency in your gradle file:
62+
63+
```groovy
64+
dependencies {
65+
implementation "com.github.haroldadmin:NetworkResponseAdapter:(latest-version)"
66+
}
67+
```
68+
69+
<!-- prettier-ignore-start -->
70+
!!! note
71+
This library uses OkHttp 4, which requires Android API version 21+ and Java 8+.
72+
<!-- prettier-ignore-end -->
73+
74+
## License
75+
76+
```text
77+
Licensed under the Apache License, Version 2.0 (the "License");
78+
you may not use this file except in compliance with the License.
79+
You may obtain a copy of the License at
80+
81+
http://www.apache.org/licenses/LICENSE-2.0
82+
83+
Unless required by applicable law or agreed to in writing, software
84+
distributed under the License is distributed on an "AS IS" BASIS,
85+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
86+
See the License for the specific language governing permissions and
87+
limitations under the License.
88+
```

docs/docs/docs/special-cases.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Special Cases
2+
3+
## Handling empty response bodies
4+
5+
This library assumes that your server returns a parse-able response body even if the request fails. Empty bodies are treated as a server error. However, some operations rely solely on the returned response code. In such cases, the body is usually empty. Such endpoints must use `Unit` as the response type:
6+
7+
```kotlin
8+
suspend fun updateStatusOnServer(): NetworkResponse<Unit, ErrorType>
9+
```
10+
11+
## Handling primitive responses
12+
13+
The most common format for sending data over the wire is JSON. However, not all responses need JSON objects as sometimes primitive string suffice. To support a wide variety of response types, Retrofit supports adding custom converters. One such converter is the [Scalars Converter](https://github.com/square/retrofit/tree/master/retrofit-converters/scalars) which can handle primitive response types.
14+
15+
To use it, use a primitive as your response type:
16+
17+
```kotlin
18+
interface Api {
19+
@GET("/details")
20+
suspend fun details(): NetworkResponse<String, String>
21+
}
22+
```
23+
24+
And then make sure that the Scalars converter is added to Retrofit before the JSON converter:
25+
26+
```kotlin
27+
val retrofit = Retrofit.Builder()
28+
.addCallAdapterFactory(NetworkResponseAdapterFactory())
29+
.addConverterFactory(ScalarsConverterFactory.create())
30+
.addConverterFactory(MoshiConverterFactory.create(moshi))
31+
.baseUrl("...")
32+
.build()
33+
```

0 commit comments

Comments
 (0)