From e145081e4ae5b862290944d7fb5b0c125522b0c0 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 12 Jun 2026 19:24:34 +0000 Subject: [PATCH 1/4] feat(digests): document digest REST endpoints in OpenAPI spec --- .stats.yml | 8 +- .../com/courier/client/CourierClient.kt | 5 + .../com/courier/client/CourierClientAsync.kt | 5 + .../courier/client/CourierClientAsyncImpl.kt | 14 + .../com/courier/client/CourierClientImpl.kt | 12 + .../courier/models/digests/DigestCategory.kt | 421 ++++++++++ .../courier/models/digests/DigestInstance.kt | 784 ++++++++++++++++++ .../digests/DigestInstanceListResponse.kt | 514 ++++++++++++ .../schedules/ScheduleListInstancesParams.kt | 244 ++++++ .../schedules/ScheduleReleaseParams.kt | 232 ++++++ .../services/async/DigestServiceAsync.kt | 41 + .../services/async/DigestServiceAsyncImpl.kt | 42 + .../async/digests/ScheduleServiceAsync.kt | 200 +++++ .../async/digests/ScheduleServiceAsyncImpl.kt | 126 +++ .../services/blocking/DigestService.kt | 37 + .../services/blocking/DigestServiceImpl.kt | 42 + .../blocking/digests/ScheduleService.kt | 195 +++++ .../blocking/digests/ScheduleServiceImpl.kt | 117 +++ .../models/digests/DigestCategoryTest.kt | 44 + .../digests/DigestInstanceListResponseTest.kt | 122 +++ .../models/digests/DigestInstanceTest.kt | 96 +++ .../ScheduleListInstancesParamsTest.kt | 52 ++ .../schedules/ScheduleReleaseParamsTest.kt | 23 + .../async/digests/ScheduleServiceAsyncTest.kt | 41 + .../blocking/digests/ScheduleServiceTest.kt | 38 + .../proguard/ProGuardCompatibilityTest.kt | 1 + 26 files changed, 3452 insertions(+), 4 deletions(-) create mode 100644 courier-java-core/src/main/kotlin/com/courier/models/digests/DigestCategory.kt create mode 100644 courier-java-core/src/main/kotlin/com/courier/models/digests/DigestInstance.kt create mode 100644 courier-java-core/src/main/kotlin/com/courier/models/digests/DigestInstanceListResponse.kt create mode 100644 courier-java-core/src/main/kotlin/com/courier/models/digests/schedules/ScheduleListInstancesParams.kt create mode 100644 courier-java-core/src/main/kotlin/com/courier/models/digests/schedules/ScheduleReleaseParams.kt create mode 100644 courier-java-core/src/main/kotlin/com/courier/services/async/DigestServiceAsync.kt create mode 100644 courier-java-core/src/main/kotlin/com/courier/services/async/DigestServiceAsyncImpl.kt create mode 100644 courier-java-core/src/main/kotlin/com/courier/services/async/digests/ScheduleServiceAsync.kt create mode 100644 courier-java-core/src/main/kotlin/com/courier/services/async/digests/ScheduleServiceAsyncImpl.kt create mode 100644 courier-java-core/src/main/kotlin/com/courier/services/blocking/DigestService.kt create mode 100644 courier-java-core/src/main/kotlin/com/courier/services/blocking/DigestServiceImpl.kt create mode 100644 courier-java-core/src/main/kotlin/com/courier/services/blocking/digests/ScheduleService.kt create mode 100644 courier-java-core/src/main/kotlin/com/courier/services/blocking/digests/ScheduleServiceImpl.kt create mode 100644 courier-java-core/src/test/kotlin/com/courier/models/digests/DigestCategoryTest.kt create mode 100644 courier-java-core/src/test/kotlin/com/courier/models/digests/DigestInstanceListResponseTest.kt create mode 100644 courier-java-core/src/test/kotlin/com/courier/models/digests/DigestInstanceTest.kt create mode 100644 courier-java-core/src/test/kotlin/com/courier/models/digests/schedules/ScheduleListInstancesParamsTest.kt create mode 100644 courier-java-core/src/test/kotlin/com/courier/models/digests/schedules/ScheduleReleaseParamsTest.kt create mode 100644 courier-java-core/src/test/kotlin/com/courier/services/async/digests/ScheduleServiceAsyncTest.kt create mode 100644 courier-java-core/src/test/kotlin/com/courier/services/blocking/digests/ScheduleServiceTest.kt diff --git a/.stats.yml b/.stats.yml index 1692babb..daedc5af 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 117 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/courier/courier-545ac9b590445e90e11113a1bdeb893a94389d69d95e0a7e5c6450bb15f5453a.yml -openapi_spec_hash: 9e243ec62800fb4a2e443eb6481afa30 -config_hash: 10bd597dd6cc89023541bc551b6532b8 +configured_endpoints: 119 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/courier/courier-2ffdd7412416851da17d4cf5b0b82ed842f730866bef1d76653f7ca83d5f622e.yml +openapi_spec_hash: e5296b102c88bb2226842167ba5d8731 +config_hash: 822a92efc80e63cdb2d496dbd6176620 diff --git a/courier-java-core/src/main/kotlin/com/courier/client/CourierClient.kt b/courier-java-core/src/main/kotlin/com/courier/client/CourierClient.kt index abd50135..5460c233 100644 --- a/courier-java-core/src/main/kotlin/com/courier/client/CourierClient.kt +++ b/courier-java-core/src/main/kotlin/com/courier/client/CourierClient.kt @@ -9,6 +9,7 @@ import com.courier.services.blocking.AuthService import com.courier.services.blocking.AutomationService import com.courier.services.blocking.BrandService import com.courier.services.blocking.BulkService +import com.courier.services.blocking.DigestService import com.courier.services.blocking.InboundService import com.courier.services.blocking.JourneyService import com.courier.services.blocking.ListService @@ -78,6 +79,8 @@ interface CourierClient { fun bulk(): BulkService + fun digests(): DigestService + fun inbound(): InboundService fun lists(): ListService @@ -139,6 +142,8 @@ interface CourierClient { fun bulk(): BulkService.WithRawResponse + fun digests(): DigestService.WithRawResponse + fun inbound(): InboundService.WithRawResponse fun lists(): ListService.WithRawResponse diff --git a/courier-java-core/src/main/kotlin/com/courier/client/CourierClientAsync.kt b/courier-java-core/src/main/kotlin/com/courier/client/CourierClientAsync.kt index 9746cfd8..68f03a77 100644 --- a/courier-java-core/src/main/kotlin/com/courier/client/CourierClientAsync.kt +++ b/courier-java-core/src/main/kotlin/com/courier/client/CourierClientAsync.kt @@ -9,6 +9,7 @@ import com.courier.services.async.AuthServiceAsync import com.courier.services.async.AutomationServiceAsync import com.courier.services.async.BrandServiceAsync import com.courier.services.async.BulkServiceAsync +import com.courier.services.async.DigestServiceAsync import com.courier.services.async.InboundServiceAsync import com.courier.services.async.JourneyServiceAsync import com.courier.services.async.ListServiceAsync @@ -78,6 +79,8 @@ interface CourierClientAsync { fun bulk(): BulkServiceAsync + fun digests(): DigestServiceAsync + fun inbound(): InboundServiceAsync fun lists(): ListServiceAsync @@ -143,6 +146,8 @@ interface CourierClientAsync { fun bulk(): BulkServiceAsync.WithRawResponse + fun digests(): DigestServiceAsync.WithRawResponse + fun inbound(): InboundServiceAsync.WithRawResponse fun lists(): ListServiceAsync.WithRawResponse diff --git a/courier-java-core/src/main/kotlin/com/courier/client/CourierClientAsyncImpl.kt b/courier-java-core/src/main/kotlin/com/courier/client/CourierClientAsyncImpl.kt index c3df7dd7..e23ede4f 100644 --- a/courier-java-core/src/main/kotlin/com/courier/client/CourierClientAsyncImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/client/CourierClientAsyncImpl.kt @@ -16,6 +16,8 @@ import com.courier.services.async.BrandServiceAsync import com.courier.services.async.BrandServiceAsyncImpl import com.courier.services.async.BulkServiceAsync import com.courier.services.async.BulkServiceAsyncImpl +import com.courier.services.async.DigestServiceAsync +import com.courier.services.async.DigestServiceAsyncImpl import com.courier.services.async.InboundServiceAsync import com.courier.services.async.InboundServiceAsyncImpl import com.courier.services.async.JourneyServiceAsync @@ -91,6 +93,10 @@ class CourierClientAsyncImpl(private val clientOptions: ClientOptions) : Courier private val bulk: BulkServiceAsync by lazy { BulkServiceAsyncImpl(clientOptionsWithUserAgent) } + private val digests: DigestServiceAsync by lazy { + DigestServiceAsyncImpl(clientOptionsWithUserAgent) + } + private val inbound: InboundServiceAsync by lazy { InboundServiceAsyncImpl(clientOptionsWithUserAgent) } @@ -152,6 +158,8 @@ class CourierClientAsyncImpl(private val clientOptions: ClientOptions) : Courier override fun bulk(): BulkServiceAsync = bulk + override fun digests(): DigestServiceAsync = digests + override fun inbound(): InboundServiceAsync = inbound override fun lists(): ListServiceAsync = lists @@ -213,6 +221,10 @@ class CourierClientAsyncImpl(private val clientOptions: ClientOptions) : Courier BulkServiceAsyncImpl.WithRawResponseImpl(clientOptions) } + private val digests: DigestServiceAsync.WithRawResponse by lazy { + DigestServiceAsyncImpl.WithRawResponseImpl(clientOptions) + } + private val inbound: InboundServiceAsync.WithRawResponse by lazy { InboundServiceAsyncImpl.WithRawResponseImpl(clientOptions) } @@ -278,6 +290,8 @@ class CourierClientAsyncImpl(private val clientOptions: ClientOptions) : Courier override fun bulk(): BulkServiceAsync.WithRawResponse = bulk + override fun digests(): DigestServiceAsync.WithRawResponse = digests + override fun inbound(): InboundServiceAsync.WithRawResponse = inbound override fun lists(): ListServiceAsync.WithRawResponse = lists diff --git a/courier-java-core/src/main/kotlin/com/courier/client/CourierClientImpl.kt b/courier-java-core/src/main/kotlin/com/courier/client/CourierClientImpl.kt index ff240280..82fa31c4 100644 --- a/courier-java-core/src/main/kotlin/com/courier/client/CourierClientImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/client/CourierClientImpl.kt @@ -16,6 +16,8 @@ import com.courier.services.blocking.BrandService import com.courier.services.blocking.BrandServiceImpl import com.courier.services.blocking.BulkService import com.courier.services.blocking.BulkServiceImpl +import com.courier.services.blocking.DigestService +import com.courier.services.blocking.DigestServiceImpl import com.courier.services.blocking.InboundService import com.courier.services.blocking.InboundServiceImpl import com.courier.services.blocking.JourneyService @@ -87,6 +89,8 @@ class CourierClientImpl(private val clientOptions: ClientOptions) : CourierClien private val bulk: BulkService by lazy { BulkServiceImpl(clientOptionsWithUserAgent) } + private val digests: DigestService by lazy { DigestServiceImpl(clientOptionsWithUserAgent) } + private val inbound: InboundService by lazy { InboundServiceImpl(clientOptionsWithUserAgent) } private val lists: ListService by lazy { ListServiceImpl(clientOptionsWithUserAgent) } @@ -138,6 +142,8 @@ class CourierClientImpl(private val clientOptions: ClientOptions) : CourierClien override fun bulk(): BulkService = bulk + override fun digests(): DigestService = digests + override fun inbound(): InboundService = inbound override fun lists(): ListService = lists @@ -199,6 +205,10 @@ class CourierClientImpl(private val clientOptions: ClientOptions) : CourierClien BulkServiceImpl.WithRawResponseImpl(clientOptions) } + private val digests: DigestService.WithRawResponse by lazy { + DigestServiceImpl.WithRawResponseImpl(clientOptions) + } + private val inbound: InboundService.WithRawResponse by lazy { InboundServiceImpl.WithRawResponseImpl(clientOptions) } @@ -264,6 +274,8 @@ class CourierClientImpl(private val clientOptions: ClientOptions) : CourierClien override fun bulk(): BulkService.WithRawResponse = bulk + override fun digests(): DigestService.WithRawResponse = digests + override fun inbound(): InboundService.WithRawResponse = inbound override fun lists(): ListService.WithRawResponse = lists diff --git a/courier-java-core/src/main/kotlin/com/courier/models/digests/DigestCategory.kt b/courier-java-core/src/main/kotlin/com/courier/models/digests/DigestCategory.kt new file mode 100644 index 00000000..d1b1cce8 --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/digests/DigestCategory.kt @@ -0,0 +1,421 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.digests + +import com.courier.core.Enum +import com.courier.core.ExcludeMissing +import com.courier.core.JsonField +import com.courier.core.JsonMissing +import com.courier.core.JsonValue +import com.courier.core.checkRequired +import com.courier.errors.CourierInvalidDataException +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +class DigestCategory +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val categoryKey: JsonField, + private val retain: JsonField, + private val sortKey: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("category_key") + @ExcludeMissing + categoryKey: JsonField = JsonMissing.of(), + @JsonProperty("retain") @ExcludeMissing retain: JsonField = JsonMissing.of(), + @JsonProperty("sort_key") @ExcludeMissing sortKey: JsonField = JsonMissing.of(), + ) : this(categoryKey, retain, sortKey, mutableMapOf()) + + /** + * The key that identifies the category within the digest. + * + * @throws CourierInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun categoryKey(): String = categoryKey.getRequired("category_key") + + /** + * Which events to keep when the number of events exceeds the retention limit for the category. + * + * @throws CourierInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun retain(): Retain = retain.getRequired("retain") + + /** + * The data key used to order events when `retain` is `highest` or `lowest`. + * + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun sortKey(): Optional = sortKey.getOptional("sort_key") + + /** + * Returns the raw JSON value of [categoryKey]. + * + * Unlike [categoryKey], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("category_key") + @ExcludeMissing + fun _categoryKey(): JsonField = categoryKey + + /** + * Returns the raw JSON value of [retain]. + * + * Unlike [retain], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("retain") @ExcludeMissing fun _retain(): JsonField = retain + + /** + * Returns the raw JSON value of [sortKey]. + * + * Unlike [sortKey], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("sort_key") @ExcludeMissing fun _sortKey(): JsonField = sortKey + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [DigestCategory]. + * + * The following fields are required: + * ```java + * .categoryKey() + * .retain() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [DigestCategory]. */ + class Builder internal constructor() { + + private var categoryKey: JsonField? = null + private var retain: JsonField? = null + private var sortKey: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(digestCategory: DigestCategory) = apply { + categoryKey = digestCategory.categoryKey + retain = digestCategory.retain + sortKey = digestCategory.sortKey + additionalProperties = digestCategory.additionalProperties.toMutableMap() + } + + /** The key that identifies the category within the digest. */ + fun categoryKey(categoryKey: String) = categoryKey(JsonField.of(categoryKey)) + + /** + * Sets [Builder.categoryKey] to an arbitrary JSON value. + * + * You should usually call [Builder.categoryKey] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun categoryKey(categoryKey: JsonField) = apply { this.categoryKey = categoryKey } + + /** + * Which events to keep when the number of events exceeds the retention limit for the + * category. + */ + fun retain(retain: Retain) = retain(JsonField.of(retain)) + + /** + * Sets [Builder.retain] to an arbitrary JSON value. + * + * You should usually call [Builder.retain] with a well-typed [Retain] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun retain(retain: JsonField) = apply { this.retain = retain } + + /** The data key used to order events when `retain` is `highest` or `lowest`. */ + fun sortKey(sortKey: String) = sortKey(JsonField.of(sortKey)) + + /** + * Sets [Builder.sortKey] to an arbitrary JSON value. + * + * You should usually call [Builder.sortKey] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun sortKey(sortKey: JsonField) = apply { this.sortKey = sortKey } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [DigestCategory]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .categoryKey() + * .retain() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): DigestCategory = + DigestCategory( + checkRequired("categoryKey", categoryKey), + checkRequired("retain", retain), + sortKey, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): DigestCategory = apply { + if (validated) { + return@apply + } + + categoryKey() + retain().validate() + sortKey() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CourierInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (categoryKey.asKnown().isPresent) 1 else 0) + + (retain.asKnown().getOrNull()?.validity() ?: 0) + + (if (sortKey.asKnown().isPresent) 1 else 0) + + /** + * Which events to keep when the number of events exceeds the retention limit for the category. + */ + class Retain @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val FIRST = of("first") + + @JvmField val LAST = of("last") + + @JvmField val HIGHEST = of("highest") + + @JvmField val LOWEST = of("lowest") + + @JvmField val NONE = of("none") + + @JvmStatic fun of(value: String) = Retain(JsonField.of(value)) + } + + /** An enum containing [Retain]'s known values. */ + enum class Known { + FIRST, + LAST, + HIGHEST, + LOWEST, + NONE, + } + + /** + * An enum containing [Retain]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Retain] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + FIRST, + LAST, + HIGHEST, + LOWEST, + NONE, + /** An enum member indicating that [Retain] was instantiated with an unknown value. */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + FIRST -> Value.FIRST + LAST -> Value.LAST + HIGHEST -> Value.HIGHEST + LOWEST -> Value.LOWEST + NONE -> Value.NONE + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws CourierInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + FIRST -> Known.FIRST + LAST -> Known.LAST + HIGHEST -> Known.HIGHEST + LOWEST -> Known.LOWEST + NONE -> Known.NONE + else -> throw CourierInvalidDataException("Unknown Retain: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws CourierInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { CourierInvalidDataException("Value is not a String") } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Retain = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CourierInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Retain && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is DigestCategory && + categoryKey == other.categoryKey && + retain == other.retain && + sortKey == other.sortKey && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(categoryKey, retain, sortKey, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "DigestCategory{categoryKey=$categoryKey, retain=$retain, sortKey=$sortKey, additionalProperties=$additionalProperties}" +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/digests/DigestInstance.kt b/courier-java-core/src/main/kotlin/com/courier/models/digests/DigestInstance.kt new file mode 100644 index 00000000..56c508a2 --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/digests/DigestInstance.kt @@ -0,0 +1,784 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.digests + +import com.courier.core.Enum +import com.courier.core.ExcludeMissing +import com.courier.core.JsonField +import com.courier.core.JsonMissing +import com.courier.core.JsonValue +import com.courier.core.checkKnown +import com.courier.core.checkRequired +import com.courier.core.toImmutable +import com.courier.errors.CourierInvalidDataException +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +class DigestInstance +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val digestInstanceId: JsonField, + private val eventCount: JsonField, + private val status: JsonField, + private val userId: JsonField, + private val categories: JsonField>, + private val categoryKeyCounts: JsonField, + private val createdAt: JsonField, + private val disabled: JsonField, + private val tenantId: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("digest_instance_id") + @ExcludeMissing + digestInstanceId: JsonField = JsonMissing.of(), + @JsonProperty("event_count") @ExcludeMissing eventCount: JsonField = JsonMissing.of(), + @JsonProperty("status") @ExcludeMissing status: JsonField = JsonMissing.of(), + @JsonProperty("user_id") @ExcludeMissing userId: JsonField = JsonMissing.of(), + @JsonProperty("categories") + @ExcludeMissing + categories: JsonField> = JsonMissing.of(), + @JsonProperty("category_key_counts") + @ExcludeMissing + categoryKeyCounts: JsonField = JsonMissing.of(), + @JsonProperty("created_at") @ExcludeMissing createdAt: JsonField = JsonMissing.of(), + @JsonProperty("disabled") @ExcludeMissing disabled: JsonField = JsonMissing.of(), + @JsonProperty("tenant_id") @ExcludeMissing tenantId: JsonField = JsonMissing.of(), + ) : this( + digestInstanceId, + eventCount, + status, + userId, + categories, + categoryKeyCounts, + createdAt, + disabled, + tenantId, + mutableMapOf(), + ) + + /** + * A unique identifier for the digest instance. + * + * @throws CourierInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun digestInstanceId(): String = digestInstanceId.getRequired("digest_instance_id") + + /** + * The total number of events received for this instance. + * + * @throws CourierInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun eventCount(): Long = eventCount.getRequired("event_count") + + /** + * The status of the digest instance. `IN_PROGRESS` instances are still accumulating events; + * `COMPLETED` instances have been released. + * + * @throws CourierInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun status(): Status = status.getRequired("status") + + /** + * The ID of the user this digest instance belongs to. + * + * @throws CourierInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun userId(): String = userId.getRequired("user_id") + + /** + * The categories configured for the digest. + * + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun categories(): Optional> = categories.getOptional("categories") + + /** + * A map of category key to the number of events received for that category. + * + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun categoryKeyCounts(): Optional = + categoryKeyCounts.getOptional("category_key_counts") + + /** + * An ISO 8601 timestamp of when the digest instance was created. + * + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun createdAt(): Optional = createdAt.getOptional("created_at") + + /** + * Whether the digest instance has been disabled. + * + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun disabled(): Optional = disabled.getOptional("disabled") + + /** + * The ID of the tenant this digest instance belongs to, if any. + * + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun tenantId(): Optional = tenantId.getOptional("tenant_id") + + /** + * Returns the raw JSON value of [digestInstanceId]. + * + * Unlike [digestInstanceId], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("digest_instance_id") + @ExcludeMissing + fun _digestInstanceId(): JsonField = digestInstanceId + + /** + * Returns the raw JSON value of [eventCount]. + * + * Unlike [eventCount], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("event_count") @ExcludeMissing fun _eventCount(): JsonField = eventCount + + /** + * Returns the raw JSON value of [status]. + * + * Unlike [status], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("status") @ExcludeMissing fun _status(): JsonField = status + + /** + * Returns the raw JSON value of [userId]. + * + * Unlike [userId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("user_id") @ExcludeMissing fun _userId(): JsonField = userId + + /** + * Returns the raw JSON value of [categories]. + * + * Unlike [categories], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("categories") + @ExcludeMissing + fun _categories(): JsonField> = categories + + /** + * Returns the raw JSON value of [categoryKeyCounts]. + * + * Unlike [categoryKeyCounts], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("category_key_counts") + @ExcludeMissing + fun _categoryKeyCounts(): JsonField = categoryKeyCounts + + /** + * Returns the raw JSON value of [createdAt]. + * + * Unlike [createdAt], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("created_at") @ExcludeMissing fun _createdAt(): JsonField = createdAt + + /** + * Returns the raw JSON value of [disabled]. + * + * Unlike [disabled], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("disabled") @ExcludeMissing fun _disabled(): JsonField = disabled + + /** + * Returns the raw JSON value of [tenantId]. + * + * Unlike [tenantId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("tenant_id") @ExcludeMissing fun _tenantId(): JsonField = tenantId + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [DigestInstance]. + * + * The following fields are required: + * ```java + * .digestInstanceId() + * .eventCount() + * .status() + * .userId() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [DigestInstance]. */ + class Builder internal constructor() { + + private var digestInstanceId: JsonField? = null + private var eventCount: JsonField? = null + private var status: JsonField? = null + private var userId: JsonField? = null + private var categories: JsonField>? = null + private var categoryKeyCounts: JsonField = JsonMissing.of() + private var createdAt: JsonField = JsonMissing.of() + private var disabled: JsonField = JsonMissing.of() + private var tenantId: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(digestInstance: DigestInstance) = apply { + digestInstanceId = digestInstance.digestInstanceId + eventCount = digestInstance.eventCount + status = digestInstance.status + userId = digestInstance.userId + categories = digestInstance.categories.map { it.toMutableList() } + categoryKeyCounts = digestInstance.categoryKeyCounts + createdAt = digestInstance.createdAt + disabled = digestInstance.disabled + tenantId = digestInstance.tenantId + additionalProperties = digestInstance.additionalProperties.toMutableMap() + } + + /** A unique identifier for the digest instance. */ + fun digestInstanceId(digestInstanceId: String) = + digestInstanceId(JsonField.of(digestInstanceId)) + + /** + * Sets [Builder.digestInstanceId] to an arbitrary JSON value. + * + * You should usually call [Builder.digestInstanceId] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun digestInstanceId(digestInstanceId: JsonField) = apply { + this.digestInstanceId = digestInstanceId + } + + /** The total number of events received for this instance. */ + fun eventCount(eventCount: Long) = eventCount(JsonField.of(eventCount)) + + /** + * Sets [Builder.eventCount] to an arbitrary JSON value. + * + * You should usually call [Builder.eventCount] with a well-typed [Long] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun eventCount(eventCount: JsonField) = apply { this.eventCount = eventCount } + + /** + * The status of the digest instance. `IN_PROGRESS` instances are still accumulating events; + * `COMPLETED` instances have been released. + */ + fun status(status: Status) = status(JsonField.of(status)) + + /** + * Sets [Builder.status] to an arbitrary JSON value. + * + * You should usually call [Builder.status] with a well-typed [Status] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun status(status: JsonField) = apply { this.status = status } + + /** The ID of the user this digest instance belongs to. */ + fun userId(userId: String) = userId(JsonField.of(userId)) + + /** + * Sets [Builder.userId] to an arbitrary JSON value. + * + * You should usually call [Builder.userId] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun userId(userId: JsonField) = apply { this.userId = userId } + + /** The categories configured for the digest. */ + fun categories(categories: List) = categories(JsonField.of(categories)) + + /** + * Sets [Builder.categories] to an arbitrary JSON value. + * + * You should usually call [Builder.categories] with a well-typed `List` + * value instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun categories(categories: JsonField>) = apply { + this.categories = categories.map { it.toMutableList() } + } + + /** + * Adds a single [DigestCategory] to [categories]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addCategory(category: DigestCategory) = apply { + categories = + (categories ?: JsonField.of(mutableListOf())).also { + checkKnown("categories", it).add(category) + } + } + + /** A map of category key to the number of events received for that category. */ + fun categoryKeyCounts(categoryKeyCounts: CategoryKeyCounts) = + categoryKeyCounts(JsonField.of(categoryKeyCounts)) + + /** + * Sets [Builder.categoryKeyCounts] to an arbitrary JSON value. + * + * You should usually call [Builder.categoryKeyCounts] with a well-typed [CategoryKeyCounts] + * value instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun categoryKeyCounts(categoryKeyCounts: JsonField) = apply { + this.categoryKeyCounts = categoryKeyCounts + } + + /** An ISO 8601 timestamp of when the digest instance was created. */ + fun createdAt(createdAt: String) = createdAt(JsonField.of(createdAt)) + + /** + * Sets [Builder.createdAt] to an arbitrary JSON value. + * + * You should usually call [Builder.createdAt] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun createdAt(createdAt: JsonField) = apply { this.createdAt = createdAt } + + /** Whether the digest instance has been disabled. */ + fun disabled(disabled: Boolean) = disabled(JsonField.of(disabled)) + + /** + * Sets [Builder.disabled] to an arbitrary JSON value. + * + * You should usually call [Builder.disabled] with a well-typed [Boolean] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun disabled(disabled: JsonField) = apply { this.disabled = disabled } + + /** The ID of the tenant this digest instance belongs to, if any. */ + fun tenantId(tenantId: String?) = tenantId(JsonField.ofNullable(tenantId)) + + /** Alias for calling [Builder.tenantId] with `tenantId.orElse(null)`. */ + fun tenantId(tenantId: Optional) = tenantId(tenantId.getOrNull()) + + /** + * Sets [Builder.tenantId] to an arbitrary JSON value. + * + * You should usually call [Builder.tenantId] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun tenantId(tenantId: JsonField) = apply { this.tenantId = tenantId } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [DigestInstance]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .digestInstanceId() + * .eventCount() + * .status() + * .userId() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): DigestInstance = + DigestInstance( + checkRequired("digestInstanceId", digestInstanceId), + checkRequired("eventCount", eventCount), + checkRequired("status", status), + checkRequired("userId", userId), + (categories ?: JsonMissing.of()).map { it.toImmutable() }, + categoryKeyCounts, + createdAt, + disabled, + tenantId, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): DigestInstance = apply { + if (validated) { + return@apply + } + + digestInstanceId() + eventCount() + status().validate() + userId() + categories().ifPresent { it.forEach { it.validate() } } + categoryKeyCounts().ifPresent { it.validate() } + createdAt() + disabled() + tenantId() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CourierInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (digestInstanceId.asKnown().isPresent) 1 else 0) + + (if (eventCount.asKnown().isPresent) 1 else 0) + + (status.asKnown().getOrNull()?.validity() ?: 0) + + (if (userId.asKnown().isPresent) 1 else 0) + + (categories.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (categoryKeyCounts.asKnown().getOrNull()?.validity() ?: 0) + + (if (createdAt.asKnown().isPresent) 1 else 0) + + (if (disabled.asKnown().isPresent) 1 else 0) + + (if (tenantId.asKnown().isPresent) 1 else 0) + + /** + * The status of the digest instance. `IN_PROGRESS` instances are still accumulating events; + * `COMPLETED` instances have been released. + */ + class Status @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val IN_PROGRESS = of("IN_PROGRESS") + + @JvmField val COMPLETED = of("COMPLETED") + + @JvmStatic fun of(value: String) = Status(JsonField.of(value)) + } + + /** An enum containing [Status]'s known values. */ + enum class Known { + IN_PROGRESS, + COMPLETED, + } + + /** + * An enum containing [Status]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Status] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + IN_PROGRESS, + COMPLETED, + /** An enum member indicating that [Status] was instantiated with an unknown value. */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + IN_PROGRESS -> Value.IN_PROGRESS + COMPLETED -> Value.COMPLETED + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws CourierInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + IN_PROGRESS -> Known.IN_PROGRESS + COMPLETED -> Known.COMPLETED + else -> throw CourierInvalidDataException("Unknown Status: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws CourierInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { CourierInvalidDataException("Value is not a String") } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Status = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CourierInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Status && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** A map of category key to the number of events received for that category. */ + class CategoryKeyCounts + @JsonCreator + private constructor( + @com.fasterxml.jackson.annotation.JsonValue + private val additionalProperties: Map + ) { + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = additionalProperties + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [CategoryKeyCounts]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [CategoryKeyCounts]. */ + class Builder internal constructor() { + + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(categoryKeyCounts: CategoryKeyCounts) = apply { + additionalProperties = categoryKeyCounts.additionalProperties.toMutableMap() + } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [CategoryKeyCounts]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): CategoryKeyCounts = CategoryKeyCounts(additionalProperties.toImmutable()) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): CategoryKeyCounts = apply { + if (validated) { + return@apply + } + + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CourierInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + additionalProperties.count { (_, value) -> !value.isNull() && !value.isMissing() } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is CategoryKeyCounts && additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = "CategoryKeyCounts{additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is DigestInstance && + digestInstanceId == other.digestInstanceId && + eventCount == other.eventCount && + status == other.status && + userId == other.userId && + categories == other.categories && + categoryKeyCounts == other.categoryKeyCounts && + createdAt == other.createdAt && + disabled == other.disabled && + tenantId == other.tenantId && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + digestInstanceId, + eventCount, + status, + userId, + categories, + categoryKeyCounts, + createdAt, + disabled, + tenantId, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "DigestInstance{digestInstanceId=$digestInstanceId, eventCount=$eventCount, status=$status, userId=$userId, categories=$categories, categoryKeyCounts=$categoryKeyCounts, createdAt=$createdAt, disabled=$disabled, tenantId=$tenantId, additionalProperties=$additionalProperties}" +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/digests/DigestInstanceListResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/digests/DigestInstanceListResponse.kt new file mode 100644 index 00000000..1b24f085 --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/digests/DigestInstanceListResponse.kt @@ -0,0 +1,514 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.digests + +import com.courier.core.Enum +import com.courier.core.ExcludeMissing +import com.courier.core.JsonField +import com.courier.core.JsonMissing +import com.courier.core.JsonValue +import com.courier.core.checkKnown +import com.courier.core.checkRequired +import com.courier.core.toImmutable +import com.courier.errors.CourierInvalidDataException +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +class DigestInstanceListResponse +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val hasMore: JsonField, + private val items: JsonField>, + private val type: JsonField, + private val cursor: JsonField, + private val nextUrl: JsonField, + private val url: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("has_more") @ExcludeMissing hasMore: JsonField = JsonMissing.of(), + @JsonProperty("items") + @ExcludeMissing + items: JsonField> = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonField = JsonMissing.of(), + @JsonProperty("cursor") @ExcludeMissing cursor: JsonField = JsonMissing.of(), + @JsonProperty("next_url") @ExcludeMissing nextUrl: JsonField = JsonMissing.of(), + @JsonProperty("url") @ExcludeMissing url: JsonField = JsonMissing.of(), + ) : this(hasMore, items, type, cursor, nextUrl, url, mutableMapOf()) + + /** + * Whether there are more digest instances to fetch using the cursor. + * + * @throws CourierInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun hasMore(): Boolean = hasMore.getRequired("has_more") + + /** + * The digest instances for this page of results. + * + * @throws CourierInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun items(): List = items.getRequired("items") + + /** + * Always `list` for a paginated list response. + * + * @throws CourierInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun type(): Type = type.getRequired("type") + + /** + * A cursor token for fetching the next page of results, or null when there are none. + * + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun cursor(): Optional = cursor.getOptional("cursor") + + /** + * The path to fetch the next page of results, or null when there are none. + * + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun nextUrl(): Optional = nextUrl.getOptional("next_url") + + /** + * The path of the current request. + * + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun url(): Optional = url.getOptional("url") + + /** + * Returns the raw JSON value of [hasMore]. + * + * Unlike [hasMore], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("has_more") @ExcludeMissing fun _hasMore(): JsonField = hasMore + + /** + * Returns the raw JSON value of [items]. + * + * Unlike [items], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("items") @ExcludeMissing fun _items(): JsonField> = items + + /** + * Returns the raw JSON value of [type]. + * + * Unlike [type], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonField = type + + /** + * Returns the raw JSON value of [cursor]. + * + * Unlike [cursor], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("cursor") @ExcludeMissing fun _cursor(): JsonField = cursor + + /** + * Returns the raw JSON value of [nextUrl]. + * + * Unlike [nextUrl], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("next_url") @ExcludeMissing fun _nextUrl(): JsonField = nextUrl + + /** + * Returns the raw JSON value of [url]. + * + * Unlike [url], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("url") @ExcludeMissing fun _url(): JsonField = url + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [DigestInstanceListResponse]. + * + * The following fields are required: + * ```java + * .hasMore() + * .items() + * .type() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [DigestInstanceListResponse]. */ + class Builder internal constructor() { + + private var hasMore: JsonField? = null + private var items: JsonField>? = null + private var type: JsonField? = null + private var cursor: JsonField = JsonMissing.of() + private var nextUrl: JsonField = JsonMissing.of() + private var url: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(digestInstanceListResponse: DigestInstanceListResponse) = apply { + hasMore = digestInstanceListResponse.hasMore + items = digestInstanceListResponse.items.map { it.toMutableList() } + type = digestInstanceListResponse.type + cursor = digestInstanceListResponse.cursor + nextUrl = digestInstanceListResponse.nextUrl + url = digestInstanceListResponse.url + additionalProperties = digestInstanceListResponse.additionalProperties.toMutableMap() + } + + /** Whether there are more digest instances to fetch using the cursor. */ + fun hasMore(hasMore: Boolean) = hasMore(JsonField.of(hasMore)) + + /** + * Sets [Builder.hasMore] to an arbitrary JSON value. + * + * You should usually call [Builder.hasMore] with a well-typed [Boolean] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun hasMore(hasMore: JsonField) = apply { this.hasMore = hasMore } + + /** The digest instances for this page of results. */ + fun items(items: List) = items(JsonField.of(items)) + + /** + * Sets [Builder.items] to an arbitrary JSON value. + * + * You should usually call [Builder.items] with a well-typed `List` value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun items(items: JsonField>) = apply { + this.items = items.map { it.toMutableList() } + } + + /** + * Adds a single [DigestInstance] to [items]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addItem(item: DigestInstance) = apply { + items = + (items ?: JsonField.of(mutableListOf())).also { checkKnown("items", it).add(item) } + } + + /** Always `list` for a paginated list response. */ + fun type(type: Type) = type(JsonField.of(type)) + + /** + * Sets [Builder.type] to an arbitrary JSON value. + * + * You should usually call [Builder.type] with a well-typed [Type] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun type(type: JsonField) = apply { this.type = type } + + /** A cursor token for fetching the next page of results, or null when there are none. */ + fun cursor(cursor: String?) = cursor(JsonField.ofNullable(cursor)) + + /** Alias for calling [Builder.cursor] with `cursor.orElse(null)`. */ + fun cursor(cursor: Optional) = cursor(cursor.getOrNull()) + + /** + * Sets [Builder.cursor] to an arbitrary JSON value. + * + * You should usually call [Builder.cursor] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun cursor(cursor: JsonField) = apply { this.cursor = cursor } + + /** The path to fetch the next page of results, or null when there are none. */ + fun nextUrl(nextUrl: String?) = nextUrl(JsonField.ofNullable(nextUrl)) + + /** Alias for calling [Builder.nextUrl] with `nextUrl.orElse(null)`. */ + fun nextUrl(nextUrl: Optional) = nextUrl(nextUrl.getOrNull()) + + /** + * Sets [Builder.nextUrl] to an arbitrary JSON value. + * + * You should usually call [Builder.nextUrl] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun nextUrl(nextUrl: JsonField) = apply { this.nextUrl = nextUrl } + + /** The path of the current request. */ + fun url(url: String) = url(JsonField.of(url)) + + /** + * Sets [Builder.url] to an arbitrary JSON value. + * + * You should usually call [Builder.url] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun url(url: JsonField) = apply { this.url = url } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [DigestInstanceListResponse]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .hasMore() + * .items() + * .type() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): DigestInstanceListResponse = + DigestInstanceListResponse( + checkRequired("hasMore", hasMore), + checkRequired("items", items).map { it.toImmutable() }, + checkRequired("type", type), + cursor, + nextUrl, + url, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): DigestInstanceListResponse = apply { + if (validated) { + return@apply + } + + hasMore() + items().forEach { it.validate() } + type().validate() + cursor() + nextUrl() + url() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CourierInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (hasMore.asKnown().isPresent) 1 else 0) + + (items.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (type.asKnown().getOrNull()?.validity() ?: 0) + + (if (cursor.asKnown().isPresent) 1 else 0) + + (if (nextUrl.asKnown().isPresent) 1 else 0) + + (if (url.asKnown().isPresent) 1 else 0) + + /** Always `list` for a paginated list response. */ + class Type @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val LIST = of("list") + + @JvmStatic fun of(value: String) = Type(JsonField.of(value)) + } + + /** An enum containing [Type]'s known values. */ + enum class Known { + LIST + } + + /** + * An enum containing [Type]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Type] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + LIST, + /** An enum member indicating that [Type] was instantiated with an unknown value. */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + LIST -> Value.LIST + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws CourierInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + LIST -> Known.LIST + else -> throw CourierInvalidDataException("Unknown Type: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws CourierInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { CourierInvalidDataException("Value is not a String") } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Type = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CourierInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Type && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is DigestInstanceListResponse && + hasMore == other.hasMore && + items == other.items && + type == other.type && + cursor == other.cursor && + nextUrl == other.nextUrl && + url == other.url && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(hasMore, items, type, cursor, nextUrl, url, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "DigestInstanceListResponse{hasMore=$hasMore, items=$items, type=$type, cursor=$cursor, nextUrl=$nextUrl, url=$url, additionalProperties=$additionalProperties}" +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/digests/schedules/ScheduleListInstancesParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/digests/schedules/ScheduleListInstancesParams.kt new file mode 100644 index 00000000..2cb01798 --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/digests/schedules/ScheduleListInstancesParams.kt @@ -0,0 +1,244 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.digests.schedules + +import com.courier.core.Params +import com.courier.core.http.Headers +import com.courier.core.http.QueryParams +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** + * List the digest instances for a schedule. Each instance represents the events accumulated for a + * single user against the schedule, and can be used to monitor digest accumulation before the + * digest is released. + */ +class ScheduleListInstancesParams +private constructor( + private val scheduleId: String?, + private val cursor: String?, + private val limit: Long?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun scheduleId(): Optional = Optional.ofNullable(scheduleId) + + /** A cursor token from a previous response, used to fetch the next page of results. */ + fun cursor(): Optional = Optional.ofNullable(cursor) + + /** The maximum number of digest instances to return. Defaults to 20, with a maximum of 100. */ + fun limit(): Optional = Optional.ofNullable(limit) + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + @JvmStatic fun none(): ScheduleListInstancesParams = builder().build() + + /** + * Returns a mutable builder for constructing an instance of [ScheduleListInstancesParams]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [ScheduleListInstancesParams]. */ + class Builder internal constructor() { + + private var scheduleId: String? = null + private var cursor: String? = null + private var limit: Long? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + @JvmSynthetic + internal fun from(scheduleListInstancesParams: ScheduleListInstancesParams) = apply { + scheduleId = scheduleListInstancesParams.scheduleId + cursor = scheduleListInstancesParams.cursor + limit = scheduleListInstancesParams.limit + additionalHeaders = scheduleListInstancesParams.additionalHeaders.toBuilder() + additionalQueryParams = scheduleListInstancesParams.additionalQueryParams.toBuilder() + } + + fun scheduleId(scheduleId: String?) = apply { this.scheduleId = scheduleId } + + /** Alias for calling [Builder.scheduleId] with `scheduleId.orElse(null)`. */ + fun scheduleId(scheduleId: Optional) = scheduleId(scheduleId.getOrNull()) + + /** A cursor token from a previous response, used to fetch the next page of results. */ + fun cursor(cursor: String?) = apply { this.cursor = cursor } + + /** Alias for calling [Builder.cursor] with `cursor.orElse(null)`. */ + fun cursor(cursor: Optional) = cursor(cursor.getOrNull()) + + /** + * The maximum number of digest instances to return. Defaults to 20, with a maximum of 100. + */ + fun limit(limit: Long?) = apply { this.limit = limit } + + /** + * Alias for [Builder.limit]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun limit(limit: Long) = limit(limit as Long?) + + /** Alias for calling [Builder.limit] with `limit.orElse(null)`. */ + fun limit(limit: Optional) = limit(limit.getOrNull()) + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [ScheduleListInstancesParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): ScheduleListInstancesParams = + ScheduleListInstancesParams( + scheduleId, + cursor, + limit, + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + fun _pathParam(index: Int): String = + when (index) { + 0 -> scheduleId ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = + QueryParams.builder() + .apply { + cursor?.let { put("cursor", it) } + limit?.let { put("limit", it.toString()) } + putAll(additionalQueryParams) + } + .build() + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ScheduleListInstancesParams && + scheduleId == other.scheduleId && + cursor == other.cursor && + limit == other.limit && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = + Objects.hash(scheduleId, cursor, limit, additionalHeaders, additionalQueryParams) + + override fun toString() = + "ScheduleListInstancesParams{scheduleId=$scheduleId, cursor=$cursor, limit=$limit, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/digests/schedules/ScheduleReleaseParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/digests/schedules/ScheduleReleaseParams.kt new file mode 100644 index 00000000..8f6228ee --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/digests/schedules/ScheduleReleaseParams.kt @@ -0,0 +1,232 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.digests.schedules + +import com.courier.core.JsonValue +import com.courier.core.Params +import com.courier.core.http.Headers +import com.courier.core.http.QueryParams +import com.courier.core.toImmutable +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** + * Send a digest now instead of waiting for its scheduled time, so your users get what they have + * collected so far right away. + */ +class ScheduleReleaseParams +private constructor( + private val scheduleId: String?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, + private val additionalBodyProperties: Map, +) : Params { + + fun scheduleId(): Optional = Optional.ofNullable(scheduleId) + + /** Additional body properties to send with the request. */ + fun _additionalBodyProperties(): Map = additionalBodyProperties + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + @JvmStatic fun none(): ScheduleReleaseParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [ScheduleReleaseParams]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [ScheduleReleaseParams]. */ + class Builder internal constructor() { + + private var scheduleId: String? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + private var additionalBodyProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(scheduleReleaseParams: ScheduleReleaseParams) = apply { + scheduleId = scheduleReleaseParams.scheduleId + additionalHeaders = scheduleReleaseParams.additionalHeaders.toBuilder() + additionalQueryParams = scheduleReleaseParams.additionalQueryParams.toBuilder() + additionalBodyProperties = scheduleReleaseParams.additionalBodyProperties.toMutableMap() + } + + fun scheduleId(scheduleId: String?) = apply { this.scheduleId = scheduleId } + + /** Alias for calling [Builder.scheduleId] with `scheduleId.orElse(null)`. */ + fun scheduleId(scheduleId: Optional) = scheduleId(scheduleId.getOrNull()) + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + this.additionalBodyProperties.clear() + putAllAdditionalBodyProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + additionalBodyProperties.put(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + this.additionalBodyProperties.putAll(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { + additionalBodyProperties.remove(key) + } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalBodyProperty) + } + + /** + * Returns an immutable instance of [ScheduleReleaseParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): ScheduleReleaseParams = + ScheduleReleaseParams( + scheduleId, + additionalHeaders.build(), + additionalQueryParams.build(), + additionalBodyProperties.toImmutable(), + ) + } + + fun _body(): Optional> = + Optional.ofNullable(additionalBodyProperties.ifEmpty { null }) + + fun _pathParam(index: Int): String = + when (index) { + 0 -> scheduleId ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ScheduleReleaseParams && + scheduleId == other.scheduleId && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams && + additionalBodyProperties == other.additionalBodyProperties + } + + override fun hashCode(): Int = + Objects.hash(scheduleId, additionalHeaders, additionalQueryParams, additionalBodyProperties) + + override fun toString() = + "ScheduleReleaseParams{scheduleId=$scheduleId, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams, additionalBodyProperties=$additionalBodyProperties}" +} diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/DigestServiceAsync.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/DigestServiceAsync.kt new file mode 100644 index 00000000..afe0cc5d --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/DigestServiceAsync.kt @@ -0,0 +1,41 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.services.async + +import com.courier.core.ClientOptions +import com.courier.services.async.digests.ScheduleServiceAsync +import java.util.function.Consumer + +interface DigestServiceAsync { + + /** + * Returns a view of this service that provides access to raw HTTP responses for each method. + */ + fun withRawResponse(): WithRawResponse + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: Consumer): DigestServiceAsync + + fun schedules(): ScheduleServiceAsync + + /** + * A view of [DigestServiceAsync] that provides access to raw HTTP responses for each method. + */ + interface WithRawResponse { + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions( + modifier: Consumer + ): DigestServiceAsync.WithRawResponse + + fun schedules(): ScheduleServiceAsync.WithRawResponse + } +} diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/DigestServiceAsyncImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/DigestServiceAsyncImpl.kt new file mode 100644 index 00000000..aa271ff8 --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/DigestServiceAsyncImpl.kt @@ -0,0 +1,42 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.services.async + +import com.courier.core.ClientOptions +import com.courier.services.async.digests.ScheduleServiceAsync +import com.courier.services.async.digests.ScheduleServiceAsyncImpl +import java.util.function.Consumer + +class DigestServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : + DigestServiceAsync { + + private val withRawResponse: DigestServiceAsync.WithRawResponse by lazy { + WithRawResponseImpl(clientOptions) + } + + private val schedules: ScheduleServiceAsync by lazy { ScheduleServiceAsyncImpl(clientOptions) } + + override fun withRawResponse(): DigestServiceAsync.WithRawResponse = withRawResponse + + override fun withOptions(modifier: Consumer): DigestServiceAsync = + DigestServiceAsyncImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + + override fun schedules(): ScheduleServiceAsync = schedules + + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : + DigestServiceAsync.WithRawResponse { + + private val schedules: ScheduleServiceAsync.WithRawResponse by lazy { + ScheduleServiceAsyncImpl.WithRawResponseImpl(clientOptions) + } + + override fun withOptions( + modifier: Consumer + ): DigestServiceAsync.WithRawResponse = + DigestServiceAsyncImpl.WithRawResponseImpl( + clientOptions.toBuilder().apply(modifier::accept).build() + ) + + override fun schedules(): ScheduleServiceAsync.WithRawResponse = schedules + } +} diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/digests/ScheduleServiceAsync.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/digests/ScheduleServiceAsync.kt new file mode 100644 index 00000000..92475a25 --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/digests/ScheduleServiceAsync.kt @@ -0,0 +1,200 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.services.async.digests + +import com.courier.core.ClientOptions +import com.courier.core.RequestOptions +import com.courier.core.http.HttpResponse +import com.courier.core.http.HttpResponseFor +import com.courier.models.digests.DigestInstanceListResponse +import com.courier.models.digests.schedules.ScheduleListInstancesParams +import com.courier.models.digests.schedules.ScheduleReleaseParams +import java.util.concurrent.CompletableFuture +import java.util.function.Consumer + +interface ScheduleServiceAsync { + + /** + * Returns a view of this service that provides access to raw HTTP responses for each method. + */ + fun withRawResponse(): WithRawResponse + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: Consumer): ScheduleServiceAsync + + /** + * List the digest instances for a schedule. Each instance represents the events accumulated for + * a single user against the schedule, and can be used to monitor digest accumulation before the + * digest is released. + */ + fun listInstances(scheduleId: String): CompletableFuture = + listInstances(scheduleId, ScheduleListInstancesParams.none()) + + /** @see listInstances */ + fun listInstances( + scheduleId: String, + params: ScheduleListInstancesParams = ScheduleListInstancesParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + listInstances(params.toBuilder().scheduleId(scheduleId).build(), requestOptions) + + /** @see listInstances */ + fun listInstances( + scheduleId: String, + params: ScheduleListInstancesParams = ScheduleListInstancesParams.none(), + ): CompletableFuture = + listInstances(scheduleId, params, RequestOptions.none()) + + /** @see listInstances */ + fun listInstances( + params: ScheduleListInstancesParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + + /** @see listInstances */ + fun listInstances( + params: ScheduleListInstancesParams + ): CompletableFuture = listInstances(params, RequestOptions.none()) + + /** @see listInstances */ + fun listInstances( + scheduleId: String, + requestOptions: RequestOptions, + ): CompletableFuture = + listInstances(scheduleId, ScheduleListInstancesParams.none(), requestOptions) + + /** + * Send a digest now instead of waiting for its scheduled time, so your users get what they have + * collected so far right away. + */ + fun release(scheduleId: String): CompletableFuture = + release(scheduleId, ScheduleReleaseParams.none()) + + /** @see release */ + fun release( + scheduleId: String, + params: ScheduleReleaseParams = ScheduleReleaseParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + release(params.toBuilder().scheduleId(scheduleId).build(), requestOptions) + + /** @see release */ + fun release( + scheduleId: String, + params: ScheduleReleaseParams = ScheduleReleaseParams.none(), + ): CompletableFuture = release(scheduleId, params, RequestOptions.none()) + + /** @see release */ + fun release( + params: ScheduleReleaseParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + + /** @see release */ + fun release(params: ScheduleReleaseParams): CompletableFuture = + release(params, RequestOptions.none()) + + /** @see release */ + fun release(scheduleId: String, requestOptions: RequestOptions): CompletableFuture = + release(scheduleId, ScheduleReleaseParams.none(), requestOptions) + + /** + * A view of [ScheduleServiceAsync] that provides access to raw HTTP responses for each method. + */ + interface WithRawResponse { + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions( + modifier: Consumer + ): ScheduleServiceAsync.WithRawResponse + + /** + * Returns a raw HTTP response for `get /digests/schedules/{schedule_id}/instances`, but is + * otherwise the same as [ScheduleServiceAsync.listInstances]. + */ + fun listInstances( + scheduleId: String + ): CompletableFuture> = + listInstances(scheduleId, ScheduleListInstancesParams.none()) + + /** @see listInstances */ + fun listInstances( + scheduleId: String, + params: ScheduleListInstancesParams = ScheduleListInstancesParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> = + listInstances(params.toBuilder().scheduleId(scheduleId).build(), requestOptions) + + /** @see listInstances */ + fun listInstances( + scheduleId: String, + params: ScheduleListInstancesParams = ScheduleListInstancesParams.none(), + ): CompletableFuture> = + listInstances(scheduleId, params, RequestOptions.none()) + + /** @see listInstances */ + fun listInstances( + params: ScheduleListInstancesParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> + + /** @see listInstances */ + fun listInstances( + params: ScheduleListInstancesParams + ): CompletableFuture> = + listInstances(params, RequestOptions.none()) + + /** @see listInstances */ + fun listInstances( + scheduleId: String, + requestOptions: RequestOptions, + ): CompletableFuture> = + listInstances(scheduleId, ScheduleListInstancesParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `post /digests/schedules/{schedule_id}/trigger`, but is + * otherwise the same as [ScheduleServiceAsync.release]. + */ + fun release(scheduleId: String): CompletableFuture = + release(scheduleId, ScheduleReleaseParams.none()) + + /** @see release */ + fun release( + scheduleId: String, + params: ScheduleReleaseParams = ScheduleReleaseParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + release(params.toBuilder().scheduleId(scheduleId).build(), requestOptions) + + /** @see release */ + fun release( + scheduleId: String, + params: ScheduleReleaseParams = ScheduleReleaseParams.none(), + ): CompletableFuture = release(scheduleId, params, RequestOptions.none()) + + /** @see release */ + fun release( + params: ScheduleReleaseParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + + /** @see release */ + fun release(params: ScheduleReleaseParams): CompletableFuture = + release(params, RequestOptions.none()) + + /** @see release */ + fun release( + scheduleId: String, + requestOptions: RequestOptions, + ): CompletableFuture = + release(scheduleId, ScheduleReleaseParams.none(), requestOptions) + } +} diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/digests/ScheduleServiceAsyncImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/digests/ScheduleServiceAsyncImpl.kt new file mode 100644 index 00000000..1af16147 --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/digests/ScheduleServiceAsyncImpl.kt @@ -0,0 +1,126 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.services.async.digests + +import com.courier.core.ClientOptions +import com.courier.core.RequestOptions +import com.courier.core.checkRequired +import com.courier.core.handlers.emptyHandler +import com.courier.core.handlers.errorBodyHandler +import com.courier.core.handlers.errorHandler +import com.courier.core.handlers.jsonHandler +import com.courier.core.http.HttpMethod +import com.courier.core.http.HttpRequest +import com.courier.core.http.HttpResponse +import com.courier.core.http.HttpResponse.Handler +import com.courier.core.http.HttpResponseFor +import com.courier.core.http.json +import com.courier.core.http.parseable +import com.courier.core.prepareAsync +import com.courier.models.digests.DigestInstanceListResponse +import com.courier.models.digests.schedules.ScheduleListInstancesParams +import com.courier.models.digests.schedules.ScheduleReleaseParams +import java.util.concurrent.CompletableFuture +import java.util.function.Consumer +import kotlin.jvm.optionals.getOrNull + +class ScheduleServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : + ScheduleServiceAsync { + + private val withRawResponse: ScheduleServiceAsync.WithRawResponse by lazy { + WithRawResponseImpl(clientOptions) + } + + override fun withRawResponse(): ScheduleServiceAsync.WithRawResponse = withRawResponse + + override fun withOptions(modifier: Consumer): ScheduleServiceAsync = + ScheduleServiceAsyncImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + + override fun listInstances( + params: ScheduleListInstancesParams, + requestOptions: RequestOptions, + ): CompletableFuture = + // get /digests/schedules/{schedule_id}/instances + withRawResponse().listInstances(params, requestOptions).thenApply { it.parse() } + + override fun release( + params: ScheduleReleaseParams, + requestOptions: RequestOptions, + ): CompletableFuture = + // post /digests/schedules/{schedule_id}/trigger + withRawResponse().release(params, requestOptions).thenAccept {} + + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : + ScheduleServiceAsync.WithRawResponse { + + private val errorHandler: Handler = + errorHandler(errorBodyHandler(clientOptions.jsonMapper)) + + override fun withOptions( + modifier: Consumer + ): ScheduleServiceAsync.WithRawResponse = + ScheduleServiceAsyncImpl.WithRawResponseImpl( + clientOptions.toBuilder().apply(modifier::accept).build() + ) + + private val listInstancesHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun listInstances( + params: ScheduleListInstancesParams, + requestOptions: RequestOptions, + ): CompletableFuture> { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("scheduleId", params.scheduleId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("digests", "schedules", params._pathParam(0), "instances") + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response + .use { listInstancesHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } + + private val releaseHandler: Handler = emptyHandler() + + override fun release( + params: ScheduleReleaseParams, + requestOptions: RequestOptions, + ): CompletableFuture { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("scheduleId", params.scheduleId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("digests", "schedules", params._pathParam(0), "trigger") + .apply { params._body().ifPresent { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response.use { releaseHandler.handle(it) } + } + } + } + } +} diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/DigestService.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/DigestService.kt new file mode 100644 index 00000000..c7ccda3f --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/DigestService.kt @@ -0,0 +1,37 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.services.blocking + +import com.courier.core.ClientOptions +import com.courier.services.blocking.digests.ScheduleService +import java.util.function.Consumer + +interface DigestService { + + /** + * Returns a view of this service that provides access to raw HTTP responses for each method. + */ + fun withRawResponse(): WithRawResponse + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: Consumer): DigestService + + fun schedules(): ScheduleService + + /** A view of [DigestService] that provides access to raw HTTP responses for each method. */ + interface WithRawResponse { + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: Consumer): DigestService.WithRawResponse + + fun schedules(): ScheduleService.WithRawResponse + } +} diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/DigestServiceImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/DigestServiceImpl.kt new file mode 100644 index 00000000..9bc624d3 --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/DigestServiceImpl.kt @@ -0,0 +1,42 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.services.blocking + +import com.courier.core.ClientOptions +import com.courier.services.blocking.digests.ScheduleService +import com.courier.services.blocking.digests.ScheduleServiceImpl +import java.util.function.Consumer + +class DigestServiceImpl internal constructor(private val clientOptions: ClientOptions) : + DigestService { + + private val withRawResponse: DigestService.WithRawResponse by lazy { + WithRawResponseImpl(clientOptions) + } + + private val schedules: ScheduleService by lazy { ScheduleServiceImpl(clientOptions) } + + override fun withRawResponse(): DigestService.WithRawResponse = withRawResponse + + override fun withOptions(modifier: Consumer): DigestService = + DigestServiceImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + + override fun schedules(): ScheduleService = schedules + + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : + DigestService.WithRawResponse { + + private val schedules: ScheduleService.WithRawResponse by lazy { + ScheduleServiceImpl.WithRawResponseImpl(clientOptions) + } + + override fun withOptions( + modifier: Consumer + ): DigestService.WithRawResponse = + DigestServiceImpl.WithRawResponseImpl( + clientOptions.toBuilder().apply(modifier::accept).build() + ) + + override fun schedules(): ScheduleService.WithRawResponse = schedules + } +} diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/digests/ScheduleService.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/digests/ScheduleService.kt new file mode 100644 index 00000000..5774cb32 --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/digests/ScheduleService.kt @@ -0,0 +1,195 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.services.blocking.digests + +import com.courier.core.ClientOptions +import com.courier.core.RequestOptions +import com.courier.core.http.HttpResponse +import com.courier.core.http.HttpResponseFor +import com.courier.models.digests.DigestInstanceListResponse +import com.courier.models.digests.schedules.ScheduleListInstancesParams +import com.courier.models.digests.schedules.ScheduleReleaseParams +import com.google.errorprone.annotations.MustBeClosed +import java.util.function.Consumer + +interface ScheduleService { + + /** + * Returns a view of this service that provides access to raw HTTP responses for each method. + */ + fun withRawResponse(): WithRawResponse + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: Consumer): ScheduleService + + /** + * List the digest instances for a schedule. Each instance represents the events accumulated for + * a single user against the schedule, and can be used to monitor digest accumulation before the + * digest is released. + */ + fun listInstances(scheduleId: String): DigestInstanceListResponse = + listInstances(scheduleId, ScheduleListInstancesParams.none()) + + /** @see listInstances */ + fun listInstances( + scheduleId: String, + params: ScheduleListInstancesParams = ScheduleListInstancesParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): DigestInstanceListResponse = + listInstances(params.toBuilder().scheduleId(scheduleId).build(), requestOptions) + + /** @see listInstances */ + fun listInstances( + scheduleId: String, + params: ScheduleListInstancesParams = ScheduleListInstancesParams.none(), + ): DigestInstanceListResponse = listInstances(scheduleId, params, RequestOptions.none()) + + /** @see listInstances */ + fun listInstances( + params: ScheduleListInstancesParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): DigestInstanceListResponse + + /** @see listInstances */ + fun listInstances(params: ScheduleListInstancesParams): DigestInstanceListResponse = + listInstances(params, RequestOptions.none()) + + /** @see listInstances */ + fun listInstances( + scheduleId: String, + requestOptions: RequestOptions, + ): DigestInstanceListResponse = + listInstances(scheduleId, ScheduleListInstancesParams.none(), requestOptions) + + /** + * Send a digest now instead of waiting for its scheduled time, so your users get what they have + * collected so far right away. + */ + fun release(scheduleId: String) = release(scheduleId, ScheduleReleaseParams.none()) + + /** @see release */ + fun release( + scheduleId: String, + params: ScheduleReleaseParams = ScheduleReleaseParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ) = release(params.toBuilder().scheduleId(scheduleId).build(), requestOptions) + + /** @see release */ + fun release(scheduleId: String, params: ScheduleReleaseParams = ScheduleReleaseParams.none()) = + release(scheduleId, params, RequestOptions.none()) + + /** @see release */ + fun release( + params: ScheduleReleaseParams, + requestOptions: RequestOptions = RequestOptions.none(), + ) + + /** @see release */ + fun release(params: ScheduleReleaseParams) = release(params, RequestOptions.none()) + + /** @see release */ + fun release(scheduleId: String, requestOptions: RequestOptions) = + release(scheduleId, ScheduleReleaseParams.none(), requestOptions) + + /** A view of [ScheduleService] that provides access to raw HTTP responses for each method. */ + interface WithRawResponse { + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: Consumer): ScheduleService.WithRawResponse + + /** + * Returns a raw HTTP response for `get /digests/schedules/{schedule_id}/instances`, but is + * otherwise the same as [ScheduleService.listInstances]. + */ + @MustBeClosed + fun listInstances(scheduleId: String): HttpResponseFor = + listInstances(scheduleId, ScheduleListInstancesParams.none()) + + /** @see listInstances */ + @MustBeClosed + fun listInstances( + scheduleId: String, + params: ScheduleListInstancesParams = ScheduleListInstancesParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + listInstances(params.toBuilder().scheduleId(scheduleId).build(), requestOptions) + + /** @see listInstances */ + @MustBeClosed + fun listInstances( + scheduleId: String, + params: ScheduleListInstancesParams = ScheduleListInstancesParams.none(), + ): HttpResponseFor = + listInstances(scheduleId, params, RequestOptions.none()) + + /** @see listInstances */ + @MustBeClosed + fun listInstances( + params: ScheduleListInstancesParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see listInstances */ + @MustBeClosed + fun listInstances( + params: ScheduleListInstancesParams + ): HttpResponseFor = + listInstances(params, RequestOptions.none()) + + /** @see listInstances */ + @MustBeClosed + fun listInstances( + scheduleId: String, + requestOptions: RequestOptions, + ): HttpResponseFor = + listInstances(scheduleId, ScheduleListInstancesParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `post /digests/schedules/{schedule_id}/trigger`, but is + * otherwise the same as [ScheduleService.release]. + */ + @MustBeClosed + fun release(scheduleId: String): HttpResponse = + release(scheduleId, ScheduleReleaseParams.none()) + + /** @see release */ + @MustBeClosed + fun release( + scheduleId: String, + params: ScheduleReleaseParams = ScheduleReleaseParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse = release(params.toBuilder().scheduleId(scheduleId).build(), requestOptions) + + /** @see release */ + @MustBeClosed + fun release( + scheduleId: String, + params: ScheduleReleaseParams = ScheduleReleaseParams.none(), + ): HttpResponse = release(scheduleId, params, RequestOptions.none()) + + /** @see release */ + @MustBeClosed + fun release( + params: ScheduleReleaseParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse + + /** @see release */ + @MustBeClosed + fun release(params: ScheduleReleaseParams): HttpResponse = + release(params, RequestOptions.none()) + + /** @see release */ + @MustBeClosed + fun release(scheduleId: String, requestOptions: RequestOptions): HttpResponse = + release(scheduleId, ScheduleReleaseParams.none(), requestOptions) + } +} diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/digests/ScheduleServiceImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/digests/ScheduleServiceImpl.kt new file mode 100644 index 00000000..346dde55 --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/digests/ScheduleServiceImpl.kt @@ -0,0 +1,117 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.services.blocking.digests + +import com.courier.core.ClientOptions +import com.courier.core.RequestOptions +import com.courier.core.checkRequired +import com.courier.core.handlers.emptyHandler +import com.courier.core.handlers.errorBodyHandler +import com.courier.core.handlers.errorHandler +import com.courier.core.handlers.jsonHandler +import com.courier.core.http.HttpMethod +import com.courier.core.http.HttpRequest +import com.courier.core.http.HttpResponse +import com.courier.core.http.HttpResponse.Handler +import com.courier.core.http.HttpResponseFor +import com.courier.core.http.json +import com.courier.core.http.parseable +import com.courier.core.prepare +import com.courier.models.digests.DigestInstanceListResponse +import com.courier.models.digests.schedules.ScheduleListInstancesParams +import com.courier.models.digests.schedules.ScheduleReleaseParams +import java.util.function.Consumer +import kotlin.jvm.optionals.getOrNull + +class ScheduleServiceImpl internal constructor(private val clientOptions: ClientOptions) : + ScheduleService { + + private val withRawResponse: ScheduleService.WithRawResponse by lazy { + WithRawResponseImpl(clientOptions) + } + + override fun withRawResponse(): ScheduleService.WithRawResponse = withRawResponse + + override fun withOptions(modifier: Consumer): ScheduleService = + ScheduleServiceImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + + override fun listInstances( + params: ScheduleListInstancesParams, + requestOptions: RequestOptions, + ): DigestInstanceListResponse = + // get /digests/schedules/{schedule_id}/instances + withRawResponse().listInstances(params, requestOptions).parse() + + override fun release(params: ScheduleReleaseParams, requestOptions: RequestOptions) { + // post /digests/schedules/{schedule_id}/trigger + withRawResponse().release(params, requestOptions) + } + + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : + ScheduleService.WithRawResponse { + + private val errorHandler: Handler = + errorHandler(errorBodyHandler(clientOptions.jsonMapper)) + + override fun withOptions( + modifier: Consumer + ): ScheduleService.WithRawResponse = + ScheduleServiceImpl.WithRawResponseImpl( + clientOptions.toBuilder().apply(modifier::accept).build() + ) + + private val listInstancesHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun listInstances( + params: ScheduleListInstancesParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("scheduleId", params.scheduleId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("digests", "schedules", params._pathParam(0), "instances") + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { listInstancesHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val releaseHandler: Handler = emptyHandler() + + override fun release( + params: ScheduleReleaseParams, + requestOptions: RequestOptions, + ): HttpResponse { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("scheduleId", params.scheduleId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("digests", "schedules", params._pathParam(0), "trigger") + .apply { params._body().ifPresent { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response.use { releaseHandler.handle(it) } + } + } + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/models/digests/DigestCategoryTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/digests/DigestCategoryTest.kt new file mode 100644 index 00000000..982b968b --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/models/digests/DigestCategoryTest.kt @@ -0,0 +1,44 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.digests + +import com.courier.core.jsonMapper +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class DigestCategoryTest { + + @Test + fun create() { + val digestCategory = + DigestCategory.builder() + .categoryKey("category_key") + .retain(DigestCategory.Retain.FIRST) + .sortKey("sort_key") + .build() + + assertThat(digestCategory.categoryKey()).isEqualTo("category_key") + assertThat(digestCategory.retain()).isEqualTo(DigestCategory.Retain.FIRST) + assertThat(digestCategory.sortKey()).contains("sort_key") + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val digestCategory = + DigestCategory.builder() + .categoryKey("category_key") + .retain(DigestCategory.Retain.FIRST) + .sortKey("sort_key") + .build() + + val roundtrippedDigestCategory = + jsonMapper.readValue( + jsonMapper.writeValueAsString(digestCategory), + jacksonTypeRef(), + ) + + assertThat(roundtrippedDigestCategory).isEqualTo(digestCategory) + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/models/digests/DigestInstanceListResponseTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/digests/DigestInstanceListResponseTest.kt new file mode 100644 index 00000000..3261e659 --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/models/digests/DigestInstanceListResponseTest.kt @@ -0,0 +1,122 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.digests + +import com.courier.core.JsonValue +import com.courier.core.jsonMapper +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class DigestInstanceListResponseTest { + + @Test + fun create() { + val digestInstanceListResponse = + DigestInstanceListResponse.builder() + .hasMore(true) + .addItem( + DigestInstance.builder() + .digestInstanceId("digest_instance_id") + .eventCount(0L) + .status(DigestInstance.Status.IN_PROGRESS) + .userId("user_id") + .addCategory( + DigestCategory.builder() + .categoryKey("category_key") + .retain(DigestCategory.Retain.FIRST) + .sortKey("sort_key") + .build() + ) + .categoryKeyCounts( + DigestInstance.CategoryKeyCounts.builder() + .putAdditionalProperty("foo", JsonValue.from(0)) + .build() + ) + .createdAt("created_at") + .disabled(true) + .tenantId("tenant_id") + .build() + ) + .type(DigestInstanceListResponse.Type.LIST) + .cursor("cursor") + .nextUrl("next_url") + .url("url") + .build() + + assertThat(digestInstanceListResponse.hasMore()).isEqualTo(true) + assertThat(digestInstanceListResponse.items()) + .containsExactly( + DigestInstance.builder() + .digestInstanceId("digest_instance_id") + .eventCount(0L) + .status(DigestInstance.Status.IN_PROGRESS) + .userId("user_id") + .addCategory( + DigestCategory.builder() + .categoryKey("category_key") + .retain(DigestCategory.Retain.FIRST) + .sortKey("sort_key") + .build() + ) + .categoryKeyCounts( + DigestInstance.CategoryKeyCounts.builder() + .putAdditionalProperty("foo", JsonValue.from(0)) + .build() + ) + .createdAt("created_at") + .disabled(true) + .tenantId("tenant_id") + .build() + ) + assertThat(digestInstanceListResponse.type()) + .isEqualTo(DigestInstanceListResponse.Type.LIST) + assertThat(digestInstanceListResponse.cursor()).contains("cursor") + assertThat(digestInstanceListResponse.nextUrl()).contains("next_url") + assertThat(digestInstanceListResponse.url()).contains("url") + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val digestInstanceListResponse = + DigestInstanceListResponse.builder() + .hasMore(true) + .addItem( + DigestInstance.builder() + .digestInstanceId("digest_instance_id") + .eventCount(0L) + .status(DigestInstance.Status.IN_PROGRESS) + .userId("user_id") + .addCategory( + DigestCategory.builder() + .categoryKey("category_key") + .retain(DigestCategory.Retain.FIRST) + .sortKey("sort_key") + .build() + ) + .categoryKeyCounts( + DigestInstance.CategoryKeyCounts.builder() + .putAdditionalProperty("foo", JsonValue.from(0)) + .build() + ) + .createdAt("created_at") + .disabled(true) + .tenantId("tenant_id") + .build() + ) + .type(DigestInstanceListResponse.Type.LIST) + .cursor("cursor") + .nextUrl("next_url") + .url("url") + .build() + + val roundtrippedDigestInstanceListResponse = + jsonMapper.readValue( + jsonMapper.writeValueAsString(digestInstanceListResponse), + jacksonTypeRef(), + ) + + assertThat(roundtrippedDigestInstanceListResponse).isEqualTo(digestInstanceListResponse) + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/models/digests/DigestInstanceTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/digests/DigestInstanceTest.kt new file mode 100644 index 00000000..564e122f --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/models/digests/DigestInstanceTest.kt @@ -0,0 +1,96 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.digests + +import com.courier.core.JsonValue +import com.courier.core.jsonMapper +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import kotlin.jvm.optionals.getOrNull +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class DigestInstanceTest { + + @Test + fun create() { + val digestInstance = + DigestInstance.builder() + .digestInstanceId("digest_instance_id") + .eventCount(0L) + .status(DigestInstance.Status.IN_PROGRESS) + .userId("user_id") + .addCategory( + DigestCategory.builder() + .categoryKey("category_key") + .retain(DigestCategory.Retain.FIRST) + .sortKey("sort_key") + .build() + ) + .categoryKeyCounts( + DigestInstance.CategoryKeyCounts.builder() + .putAdditionalProperty("foo", JsonValue.from(0)) + .build() + ) + .createdAt("created_at") + .disabled(true) + .tenantId("tenant_id") + .build() + + assertThat(digestInstance.digestInstanceId()).isEqualTo("digest_instance_id") + assertThat(digestInstance.eventCount()).isEqualTo(0L) + assertThat(digestInstance.status()).isEqualTo(DigestInstance.Status.IN_PROGRESS) + assertThat(digestInstance.userId()).isEqualTo("user_id") + assertThat(digestInstance.categories().getOrNull()) + .containsExactly( + DigestCategory.builder() + .categoryKey("category_key") + .retain(DigestCategory.Retain.FIRST) + .sortKey("sort_key") + .build() + ) + assertThat(digestInstance.categoryKeyCounts()) + .contains( + DigestInstance.CategoryKeyCounts.builder() + .putAdditionalProperty("foo", JsonValue.from(0)) + .build() + ) + assertThat(digestInstance.createdAt()).contains("created_at") + assertThat(digestInstance.disabled()).contains(true) + assertThat(digestInstance.tenantId()).contains("tenant_id") + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val digestInstance = + DigestInstance.builder() + .digestInstanceId("digest_instance_id") + .eventCount(0L) + .status(DigestInstance.Status.IN_PROGRESS) + .userId("user_id") + .addCategory( + DigestCategory.builder() + .categoryKey("category_key") + .retain(DigestCategory.Retain.FIRST) + .sortKey("sort_key") + .build() + ) + .categoryKeyCounts( + DigestInstance.CategoryKeyCounts.builder() + .putAdditionalProperty("foo", JsonValue.from(0)) + .build() + ) + .createdAt("created_at") + .disabled(true) + .tenantId("tenant_id") + .build() + + val roundtrippedDigestInstance = + jsonMapper.readValue( + jsonMapper.writeValueAsString(digestInstance), + jacksonTypeRef(), + ) + + assertThat(roundtrippedDigestInstance).isEqualTo(digestInstance) + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/models/digests/schedules/ScheduleListInstancesParamsTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/digests/schedules/ScheduleListInstancesParamsTest.kt new file mode 100644 index 00000000..fc65a5ad --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/models/digests/schedules/ScheduleListInstancesParamsTest.kt @@ -0,0 +1,52 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.digests.schedules + +import com.courier.core.http.QueryParams +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class ScheduleListInstancesParamsTest { + + @Test + fun create() { + ScheduleListInstancesParams.builder() + .scheduleId("schedule_id") + .cursor("cursor") + .limit(100L) + .build() + } + + @Test + fun pathParams() { + val params = ScheduleListInstancesParams.builder().scheduleId("schedule_id").build() + + assertThat(params._pathParam(0)).isEqualTo("schedule_id") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } + + @Test + fun queryParams() { + val params = + ScheduleListInstancesParams.builder() + .scheduleId("schedule_id") + .cursor("cursor") + .limit(100L) + .build() + + val queryParams = params._queryParams() + + assertThat(queryParams) + .isEqualTo(QueryParams.builder().put("cursor", "cursor").put("limit", "100").build()) + } + + @Test + fun queryParamsWithoutOptionalFields() { + val params = ScheduleListInstancesParams.builder().scheduleId("schedule_id").build() + + val queryParams = params._queryParams() + + assertThat(queryParams).isEqualTo(QueryParams.builder().build()) + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/models/digests/schedules/ScheduleReleaseParamsTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/digests/schedules/ScheduleReleaseParamsTest.kt new file mode 100644 index 00000000..fa221e25 --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/models/digests/schedules/ScheduleReleaseParamsTest.kt @@ -0,0 +1,23 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.digests.schedules + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class ScheduleReleaseParamsTest { + + @Test + fun create() { + ScheduleReleaseParams.builder().scheduleId("schedule_id").build() + } + + @Test + fun pathParams() { + val params = ScheduleReleaseParams.builder().scheduleId("schedule_id").build() + + assertThat(params._pathParam(0)).isEqualTo("schedule_id") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/services/async/digests/ScheduleServiceAsyncTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/async/digests/ScheduleServiceAsyncTest.kt new file mode 100644 index 00000000..67e9fecb --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/services/async/digests/ScheduleServiceAsyncTest.kt @@ -0,0 +1,41 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.services.async.digests + +import com.courier.client.okhttp.CourierOkHttpClientAsync +import com.courier.models.digests.schedules.ScheduleListInstancesParams +import org.junit.jupiter.api.Disabled +import org.junit.jupiter.api.Test + +internal class ScheduleServiceAsyncTest { + + @Disabled("Mock server tests are disabled") + @Test + fun listInstances() { + val client = CourierOkHttpClientAsync.builder().apiKey("My API Key").build() + val scheduleServiceAsync = client.digests().schedules() + + val digestInstanceListResponseFuture = + scheduleServiceAsync.listInstances( + ScheduleListInstancesParams.builder() + .scheduleId("schedule_id") + .cursor("cursor") + .limit(100L) + .build() + ) + + val digestInstanceListResponse = digestInstanceListResponseFuture.get() + digestInstanceListResponse.validate() + } + + @Disabled("Mock server tests are disabled") + @Test + fun release() { + val client = CourierOkHttpClientAsync.builder().apiKey("My API Key").build() + val scheduleServiceAsync = client.digests().schedules() + + val future = scheduleServiceAsync.release("schedule_id") + + val response = future.get() + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/services/blocking/digests/ScheduleServiceTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/blocking/digests/ScheduleServiceTest.kt new file mode 100644 index 00000000..92b7245d --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/services/blocking/digests/ScheduleServiceTest.kt @@ -0,0 +1,38 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.services.blocking.digests + +import com.courier.client.okhttp.CourierOkHttpClient +import com.courier.models.digests.schedules.ScheduleListInstancesParams +import org.junit.jupiter.api.Disabled +import org.junit.jupiter.api.Test + +internal class ScheduleServiceTest { + + @Disabled("Mock server tests are disabled") + @Test + fun listInstances() { + val client = CourierOkHttpClient.builder().apiKey("My API Key").build() + val scheduleService = client.digests().schedules() + + val digestInstanceListResponse = + scheduleService.listInstances( + ScheduleListInstancesParams.builder() + .scheduleId("schedule_id") + .cursor("cursor") + .limit(100L) + .build() + ) + + digestInstanceListResponse.validate() + } + + @Disabled("Mock server tests are disabled") + @Test + fun release() { + val client = CourierOkHttpClient.builder().apiKey("My API Key").build() + val scheduleService = client.digests().schedules() + + scheduleService.release("schedule_id") + } +} diff --git a/courier-java-proguard-test/src/test/kotlin/com/courier/proguard/ProGuardCompatibilityTest.kt b/courier-java-proguard-test/src/test/kotlin/com/courier/proguard/ProGuardCompatibilityTest.kt index c17a25a0..5f8e6a70 100644 --- a/courier-java-proguard-test/src/test/kotlin/com/courier/proguard/ProGuardCompatibilityTest.kt +++ b/courier-java-proguard-test/src/test/kotlin/com/courier/proguard/ProGuardCompatibilityTest.kt @@ -59,6 +59,7 @@ internal class ProGuardCompatibilityTest { assertThat(client.journeys()).isNotNull() assertThat(client.brands()).isNotNull() assertThat(client.bulk()).isNotNull() + assertThat(client.digests()).isNotNull() assertThat(client.inbound()).isNotNull() assertThat(client.lists()).isNotNull() assertThat(client.messages()).isNotNull() From e911a62de5f150a736100edb78cae0e4f0ca3751 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 12 Jun 2026 21:44:40 +0000 Subject: [PATCH 2/4] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index daedc5af..27e7c567 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 119 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/courier/courier-2ffdd7412416851da17d4cf5b0b82ed842f730866bef1d76653f7ca83d5f622e.yml -openapi_spec_hash: e5296b102c88bb2226842167ba5d8731 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/courier/courier-40a1678baebc2a397e88f984d193460f97b535ad7f8b160a25ae217adce5b369.yml +openapi_spec_hash: a0c742f9a202374774303bc339143422 config_hash: 822a92efc80e63cdb2d496dbd6176620 From 58fbe5b49f8bb199a8e1b61877b4e922387263b0 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 12 Jun 2026 21:57:14 +0000 Subject: [PATCH 3/4] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 27e7c567..6ee7bef5 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 119 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/courier/courier-40a1678baebc2a397e88f984d193460f97b535ad7f8b160a25ae217adce5b369.yml -openapi_spec_hash: a0c742f9a202374774303bc339143422 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/courier/courier-a64bb97c3455b0689de7f6a297ba1dc1e747561ce310ddb18b9c4a5f4d3d510a.yml +openapi_spec_hash: 6a3b89f3ea7600e784902f61680f8f1a config_hash: 822a92efc80e63cdb2d496dbd6176620 From 81bb3b32efed54ac58185ce4c2fc0486385158f5 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 12 Jun 2026 21:57:36 +0000 Subject: [PATCH 4/4] release: 4.15.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 8 ++++++++ build.gradle.kts | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index a817334f..34f6b414 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "4.14.0" + ".": "4.15.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ce148ee..0bdab1ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 4.15.0 (2026-06-12) + +Full Changelog: [v4.14.0...v4.15.0](https://github.com/trycourier/courier-java/compare/v4.14.0...v4.15.0) + +### Features + +* **digests:** document digest REST endpoints in OpenAPI spec ([e145081](https://github.com/trycourier/courier-java/commit/e145081e4ae5b862290944d7fb5b0c125522b0c0)) + ## 4.14.0 (2026-05-28) Full Changelog: [v4.13.1...v4.14.0](https://github.com/trycourier/courier-java/compare/v4.13.1...v4.14.0) diff --git a/build.gradle.kts b/build.gradle.kts index d5fc2de8..31189891 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,7 +8,7 @@ repositories { allprojects { group = "com.courier" - version = "4.14.0" // x-release-please-version + version = "4.15.0" // x-release-please-version } subprojects {