Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .stats.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
configured_endpoints: 9
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/brand-dev%2Fbrand.dev-1ff30126e780960cb04d5855fb8e9227099f91e1a3293f656cfaad50e1d7eb1c.yml
openapi_spec_hash: 42c1034ce32cbe5410b124e577998de8
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/brand-dev%2Fbrand.dev-a41dc66f0aa3dbc9e8fe1da75f1101cbcb2fac79f728de42e4877cfe1bde3b6e.yml
openapi_spec_hash: 63c1a53e0899fb63a514dad395fd48f9
config_hash: 4b10254ea5b8e26ce632222b94a918aa
14 changes: 11 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ import com.branddev.api.client.okhttp.BrandDevOkHttpClient;

BrandDevClient client = BrandDevOkHttpClient.builder()
// Configures using the `branddev.apiKey` and `branddev.baseUrl` system properties
Or configures using the `BRAND_DEV_API_KEY` and `BRAND_DEV_BASE_URL` environment variables
// Or configures using the `BRAND_DEV_API_KEY` and `BRAND_DEV_BASE_URL` environment variables
.fromEnv()
.apiKey("My API Key")
.build();
Expand Down Expand Up @@ -231,6 +231,8 @@ The SDK throws custom unchecked exception types:

- [`BrandDevIoException`](brand-dev-java-core/src/main/kotlin/com/branddev/api/errors/BrandDevIoException.kt): I/O networking errors.

- [`BrandDevRetryableException`](brand-dev-java-core/src/main/kotlin/com/branddev/api/errors/BrandDevRetryableException.kt): Generic error indicating a failure that could be retried by the client.

- [`BrandDevInvalidDataException`](brand-dev-java-core/src/main/kotlin/com/branddev/api/errors/BrandDevInvalidDataException.kt): Failure to interpret successfully parsed data. For example, when accessing a property that's supposed to be required, but the API unexpectedly omitted it from the response.

- [`BrandDevException`](brand-dev-java-core/src/main/kotlin/com/branddev/api/errors/BrandDevException.kt): Base class for all exceptions. Most errors will result in one of the previously mentioned ones, but completely generic errors may be thrown using the base class.
Expand All @@ -251,6 +253,12 @@ Or to `debug` for more verbose logging:
$ export BRAND_DEV_LOG=debug
```

## ProGuard and R8

Although the SDK uses reflection, it is still usable with [ProGuard](https://github.com/Guardsquare/proguard) and [R8](https://developer.android.com/topic/performance/app-optimization/enable-app-optimization) because `brand-dev-java-core` is published with a [configuration file](brand-dev-java-core/src/main/resources/META-INF/proguard/brand-dev-java-core.pro) containing [keep rules](https://www.guardsquare.com/manual/configuration/usage).

ProGuard and R8 should automatically detect and use the published rules, but you can also manually copy the keep rules if necessary.

## Jackson

The SDK depends on [Jackson](https://github.com/FasterXML/jackson) for JSON serialization/deserialization. It is compatible with version 2.13.4 or higher, but depends on version 2.18.2 by default.
Expand All @@ -266,7 +274,7 @@ If the SDK threw an exception, but you're _certain_ the version is compatible, t

### Retries

The SDK automatically retries 2 times by default, with a short exponential backoff.
The SDK automatically retries 2 times by default, with a short exponential backoff between requests.

Only the following error types are retried:

Expand All @@ -276,7 +284,7 @@ Only the following error types are retried:
- 429 Rate Limit
- 5xx Internal

The API may also explicitly instruct the SDK to retry or not retry a response.
The API may also explicitly instruct the SDK to retry or not retry a request.

To set a custom number of retries, configure the client using the `maxRetries` method:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.branddev.api.client.BrandDevClientImpl
import com.branddev.api.core.ClientOptions
import com.branddev.api.core.Timeout
import com.branddev.api.core.http.Headers
import com.branddev.api.core.http.HttpClient
import com.branddev.api.core.http.QueryParams
import com.branddev.api.core.jsonMapper
import com.fasterxml.jackson.databind.json.JsonMapper
Expand All @@ -19,13 +20,22 @@ import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.X509TrustManager
import kotlin.jvm.optionals.getOrNull

/**
* A class that allows building an instance of [BrandDevClient] with [OkHttpClient] as the
* underlying [HttpClient].
*/
class BrandDevOkHttpClient private constructor() {

companion object {

/** Returns a mutable builder for constructing an instance of [BrandDevOkHttpClient]. */
/** Returns a mutable builder for constructing an instance of [BrandDevClient]. */
@JvmStatic fun builder() = Builder()

/**
* Returns a client configured using system properties and environment variables.
*
* @see ClientOptions.Builder.fromEnv
*/
@JvmStatic fun fromEnv(): BrandDevClient = builder().fromEnv().build()
}

Expand Down Expand Up @@ -102,19 +112,49 @@ class BrandDevOkHttpClient private constructor() {
clientOptions.checkJacksonVersionCompatibility(checkJacksonVersionCompatibility)
}

/**
* The Jackson JSON mapper to use for serializing and deserializing JSON.
*
* Defaults to [com.branddev.api.core.jsonMapper]. The default is usually sufficient and
* rarely needs to be overridden.
*/
fun jsonMapper(jsonMapper: JsonMapper) = apply { clientOptions.jsonMapper(jsonMapper) }

/**
* The clock to use for operations that require timing, like retries.
*
* This is primarily useful for using a fake clock in tests.
*
* Defaults to [Clock.systemUTC].
*/
fun clock(clock: Clock) = apply { clientOptions.clock(clock) }

/**
* The base URL to use for every request.
*
* Defaults to the production environment: `https://api.brand.dev/v1`.
*/
fun baseUrl(baseUrl: String?) = apply { clientOptions.baseUrl(baseUrl) }

/** Alias for calling [Builder.baseUrl] with `baseUrl.orElse(null)`. */
fun baseUrl(baseUrl: Optional<String>) = baseUrl(baseUrl.getOrNull())

/**
* Whether to call `validate` on every response before returning it.
*
* Defaults to false, which means the shape of the response will not be validated upfront.
* Instead, validation will only occur for the parts of the response that are accessed.
*/
fun responseValidation(responseValidation: Boolean) = apply {
clientOptions.responseValidation(responseValidation)
}

/**
* Sets the maximum time allowed for various parts of an HTTP call's lifecycle, excluding
* retries.
*
* Defaults to [Timeout.default].
*/
fun timeout(timeout: Timeout) = apply { clientOptions.timeout(timeout) }

/**
Expand All @@ -126,6 +166,21 @@ class BrandDevOkHttpClient private constructor() {
*/
fun timeout(timeout: Duration) = apply { clientOptions.timeout(timeout) }

/**
* The maximum number of times to retry failed requests, with a short exponential backoff
* between requests.
*
* Only the following error types are retried:
* - Connection errors (for example, due to a network connectivity problem)
* - 408 Request Timeout
* - 409 Conflict
* - 429 Rate Limit
* - 5xx Internal
*
* The API may also explicitly instruct the SDK to retry or not retry a request.
*
* Defaults to 2.
*/
fun maxRetries(maxRetries: Int) = apply { clientOptions.maxRetries(maxRetries) }

fun apiKey(apiKey: String) = apply { clientOptions.apiKey(apiKey) }
Expand Down Expand Up @@ -210,6 +265,11 @@ class BrandDevOkHttpClient private constructor() {
clientOptions.removeAllQueryParams(keys)
}

/**
* Updates configuration using system properties and environment variables.
*
* @see ClientOptions.Builder.fromEnv
*/
fun fromEnv() = apply { clientOptions.fromEnv() }

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.branddev.api.client.BrandDevClientAsyncImpl
import com.branddev.api.core.ClientOptions
import com.branddev.api.core.Timeout
import com.branddev.api.core.http.Headers
import com.branddev.api.core.http.HttpClient
import com.branddev.api.core.http.QueryParams
import com.branddev.api.core.jsonMapper
import com.fasterxml.jackson.databind.json.JsonMapper
Expand All @@ -19,15 +20,22 @@ import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.X509TrustManager
import kotlin.jvm.optionals.getOrNull

/**
* A class that allows building an instance of [BrandDevClientAsync] with [OkHttpClient] as the
* underlying [HttpClient].
*/
class BrandDevOkHttpClientAsync private constructor() {

companion object {

/**
* Returns a mutable builder for constructing an instance of [BrandDevOkHttpClientAsync].
*/
/** Returns a mutable builder for constructing an instance of [BrandDevClientAsync]. */
@JvmStatic fun builder() = Builder()

/**
* Returns a client configured using system properties and environment variables.
*
* @see ClientOptions.Builder.fromEnv
*/
@JvmStatic fun fromEnv(): BrandDevClientAsync = builder().fromEnv().build()
}

Expand Down Expand Up @@ -104,19 +112,49 @@ class BrandDevOkHttpClientAsync private constructor() {
clientOptions.checkJacksonVersionCompatibility(checkJacksonVersionCompatibility)
}

/**
* The Jackson JSON mapper to use for serializing and deserializing JSON.
*
* Defaults to [com.branddev.api.core.jsonMapper]. The default is usually sufficient and
* rarely needs to be overridden.
*/
fun jsonMapper(jsonMapper: JsonMapper) = apply { clientOptions.jsonMapper(jsonMapper) }

/**
* The clock to use for operations that require timing, like retries.
*
* This is primarily useful for using a fake clock in tests.
*
* Defaults to [Clock.systemUTC].
*/
fun clock(clock: Clock) = apply { clientOptions.clock(clock) }

/**
* The base URL to use for every request.
*
* Defaults to the production environment: `https://api.brand.dev/v1`.
*/
fun baseUrl(baseUrl: String?) = apply { clientOptions.baseUrl(baseUrl) }

/** Alias for calling [Builder.baseUrl] with `baseUrl.orElse(null)`. */
fun baseUrl(baseUrl: Optional<String>) = baseUrl(baseUrl.getOrNull())

/**
* Whether to call `validate` on every response before returning it.
*
* Defaults to false, which means the shape of the response will not be validated upfront.
* Instead, validation will only occur for the parts of the response that are accessed.
*/
fun responseValidation(responseValidation: Boolean) = apply {
clientOptions.responseValidation(responseValidation)
}

/**
* Sets the maximum time allowed for various parts of an HTTP call's lifecycle, excluding
* retries.
*
* Defaults to [Timeout.default].
*/
fun timeout(timeout: Timeout) = apply { clientOptions.timeout(timeout) }

/**
Expand All @@ -128,6 +166,21 @@ class BrandDevOkHttpClientAsync private constructor() {
*/
fun timeout(timeout: Duration) = apply { clientOptions.timeout(timeout) }

/**
* The maximum number of times to retry failed requests, with a short exponential backoff
* between requests.
*
* Only the following error types are retried:
* - Connection errors (for example, due to a network connectivity problem)
* - 408 Request Timeout
* - 409 Conflict
* - 429 Rate Limit
* - 5xx Internal
*
* The API may also explicitly instruct the SDK to retry or not retry a request.
*
* Defaults to 2.
*/
fun maxRetries(maxRetries: Int) = apply { clientOptions.maxRetries(maxRetries) }

fun apiKey(apiKey: String) = apply { clientOptions.apiKey(apiKey) }
Expand Down Expand Up @@ -212,6 +265,11 @@ class BrandDevOkHttpClientAsync private constructor() {
clientOptions.removeAllQueryParams(keys)
}

/**
* Updates configuration using system properties and environment variables.
*
* @see ClientOptions.Builder.fromEnv
*/
fun fromEnv() = apply { clientOptions.fromEnv() }

/**
Expand Down
Loading
Loading