From ba686ac91e66e3f6979623246a9f9b01607839aa Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 14 Apr 2026 00:56:24 +0000 Subject: [PATCH 1/3] fix(types): make note optional in notifications, flatten template response --- .stats.yml | 6 +- .../notifications/NotificationListResponse.kt | 73 +++++++++---------- ...nse.kt => NotificationTemplateResponse.kt} | 43 +++++------ .../notifications/checks/CheckDeleteParams.kt | 1 + .../notifications/checks/CheckListParams.kt | 1 + .../notifications/checks/CheckUpdateParams.kt | 1 + .../async/NotificationServiceAsync.kt | 65 ++++++++--------- .../async/NotificationServiceAsyncImpl.kt | 26 +++---- .../async/notifications/CheckServiceAsync.kt | 3 + .../services/blocking/NotificationService.kt | 59 ++++++++------- .../blocking/NotificationServiceImpl.kt | 26 +++---- .../blocking/notifications/CheckService.kt | 3 + .../NotificationListResponseTest.kt | 6 +- ...kt => NotificationTemplateResponseTest.kt} | 43 ++++++----- .../async/NotificationServiceAsyncTest.kt | 18 ++--- .../blocking/NotificationServiceTest.kt | 12 +-- 16 files changed, 191 insertions(+), 195 deletions(-) rename courier-java-core/src/main/kotlin/com/courier/models/notifications/{NotificationTemplateGetResponse.kt => NotificationTemplateResponse.kt} (96%) rename courier-java-core/src/test/kotlin/com/courier/models/notifications/{NotificationTemplateGetResponseTest.kt => NotificationTemplateResponseTest.kt} (78%) diff --git a/.stats.yml b/.stats.yml index 37cb4404..998581c7 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 103 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/courier%2Fcourier-f0ac5c2fa86eabda773c549f5809d3e2d109e3e1d5a07f6fe1ace18355e4680a.yml -openapi_spec_hash: b25dc0b42dd9386ab4a025bb2143bde6 -config_hash: 6037e4a9909efb8b2edac2dcc907b84f +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/courier%2Fcourier-0f56d7860a1be3ffaea5dea291b20ac92e31c94d54e41cc8a30462dacf2f2d37.yml +openapi_spec_hash: 7e7c6f963e83c5f626c09efa322f476a +config_hash: afcc4f6f8c33ca3f338589e32e086f56 diff --git a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationListResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationListResponse.kt index 65dd898b..d9701228 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationListResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationListResponse.kt @@ -429,10 +429,10 @@ private constructor( private val id: JsonField, private val createdAt: JsonField, private val eventIds: JsonField>, - private val note: JsonField, private val routing: JsonField, private val topicId: JsonField, private val updatedAt: JsonField, + private val note: JsonField, private val tags: JsonField, private val title: JsonField, private val additionalProperties: MutableMap, @@ -447,7 +447,6 @@ private constructor( @JsonProperty("event_ids") @ExcludeMissing eventIds: JsonField> = JsonMissing.of(), - @JsonProperty("note") @ExcludeMissing note: JsonField = JsonMissing.of(), @JsonProperty("routing") @ExcludeMissing routing: JsonField = JsonMissing.of(), @@ -457,16 +456,17 @@ private constructor( @JsonProperty("updated_at") @ExcludeMissing updatedAt: JsonField = JsonMissing.of(), + @JsonProperty("note") @ExcludeMissing note: JsonField = JsonMissing.of(), @JsonProperty("tags") @ExcludeMissing tags: JsonField = JsonMissing.of(), @JsonProperty("title") @ExcludeMissing title: JsonField = JsonMissing.of(), ) : this( id, createdAt, eventIds, - note, routing, topicId, updatedAt, + note, tags, title, mutableMapOf(), @@ -495,13 +495,6 @@ private constructor( */ fun eventIds(): List = eventIds.getRequired("event_ids") - /** - * @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 note(): String = note.getRequired("note") - /** * @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 @@ -523,6 +516,12 @@ private constructor( */ fun updatedAt(): Long = updatedAt.getRequired("updated_at") + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun note(): Optional = note.getOptional("note") + /** * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if * the server responded with an unexpected value). @@ -562,13 +561,6 @@ private constructor( @ExcludeMissing fun _eventIds(): JsonField> = eventIds - /** - * Returns the raw JSON value of [note]. - * - * Unlike [note], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("note") @ExcludeMissing fun _note(): JsonField = note - /** * Returns the raw JSON value of [routing]. * @@ -595,6 +587,13 @@ private constructor( @ExcludeMissing fun _updatedAt(): JsonField = updatedAt + /** + * Returns the raw JSON value of [note]. + * + * Unlike [note], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("note") @ExcludeMissing fun _note(): JsonField = note + /** * Returns the raw JSON value of [tags]. * @@ -631,7 +630,6 @@ private constructor( * .id() * .createdAt() * .eventIds() - * .note() * .routing() * .topicId() * .updatedAt() @@ -646,10 +644,10 @@ private constructor( private var id: JsonField? = null private var createdAt: JsonField? = null private var eventIds: JsonField>? = null - private var note: JsonField? = null private var routing: JsonField? = null private var topicId: JsonField? = null private var updatedAt: JsonField? = null + private var note: JsonField = JsonMissing.of() private var tags: JsonField = JsonMissing.of() private var title: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @@ -659,10 +657,10 @@ private constructor( id = notification.id createdAt = notification.createdAt eventIds = notification.eventIds.map { it.toMutableList() } - note = notification.note routing = notification.routing topicId = notification.topicId updatedAt = notification.updatedAt + note = notification.note tags = notification.tags title = notification.title additionalProperties = notification.additionalProperties.toMutableMap() @@ -716,17 +714,6 @@ private constructor( } } - fun note(note: String) = note(JsonField.of(note)) - - /** - * Sets [Builder.note] to an arbitrary JSON value. - * - * You should usually call [Builder.note] with a well-typed [String] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun note(note: JsonField) = apply { this.note = note } - fun routing(routing: MessageRouting) = routing(JsonField.of(routing)) /** @@ -760,6 +747,17 @@ private constructor( */ fun updatedAt(updatedAt: JsonField) = apply { this.updatedAt = updatedAt } + fun note(note: String) = note(JsonField.of(note)) + + /** + * Sets [Builder.note] to an arbitrary JSON value. + * + * You should usually call [Builder.note] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun note(note: JsonField) = apply { this.note = note } + fun tags(tags: Tags?) = tags(JsonField.ofNullable(tags)) /** Alias for calling [Builder.tags] with `tags.orElse(null)`. */ @@ -820,7 +818,6 @@ private constructor( * .id() * .createdAt() * .eventIds() - * .note() * .routing() * .topicId() * .updatedAt() @@ -833,10 +830,10 @@ private constructor( checkRequired("id", id), checkRequired("createdAt", createdAt), checkRequired("eventIds", eventIds).map { it.toImmutable() }, - checkRequired("note", note), checkRequired("routing", routing), checkRequired("topicId", topicId), checkRequired("updatedAt", updatedAt), + note, tags, title, additionalProperties.toMutableMap(), @@ -853,10 +850,10 @@ private constructor( id() createdAt() eventIds() - note() routing().validate() topicId() updatedAt() + note() tags().ifPresent { it.validate() } title() validated = true @@ -881,10 +878,10 @@ private constructor( (if (id.asKnown().isPresent) 1 else 0) + (if (createdAt.asKnown().isPresent) 1 else 0) + (eventIds.asKnown().getOrNull()?.size ?: 0) + - (if (note.asKnown().isPresent) 1 else 0) + (routing.asKnown().getOrNull()?.validity() ?: 0) + (if (topicId.asKnown().isPresent) 1 else 0) + (if (updatedAt.asKnown().isPresent) 1 else 0) + + (if (note.asKnown().isPresent) 1 else 0) + (tags.asKnown().getOrNull()?.validity() ?: 0) + (if (title.asKnown().isPresent) 1 else 0) @@ -1282,10 +1279,10 @@ private constructor( id == other.id && createdAt == other.createdAt && eventIds == other.eventIds && - note == other.note && routing == other.routing && topicId == other.topicId && updatedAt == other.updatedAt && + note == other.note && tags == other.tags && title == other.title && additionalProperties == other.additionalProperties @@ -1296,10 +1293,10 @@ private constructor( id, createdAt, eventIds, - note, routing, topicId, updatedAt, + note, tags, title, additionalProperties, @@ -1309,7 +1306,7 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "Notification{id=$id, createdAt=$createdAt, eventIds=$eventIds, note=$note, routing=$routing, topicId=$topicId, updatedAt=$updatedAt, tags=$tags, title=$title, additionalProperties=$additionalProperties}" + "Notification{id=$id, createdAt=$createdAt, eventIds=$eventIds, routing=$routing, topicId=$topicId, updatedAt=$updatedAt, note=$note, tags=$tags, title=$title, additionalProperties=$additionalProperties}" } } diff --git a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplateGetResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplateResponse.kt similarity index 96% rename from courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplateGetResponse.kt rename to courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplateResponse.kt index 5fecbc80..685a35ac 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplateGetResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplateResponse.kt @@ -22,10 +22,10 @@ import java.util.Optional import kotlin.jvm.optionals.getOrNull /** - * Envelope response for GET /notifications/{id}. The notification object mirrors the POST/PUT input - * shape. Nullable fields return null when unset. + * Response for GET /notifications/{id}, POST /notifications, and PUT /notifications/{id}. Wraps the + * template payload inside a `notification` key alongside metadata. */ -class NotificationTemplateGetResponse +class NotificationTemplateResponse @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val created: JsonField, @@ -157,8 +157,7 @@ private constructor( companion object { /** - * Returns a mutable builder for constructing an instance of - * [NotificationTemplateGetResponse]. + * Returns a mutable builder for constructing an instance of [NotificationTemplateResponse]. * * The following fields are required: * ```java @@ -171,7 +170,7 @@ private constructor( @JvmStatic fun builder() = Builder() } - /** A builder for [NotificationTemplateGetResponse]. */ + /** A builder for [NotificationTemplateResponse]. */ class Builder internal constructor() { private var created: JsonField? = null @@ -183,17 +182,15 @@ private constructor( private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic - internal fun from(notificationTemplateGetResponse: NotificationTemplateGetResponse) = - apply { - created = notificationTemplateGetResponse.created - creator = notificationTemplateGetResponse.creator - notification = notificationTemplateGetResponse.notification - state = notificationTemplateGetResponse.state - updated = notificationTemplateGetResponse.updated - updater = notificationTemplateGetResponse.updater - additionalProperties = - notificationTemplateGetResponse.additionalProperties.toMutableMap() - } + internal fun from(notificationTemplateResponse: NotificationTemplateResponse) = apply { + created = notificationTemplateResponse.created + creator = notificationTemplateResponse.creator + notification = notificationTemplateResponse.notification + state = notificationTemplateResponse.state + updated = notificationTemplateResponse.updated + updater = notificationTemplateResponse.updater + additionalProperties = notificationTemplateResponse.additionalProperties.toMutableMap() + } /** Epoch milliseconds when the template was created. */ fun created(created: Long) = created(JsonField.of(created)) @@ -287,7 +284,7 @@ private constructor( } /** - * Returns an immutable instance of [NotificationTemplateGetResponse]. + * Returns an immutable instance of [NotificationTemplateResponse]. * * Further updates to this [Builder] will not mutate the returned instance. * @@ -301,8 +298,8 @@ private constructor( * * @throws IllegalStateException if any required field is unset. */ - fun build(): NotificationTemplateGetResponse = - NotificationTemplateGetResponse( + fun build(): NotificationTemplateResponse = + NotificationTemplateResponse( checkRequired("created", created), checkRequired("creator", creator), checkRequired("notification", notification), @@ -315,7 +312,7 @@ private constructor( private var validated: Boolean = false - fun validate(): NotificationTemplateGetResponse = apply { + fun validate(): NotificationTemplateResponse = apply { if (validated) { return@apply } @@ -942,7 +939,7 @@ private constructor( return true } - return other is NotificationTemplateGetResponse && + return other is NotificationTemplateResponse && created == other.created && creator == other.creator && notification == other.notification && @@ -959,5 +956,5 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "NotificationTemplateGetResponse{created=$created, creator=$creator, notification=$notification, state=$state, updated=$updated, updater=$updater, additionalProperties=$additionalProperties}" + "NotificationTemplateResponse{created=$created, creator=$creator, notification=$notification, state=$state, updated=$updated, updater=$updater, additionalProperties=$additionalProperties}" } diff --git a/courier-java-core/src/main/kotlin/com/courier/models/notifications/checks/CheckDeleteParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/notifications/checks/CheckDeleteParams.kt index 6f36b5d3..75c46079 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/notifications/checks/CheckDeleteParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/notifications/checks/CheckDeleteParams.kt @@ -12,6 +12,7 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull +/** Cancel a notification template submission. */ class CheckDeleteParams private constructor( private val id: String, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/notifications/checks/CheckListParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/notifications/checks/CheckListParams.kt index 13a65318..3da25676 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/notifications/checks/CheckListParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/notifications/checks/CheckListParams.kt @@ -10,6 +10,7 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull +/** Retrieve the checks for a notification template submission. */ class CheckListParams private constructor( private val id: String, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/notifications/checks/CheckUpdateParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/notifications/checks/CheckUpdateParams.kt index aae1bbce..567553e6 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/notifications/checks/CheckUpdateParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/notifications/checks/CheckUpdateParams.kt @@ -23,6 +23,7 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull +/** Replace the checks for a notification template submission. */ class CheckUpdateParams private constructor( private val id: String, diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/NotificationServiceAsync.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/NotificationServiceAsync.kt index b005a4e2..37cfa66a 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/NotificationServiceAsync.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/NotificationServiceAsync.kt @@ -21,7 +21,7 @@ import com.courier.models.notifications.NotificationRetrieveContentParams import com.courier.models.notifications.NotificationRetrieveContentResponse import com.courier.models.notifications.NotificationRetrieveParams import com.courier.models.notifications.NotificationTemplateCreateRequest -import com.courier.models.notifications.NotificationTemplateGetResponse +import com.courier.models.notifications.NotificationTemplateResponse import com.courier.models.notifications.NotificationTemplateVersionListResponse import com.courier.services.async.notifications.CheckServiceAsync import java.util.concurrent.CompletableFuture @@ -47,21 +47,20 @@ interface NotificationServiceAsync { * Create a notification template. Requires all fields in the notification object. Templates are * created in draft state by default. */ - fun create( - params: NotificationCreateParams - ): CompletableFuture = create(params, RequestOptions.none()) + fun create(params: NotificationCreateParams): CompletableFuture = + create(params, RequestOptions.none()) /** @see create */ fun create( params: NotificationCreateParams, requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture + ): CompletableFuture /** @see create */ fun create( notificationTemplateCreateRequest: NotificationTemplateCreateRequest, requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture = + ): CompletableFuture = create( NotificationCreateParams.builder() .notificationTemplateCreateRequest(notificationTemplateCreateRequest) @@ -72,14 +71,14 @@ interface NotificationServiceAsync { /** @see create */ fun create( notificationTemplateCreateRequest: NotificationTemplateCreateRequest - ): CompletableFuture = + ): CompletableFuture = create(notificationTemplateCreateRequest, RequestOptions.none()) /** * Retrieve a notification template by ID. Returns the published version by default. Pass * version=draft to retrieve an unpublished template. */ - fun retrieve(id: String): CompletableFuture = + fun retrieve(id: String): CompletableFuture = retrieve(id, NotificationRetrieveParams.none()) /** @see retrieve */ @@ -87,32 +86,31 @@ interface NotificationServiceAsync { id: String, params: NotificationRetrieveParams = NotificationRetrieveParams.none(), requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture = + ): CompletableFuture = retrieve(params.toBuilder().id(id).build(), requestOptions) /** @see retrieve */ fun retrieve( id: String, params: NotificationRetrieveParams = NotificationRetrieveParams.none(), - ): CompletableFuture = - retrieve(id, params, RequestOptions.none()) + ): CompletableFuture = retrieve(id, params, RequestOptions.none()) /** @see retrieve */ fun retrieve( params: NotificationRetrieveParams, requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture + ): CompletableFuture /** @see retrieve */ fun retrieve( params: NotificationRetrieveParams - ): CompletableFuture = retrieve(params, RequestOptions.none()) + ): CompletableFuture = retrieve(params, RequestOptions.none()) /** @see retrieve */ fun retrieve( id: String, requestOptions: RequestOptions, - ): CompletableFuture = + ): CompletableFuture = retrieve(id, NotificationRetrieveParams.none(), requestOptions) /** List notification templates in your workspace. */ @@ -330,27 +328,26 @@ interface NotificationServiceAsync { fun replace( id: String, params: NotificationReplaceParams, - ): CompletableFuture = - replace(id, params, RequestOptions.none()) + ): CompletableFuture = replace(id, params, RequestOptions.none()) /** @see replace */ fun replace( id: String, params: NotificationReplaceParams, requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture = + ): CompletableFuture = replace(params.toBuilder().id(id).build(), requestOptions) /** @see replace */ fun replace( params: NotificationReplaceParams - ): CompletableFuture = replace(params, RequestOptions.none()) + ): CompletableFuture = replace(params, RequestOptions.none()) /** @see replace */ fun replace( params: NotificationReplaceParams, requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture + ): CompletableFuture /** * Retrieve the content of a notification template. The response shape depends on whether the @@ -417,20 +414,20 @@ interface NotificationServiceAsync { */ fun create( params: NotificationCreateParams - ): CompletableFuture> = + ): CompletableFuture> = create(params, RequestOptions.none()) /** @see create */ fun create( params: NotificationCreateParams, requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture> + ): CompletableFuture> /** @see create */ fun create( notificationTemplateCreateRequest: NotificationTemplateCreateRequest, requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture> = + ): CompletableFuture> = create( NotificationCreateParams.builder() .notificationTemplateCreateRequest(notificationTemplateCreateRequest) @@ -441,16 +438,14 @@ interface NotificationServiceAsync { /** @see create */ fun create( notificationTemplateCreateRequest: NotificationTemplateCreateRequest - ): CompletableFuture> = + ): CompletableFuture> = create(notificationTemplateCreateRequest, RequestOptions.none()) /** * Returns a raw HTTP response for `get /notifications/{id}`, but is otherwise the same as * [NotificationServiceAsync.retrieve]. */ - fun retrieve( - id: String - ): CompletableFuture> = + fun retrieve(id: String): CompletableFuture> = retrieve(id, NotificationRetrieveParams.none()) /** @see retrieve */ @@ -458,33 +453,33 @@ interface NotificationServiceAsync { id: String, params: NotificationRetrieveParams = NotificationRetrieveParams.none(), requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture> = + ): CompletableFuture> = retrieve(params.toBuilder().id(id).build(), requestOptions) /** @see retrieve */ fun retrieve( id: String, params: NotificationRetrieveParams = NotificationRetrieveParams.none(), - ): CompletableFuture> = + ): CompletableFuture> = retrieve(id, params, RequestOptions.none()) /** @see retrieve */ fun retrieve( params: NotificationRetrieveParams, requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture> + ): CompletableFuture> /** @see retrieve */ fun retrieve( params: NotificationRetrieveParams - ): CompletableFuture> = + ): CompletableFuture> = retrieve(params, RequestOptions.none()) /** @see retrieve */ fun retrieve( id: String, requestOptions: RequestOptions, - ): CompletableFuture> = + ): CompletableFuture> = retrieve(id, NotificationRetrieveParams.none(), requestOptions) /** @@ -722,7 +717,7 @@ interface NotificationServiceAsync { fun replace( id: String, params: NotificationReplaceParams, - ): CompletableFuture> = + ): CompletableFuture> = replace(id, params, RequestOptions.none()) /** @see replace */ @@ -730,20 +725,20 @@ interface NotificationServiceAsync { id: String, params: NotificationReplaceParams, requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture> = + ): CompletableFuture> = replace(params.toBuilder().id(id).build(), requestOptions) /** @see replace */ fun replace( params: NotificationReplaceParams - ): CompletableFuture> = + ): CompletableFuture> = replace(params, RequestOptions.none()) /** @see replace */ fun replace( params: NotificationReplaceParams, requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture> + ): CompletableFuture> /** * Returns a raw HTTP response for `get /notifications/{id}/content`, but is otherwise the diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/NotificationServiceAsyncImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/NotificationServiceAsyncImpl.kt index 80b8664a..dd19c526 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/NotificationServiceAsyncImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/NotificationServiceAsyncImpl.kt @@ -31,7 +31,7 @@ import com.courier.models.notifications.NotificationReplaceParams import com.courier.models.notifications.NotificationRetrieveContentParams import com.courier.models.notifications.NotificationRetrieveContentResponse import com.courier.models.notifications.NotificationRetrieveParams -import com.courier.models.notifications.NotificationTemplateGetResponse +import com.courier.models.notifications.NotificationTemplateResponse import com.courier.models.notifications.NotificationTemplateVersionListResponse import com.courier.services.async.notifications.CheckServiceAsync import com.courier.services.async.notifications.CheckServiceAsyncImpl @@ -58,14 +58,14 @@ class NotificationServiceAsyncImpl internal constructor(private val clientOption override fun create( params: NotificationCreateParams, requestOptions: RequestOptions, - ): CompletableFuture = + ): CompletableFuture = // post /notifications withRawResponse().create(params, requestOptions).thenApply { it.parse() } override fun retrieve( params: NotificationRetrieveParams, requestOptions: RequestOptions, - ): CompletableFuture = + ): CompletableFuture = // get /notifications/{id} withRawResponse().retrieve(params, requestOptions).thenApply { it.parse() } @@ -121,7 +121,7 @@ class NotificationServiceAsyncImpl internal constructor(private val clientOption override fun replace( params: NotificationReplaceParams, requestOptions: RequestOptions, - ): CompletableFuture = + ): CompletableFuture = // put /notifications/{id} withRawResponse().replace(params, requestOptions).thenApply { it.parse() } @@ -151,13 +151,13 @@ class NotificationServiceAsyncImpl internal constructor(private val clientOption override fun checks(): CheckServiceAsync.WithRawResponse = checks - private val createHandler: Handler = - jsonHandler(clientOptions.jsonMapper) + private val createHandler: Handler = + jsonHandler(clientOptions.jsonMapper) override fun create( params: NotificationCreateParams, requestOptions: RequestOptions, - ): CompletableFuture> { + ): CompletableFuture> { val request = HttpRequest.builder() .method(HttpMethod.POST) @@ -182,13 +182,13 @@ class NotificationServiceAsyncImpl internal constructor(private val clientOption } } - private val retrieveHandler: Handler = - jsonHandler(clientOptions.jsonMapper) + private val retrieveHandler: Handler = + jsonHandler(clientOptions.jsonMapper) override fun retrieve( params: NotificationRetrieveParams, requestOptions: RequestOptions, - ): CompletableFuture> { + ): CompletableFuture> { // We check here instead of in the params builder because this can be specified // positionally or in the params class. checkRequired("id", params.id().getOrNull()) @@ -444,13 +444,13 @@ class NotificationServiceAsyncImpl internal constructor(private val clientOption } } - private val replaceHandler: Handler = - jsonHandler(clientOptions.jsonMapper) + private val replaceHandler: Handler = + jsonHandler(clientOptions.jsonMapper) override fun replace( params: NotificationReplaceParams, requestOptions: RequestOptions, - ): CompletableFuture> { + ): CompletableFuture> { // We check here instead of in the params builder because this can be specified // positionally or in the params class. checkRequired("id", params.id().getOrNull()) diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/notifications/CheckServiceAsync.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/notifications/CheckServiceAsync.kt index 58e64836..89c9922c 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/notifications/CheckServiceAsync.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/notifications/CheckServiceAsync.kt @@ -28,6 +28,7 @@ interface CheckServiceAsync { */ fun withOptions(modifier: Consumer): CheckServiceAsync + /** Replace the checks for a notification template submission. */ fun update( submissionId: String, params: CheckUpdateParams, @@ -51,6 +52,7 @@ interface CheckServiceAsync { requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture + /** Retrieve the checks for a notification template submission. */ fun list(submissionId: String, params: CheckListParams): CompletableFuture = list(submissionId, params, RequestOptions.none()) @@ -72,6 +74,7 @@ interface CheckServiceAsync { requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture + /** Cancel a notification template submission. */ fun delete(submissionId: String, params: CheckDeleteParams): CompletableFuture = delete(submissionId, params, RequestOptions.none()) diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/NotificationService.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/NotificationService.kt index c9097206..e2b77916 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/NotificationService.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/NotificationService.kt @@ -21,7 +21,7 @@ import com.courier.models.notifications.NotificationRetrieveContentParams import com.courier.models.notifications.NotificationRetrieveContentResponse import com.courier.models.notifications.NotificationRetrieveParams import com.courier.models.notifications.NotificationTemplateCreateRequest -import com.courier.models.notifications.NotificationTemplateGetResponse +import com.courier.models.notifications.NotificationTemplateResponse import com.courier.models.notifications.NotificationTemplateVersionListResponse import com.courier.services.blocking.notifications.CheckService import com.google.errorprone.annotations.MustBeClosed @@ -47,20 +47,20 @@ interface NotificationService { * Create a notification template. Requires all fields in the notification object. Templates are * created in draft state by default. */ - fun create(params: NotificationCreateParams): NotificationTemplateGetResponse = + fun create(params: NotificationCreateParams): NotificationTemplateResponse = create(params, RequestOptions.none()) /** @see create */ fun create( params: NotificationCreateParams, requestOptions: RequestOptions = RequestOptions.none(), - ): NotificationTemplateGetResponse + ): NotificationTemplateResponse /** @see create */ fun create( notificationTemplateCreateRequest: NotificationTemplateCreateRequest, requestOptions: RequestOptions = RequestOptions.none(), - ): NotificationTemplateGetResponse = + ): NotificationTemplateResponse = create( NotificationCreateParams.builder() .notificationTemplateCreateRequest(notificationTemplateCreateRequest) @@ -71,14 +71,14 @@ interface NotificationService { /** @see create */ fun create( notificationTemplateCreateRequest: NotificationTemplateCreateRequest - ): NotificationTemplateGetResponse = + ): NotificationTemplateResponse = create(notificationTemplateCreateRequest, RequestOptions.none()) /** * Retrieve a notification template by ID. Returns the published version by default. Pass * version=draft to retrieve an unpublished template. */ - fun retrieve(id: String): NotificationTemplateGetResponse = + fun retrieve(id: String): NotificationTemplateResponse = retrieve(id, NotificationRetrieveParams.none()) /** @see retrieve */ @@ -86,26 +86,26 @@ interface NotificationService { id: String, params: NotificationRetrieveParams = NotificationRetrieveParams.none(), requestOptions: RequestOptions = RequestOptions.none(), - ): NotificationTemplateGetResponse = retrieve(params.toBuilder().id(id).build(), requestOptions) + ): NotificationTemplateResponse = retrieve(params.toBuilder().id(id).build(), requestOptions) /** @see retrieve */ fun retrieve( id: String, params: NotificationRetrieveParams = NotificationRetrieveParams.none(), - ): NotificationTemplateGetResponse = retrieve(id, params, RequestOptions.none()) + ): NotificationTemplateResponse = retrieve(id, params, RequestOptions.none()) /** @see retrieve */ fun retrieve( params: NotificationRetrieveParams, requestOptions: RequestOptions = RequestOptions.none(), - ): NotificationTemplateGetResponse + ): NotificationTemplateResponse /** @see retrieve */ - fun retrieve(params: NotificationRetrieveParams): NotificationTemplateGetResponse = + fun retrieve(params: NotificationRetrieveParams): NotificationTemplateResponse = retrieve(params, RequestOptions.none()) /** @see retrieve */ - fun retrieve(id: String, requestOptions: RequestOptions): NotificationTemplateGetResponse = + fun retrieve(id: String, requestOptions: RequestOptions): NotificationTemplateResponse = retrieve(id, NotificationRetrieveParams.none(), requestOptions) /** List notification templates in your workspace. */ @@ -301,7 +301,7 @@ interface NotificationService { ): NotificationContentMutationResponse /** Replace a notification template. All fields are required. */ - fun replace(id: String, params: NotificationReplaceParams): NotificationTemplateGetResponse = + fun replace(id: String, params: NotificationReplaceParams): NotificationTemplateResponse = replace(id, params, RequestOptions.none()) /** @see replace */ @@ -309,17 +309,17 @@ interface NotificationService { id: String, params: NotificationReplaceParams, requestOptions: RequestOptions = RequestOptions.none(), - ): NotificationTemplateGetResponse = replace(params.toBuilder().id(id).build(), requestOptions) + ): NotificationTemplateResponse = replace(params.toBuilder().id(id).build(), requestOptions) /** @see replace */ - fun replace(params: NotificationReplaceParams): NotificationTemplateGetResponse = + fun replace(params: NotificationReplaceParams): NotificationTemplateResponse = replace(params, RequestOptions.none()) /** @see replace */ fun replace( params: NotificationReplaceParams, requestOptions: RequestOptions = RequestOptions.none(), - ): NotificationTemplateGetResponse + ): NotificationTemplateResponse /** * Retrieve the content of a notification template. The response shape depends on whether the @@ -384,21 +384,21 @@ interface NotificationService { @MustBeClosed fun create( params: NotificationCreateParams - ): HttpResponseFor = create(params, RequestOptions.none()) + ): HttpResponseFor = create(params, RequestOptions.none()) /** @see create */ @MustBeClosed fun create( params: NotificationCreateParams, requestOptions: RequestOptions = RequestOptions.none(), - ): HttpResponseFor + ): HttpResponseFor /** @see create */ @MustBeClosed fun create( notificationTemplateCreateRequest: NotificationTemplateCreateRequest, requestOptions: RequestOptions = RequestOptions.none(), - ): HttpResponseFor = + ): HttpResponseFor = create( NotificationCreateParams.builder() .notificationTemplateCreateRequest(notificationTemplateCreateRequest) @@ -410,7 +410,7 @@ interface NotificationService { @MustBeClosed fun create( notificationTemplateCreateRequest: NotificationTemplateCreateRequest - ): HttpResponseFor = + ): HttpResponseFor = create(notificationTemplateCreateRequest, RequestOptions.none()) /** @@ -418,7 +418,7 @@ interface NotificationService { * [NotificationService.retrieve]. */ @MustBeClosed - fun retrieve(id: String): HttpResponseFor = + fun retrieve(id: String): HttpResponseFor = retrieve(id, NotificationRetrieveParams.none()) /** @see retrieve */ @@ -427,7 +427,7 @@ interface NotificationService { id: String, params: NotificationRetrieveParams = NotificationRetrieveParams.none(), requestOptions: RequestOptions = RequestOptions.none(), - ): HttpResponseFor = + ): HttpResponseFor = retrieve(params.toBuilder().id(id).build(), requestOptions) /** @see retrieve */ @@ -435,7 +435,7 @@ interface NotificationService { fun retrieve( id: String, params: NotificationRetrieveParams = NotificationRetrieveParams.none(), - ): HttpResponseFor = + ): HttpResponseFor = retrieve(id, params, RequestOptions.none()) /** @see retrieve */ @@ -443,21 +443,20 @@ interface NotificationService { fun retrieve( params: NotificationRetrieveParams, requestOptions: RequestOptions = RequestOptions.none(), - ): HttpResponseFor + ): HttpResponseFor /** @see retrieve */ @MustBeClosed fun retrieve( params: NotificationRetrieveParams - ): HttpResponseFor = - retrieve(params, RequestOptions.none()) + ): HttpResponseFor = retrieve(params, RequestOptions.none()) /** @see retrieve */ @MustBeClosed fun retrieve( id: String, requestOptions: RequestOptions, - ): HttpResponseFor = + ): HttpResponseFor = retrieve(id, NotificationRetrieveParams.none(), requestOptions) /** @@ -720,7 +719,7 @@ interface NotificationService { fun replace( id: String, params: NotificationReplaceParams, - ): HttpResponseFor = + ): HttpResponseFor = replace(id, params, RequestOptions.none()) /** @see replace */ @@ -729,21 +728,21 @@ interface NotificationService { id: String, params: NotificationReplaceParams, requestOptions: RequestOptions = RequestOptions.none(), - ): HttpResponseFor = + ): HttpResponseFor = replace(params.toBuilder().id(id).build(), requestOptions) /** @see replace */ @MustBeClosed fun replace( params: NotificationReplaceParams - ): HttpResponseFor = replace(params, RequestOptions.none()) + ): HttpResponseFor = replace(params, RequestOptions.none()) /** @see replace */ @MustBeClosed fun replace( params: NotificationReplaceParams, requestOptions: RequestOptions = RequestOptions.none(), - ): HttpResponseFor + ): HttpResponseFor /** * Returns a raw HTTP response for `get /notifications/{id}/content`, but is otherwise the diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/NotificationServiceImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/NotificationServiceImpl.kt index fa74685f..52ae5eb6 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/NotificationServiceImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/NotificationServiceImpl.kt @@ -31,7 +31,7 @@ import com.courier.models.notifications.NotificationReplaceParams import com.courier.models.notifications.NotificationRetrieveContentParams import com.courier.models.notifications.NotificationRetrieveContentResponse import com.courier.models.notifications.NotificationRetrieveParams -import com.courier.models.notifications.NotificationTemplateGetResponse +import com.courier.models.notifications.NotificationTemplateResponse import com.courier.models.notifications.NotificationTemplateVersionListResponse import com.courier.services.blocking.notifications.CheckService import com.courier.services.blocking.notifications.CheckServiceImpl @@ -57,14 +57,14 @@ class NotificationServiceImpl internal constructor(private val clientOptions: Cl override fun create( params: NotificationCreateParams, requestOptions: RequestOptions, - ): NotificationTemplateGetResponse = + ): NotificationTemplateResponse = // post /notifications withRawResponse().create(params, requestOptions).parse() override fun retrieve( params: NotificationRetrieveParams, requestOptions: RequestOptions, - ): NotificationTemplateGetResponse = + ): NotificationTemplateResponse = // get /notifications/{id} withRawResponse().retrieve(params, requestOptions).parse() @@ -116,7 +116,7 @@ class NotificationServiceImpl internal constructor(private val clientOptions: Cl override fun replace( params: NotificationReplaceParams, requestOptions: RequestOptions, - ): NotificationTemplateGetResponse = + ): NotificationTemplateResponse = // put /notifications/{id} withRawResponse().replace(params, requestOptions).parse() @@ -146,13 +146,13 @@ class NotificationServiceImpl internal constructor(private val clientOptions: Cl override fun checks(): CheckService.WithRawResponse = checks - private val createHandler: Handler = - jsonHandler(clientOptions.jsonMapper) + private val createHandler: Handler = + jsonHandler(clientOptions.jsonMapper) override fun create( params: NotificationCreateParams, requestOptions: RequestOptions, - ): HttpResponseFor { + ): HttpResponseFor { val request = HttpRequest.builder() .method(HttpMethod.POST) @@ -174,13 +174,13 @@ class NotificationServiceImpl internal constructor(private val clientOptions: Cl } } - private val retrieveHandler: Handler = - jsonHandler(clientOptions.jsonMapper) + private val retrieveHandler: Handler = + jsonHandler(clientOptions.jsonMapper) override fun retrieve( params: NotificationRetrieveParams, requestOptions: RequestOptions, - ): HttpResponseFor { + ): HttpResponseFor { // We check here instead of in the params builder because this can be specified // positionally or in the params class. checkRequired("id", params.id().getOrNull()) @@ -412,13 +412,13 @@ class NotificationServiceImpl internal constructor(private val clientOptions: Cl } } - private val replaceHandler: Handler = - jsonHandler(clientOptions.jsonMapper) + private val replaceHandler: Handler = + jsonHandler(clientOptions.jsonMapper) override fun replace( params: NotificationReplaceParams, requestOptions: RequestOptions, - ): HttpResponseFor { + ): HttpResponseFor { // We check here instead of in the params builder because this can be specified // positionally or in the params class. checkRequired("id", params.id().getOrNull()) diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/notifications/CheckService.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/notifications/CheckService.kt index e5df29ef..f2fe3c00 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/notifications/CheckService.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/notifications/CheckService.kt @@ -28,6 +28,7 @@ interface CheckService { */ fun withOptions(modifier: Consumer): CheckService + /** Replace the checks for a notification template submission. */ fun update(submissionId: String, params: CheckUpdateParams): CheckUpdateResponse = update(submissionId, params, RequestOptions.none()) @@ -49,6 +50,7 @@ interface CheckService { requestOptions: RequestOptions = RequestOptions.none(), ): CheckUpdateResponse + /** Retrieve the checks for a notification template submission. */ fun list(submissionId: String, params: CheckListParams): CheckListResponse = list(submissionId, params, RequestOptions.none()) @@ -69,6 +71,7 @@ interface CheckService { requestOptions: RequestOptions = RequestOptions.none(), ): CheckListResponse + /** Cancel a notification template submission. */ fun delete(submissionId: String, params: CheckDeleteParams) = delete(submissionId, params, RequestOptions.none()) diff --git a/courier-java-core/src/test/kotlin/com/courier/models/notifications/NotificationListResponseTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/notifications/NotificationListResponseTest.kt index fcd413e5..88a47c72 100644 --- a/courier-java-core/src/test/kotlin/com/courier/models/notifications/NotificationListResponseTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/models/notifications/NotificationListResponseTest.kt @@ -21,7 +21,6 @@ internal class NotificationListResponseTest { .id("id") .createdAt(0L) .addEventId("string") - .note("note") .routing( MessageRouting.builder() .addChannel("string") @@ -30,6 +29,7 @@ internal class NotificationListResponseTest { ) .topicId("topic_id") .updatedAt(0L) + .note("note") .tags( NotificationListResponse.Result.Notification.Tags.builder() .addData( @@ -54,7 +54,6 @@ internal class NotificationListResponseTest { .id("id") .createdAt(0L) .addEventId("string") - .note("note") .routing( MessageRouting.builder() .addChannel("string") @@ -63,6 +62,7 @@ internal class NotificationListResponseTest { ) .topicId("topic_id") .updatedAt(0L) + .note("note") .tags( NotificationListResponse.Result.Notification.Tags.builder() .addData( @@ -90,7 +90,6 @@ internal class NotificationListResponseTest { .id("id") .createdAt(0L) .addEventId("string") - .note("note") .routing( MessageRouting.builder() .addChannel("string") @@ -99,6 +98,7 @@ internal class NotificationListResponseTest { ) .topicId("topic_id") .updatedAt(0L) + .note("note") .tags( NotificationListResponse.Result.Notification.Tags.builder() .addData( diff --git a/courier-java-core/src/test/kotlin/com/courier/models/notifications/NotificationTemplateGetResponseTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/notifications/NotificationTemplateResponseTest.kt similarity index 78% rename from courier-java-core/src/test/kotlin/com/courier/models/notifications/NotificationTemplateGetResponseTest.kt rename to courier-java-core/src/test/kotlin/com/courier/models/notifications/NotificationTemplateResponseTest.kt index 720ed454..f7dfc007 100644 --- a/courier-java-core/src/test/kotlin/com/courier/models/notifications/NotificationTemplateGetResponseTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/models/notifications/NotificationTemplateResponseTest.kt @@ -9,16 +9,16 @@ import com.fasterxml.jackson.module.kotlin.jacksonTypeRef import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test -internal class NotificationTemplateGetResponseTest { +internal class NotificationTemplateResponseTest { @Test fun create() { - val notificationTemplateGetResponse = - NotificationTemplateGetResponse.builder() + val notificationTemplateResponse = + NotificationTemplateResponse.builder() .created(0L) .creator("creator") .notification( - NotificationTemplateGetResponse.Notification.builder() + NotificationTemplateResponse.Notification.builder() .brand(NotificationTemplatePayload.Brand.builder().id("id").build()) .content( ElementalContent.builder() @@ -49,16 +49,16 @@ internal class NotificationTemplateGetResponseTest { .id("id") .build() ) - .state(NotificationTemplateGetResponse.State.DRAFT) + .state(NotificationTemplateResponse.State.DRAFT) .updated(0L) .updater("updater") .build() - assertThat(notificationTemplateGetResponse.created()).isEqualTo(0L) - assertThat(notificationTemplateGetResponse.creator()).isEqualTo("creator") - assertThat(notificationTemplateGetResponse.notification()) + assertThat(notificationTemplateResponse.created()).isEqualTo(0L) + assertThat(notificationTemplateResponse.creator()).isEqualTo("creator") + assertThat(notificationTemplateResponse.notification()) .isEqualTo( - NotificationTemplateGetResponse.Notification.builder() + NotificationTemplateResponse.Notification.builder() .brand(NotificationTemplatePayload.Brand.builder().id("id").build()) .content( ElementalContent.builder() @@ -89,21 +89,21 @@ internal class NotificationTemplateGetResponseTest { .id("id") .build() ) - assertThat(notificationTemplateGetResponse.state()) - .isEqualTo(NotificationTemplateGetResponse.State.DRAFT) - assertThat(notificationTemplateGetResponse.updated()).contains(0L) - assertThat(notificationTemplateGetResponse.updater()).contains("updater") + assertThat(notificationTemplateResponse.state()) + .isEqualTo(NotificationTemplateResponse.State.DRAFT) + assertThat(notificationTemplateResponse.updated()).contains(0L) + assertThat(notificationTemplateResponse.updater()).contains("updater") } @Test fun roundtrip() { val jsonMapper = jsonMapper() - val notificationTemplateGetResponse = - NotificationTemplateGetResponse.builder() + val notificationTemplateResponse = + NotificationTemplateResponse.builder() .created(0L) .creator("creator") .notification( - NotificationTemplateGetResponse.Notification.builder() + NotificationTemplateResponse.Notification.builder() .brand(NotificationTemplatePayload.Brand.builder().id("id").build()) .content( ElementalContent.builder() @@ -134,18 +134,17 @@ internal class NotificationTemplateGetResponseTest { .id("id") .build() ) - .state(NotificationTemplateGetResponse.State.DRAFT) + .state(NotificationTemplateResponse.State.DRAFT) .updated(0L) .updater("updater") .build() - val roundtrippedNotificationTemplateGetResponse = + val roundtrippedNotificationTemplateResponse = jsonMapper.readValue( - jsonMapper.writeValueAsString(notificationTemplateGetResponse), - jacksonTypeRef(), + jsonMapper.writeValueAsString(notificationTemplateResponse), + jacksonTypeRef(), ) - assertThat(roundtrippedNotificationTemplateGetResponse) - .isEqualTo(notificationTemplateGetResponse) + assertThat(roundtrippedNotificationTemplateResponse).isEqualTo(notificationTemplateResponse) } } diff --git a/courier-java-core/src/test/kotlin/com/courier/services/async/NotificationServiceAsyncTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/async/NotificationServiceAsyncTest.kt index 3babf671..75c20269 100644 --- a/courier-java-core/src/test/kotlin/com/courier/services/async/NotificationServiceAsyncTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/services/async/NotificationServiceAsyncTest.kt @@ -34,7 +34,7 @@ internal class NotificationServiceAsyncTest { val client = CourierOkHttpClientAsync.builder().apiKey("My API Key").build() val notificationServiceAsync = client.notifications() - val notificationTemplateGetResponseFuture = + val notificationTemplateResponseFuture = notificationServiceAsync.create( NotificationTemplateCreateRequest.builder() .notification( @@ -71,8 +71,8 @@ internal class NotificationServiceAsyncTest { .build() ) - val notificationTemplateGetResponse = notificationTemplateGetResponseFuture.get() - notificationTemplateGetResponse.validate() + val notificationTemplateResponse = notificationTemplateResponseFuture.get() + notificationTemplateResponse.validate() } @Disabled("Mock server tests are disabled") @@ -81,13 +81,13 @@ internal class NotificationServiceAsyncTest { val client = CourierOkHttpClientAsync.builder().apiKey("My API Key").build() val notificationServiceAsync = client.notifications() - val notificationTemplateGetResponseFuture = + val notificationTemplateResponseFuture = notificationServiceAsync.retrieve( NotificationRetrieveParams.builder().id("id").version("version").build() ) - val notificationTemplateGetResponse = notificationTemplateGetResponseFuture.get() - notificationTemplateGetResponse.validate() + val notificationTemplateResponse = notificationTemplateResponseFuture.get() + notificationTemplateResponse.validate() } @Disabled("Mock server tests are disabled") @@ -261,7 +261,7 @@ internal class NotificationServiceAsyncTest { val client = CourierOkHttpClientAsync.builder().apiKey("My API Key").build() val notificationServiceAsync = client.notifications() - val notificationTemplateGetResponseFuture = + val notificationTemplateResponseFuture = notificationServiceAsync.replace( NotificationReplaceParams.builder() .id("id") @@ -302,8 +302,8 @@ internal class NotificationServiceAsyncTest { .build() ) - val notificationTemplateGetResponse = notificationTemplateGetResponseFuture.get() - notificationTemplateGetResponse.validate() + val notificationTemplateResponse = notificationTemplateResponseFuture.get() + notificationTemplateResponse.validate() } @Disabled("Mock server tests are disabled") diff --git a/courier-java-core/src/test/kotlin/com/courier/services/blocking/NotificationServiceTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/blocking/NotificationServiceTest.kt index 223982c2..61ab6c5a 100644 --- a/courier-java-core/src/test/kotlin/com/courier/services/blocking/NotificationServiceTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/services/blocking/NotificationServiceTest.kt @@ -34,7 +34,7 @@ internal class NotificationServiceTest { val client = CourierOkHttpClient.builder().apiKey("My API Key").build() val notificationService = client.notifications() - val notificationTemplateGetResponse = + val notificationTemplateResponse = notificationService.create( NotificationTemplateCreateRequest.builder() .notification( @@ -71,7 +71,7 @@ internal class NotificationServiceTest { .build() ) - notificationTemplateGetResponse.validate() + notificationTemplateResponse.validate() } @Disabled("Mock server tests are disabled") @@ -80,12 +80,12 @@ internal class NotificationServiceTest { val client = CourierOkHttpClient.builder().apiKey("My API Key").build() val notificationService = client.notifications() - val notificationTemplateGetResponse = + val notificationTemplateResponse = notificationService.retrieve( NotificationRetrieveParams.builder().id("id").version("version").build() ) - notificationTemplateGetResponse.validate() + notificationTemplateResponse.validate() } @Disabled("Mock server tests are disabled") @@ -246,7 +246,7 @@ internal class NotificationServiceTest { val client = CourierOkHttpClient.builder().apiKey("My API Key").build() val notificationService = client.notifications() - val notificationTemplateGetResponse = + val notificationTemplateResponse = notificationService.replace( NotificationReplaceParams.builder() .id("id") @@ -287,7 +287,7 @@ internal class NotificationServiceTest { .build() ) - notificationTemplateGetResponse.validate() + notificationTemplateResponse.validate() } @Disabled("Mock server tests are disabled") From 38b53079bd65f9813756e45cfbe7f8d4d5b27c99 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 14 Apr 2026 16:54:34 +0000 Subject: [PATCH 2/3] fix(types): flatten response structure in NotificationTemplateResponse --- .stats.yml | 4 +- .../NotificationTemplateCreateRequest.kt | 8 +- .../NotificationTemplatePayload.kt | 4 +- .../NotificationTemplateResponse.kt | 856 +++++++----------- .../NotificationTemplateUpdateRequest.kt | 8 +- .../NotificationTemplateResponseTest.kt | 159 ++-- 6 files changed, 426 insertions(+), 613 deletions(-) diff --git a/.stats.yml b/.stats.yml index 998581c7..effa635e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 103 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/courier%2Fcourier-0f56d7860a1be3ffaea5dea291b20ac92e31c94d54e41cc8a30462dacf2f2d37.yml -openapi_spec_hash: 7e7c6f963e83c5f626c09efa322f476a +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/courier%2Fcourier-3f78581b4e078a1f620d9f587f18d77bcde6d20f56b0e4ae798648f4236494fb.yml +openapi_spec_hash: 6bd33e0396d85e11bb46f0d549af93a3 config_hash: afcc4f6f8c33ca3f338589e32e086f56 diff --git a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplateCreateRequest.kt b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplateCreateRequest.kt index 37991db3..cb960679 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplateCreateRequest.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplateCreateRequest.kt @@ -36,8 +36,8 @@ private constructor( ) : this(notification, state, mutableMapOf()) /** - * Full document shape used in POST and PUT request bodies, and returned inside the GET response - * envelope. + * Core template fields used in POST and PUT request bodies (nested under a `notification` key) + * and returned at the top level in responses. * * @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). @@ -112,8 +112,8 @@ private constructor( } /** - * Full document shape used in POST and PUT request bodies, and returned inside the GET - * response envelope. + * Core template fields used in POST and PUT request bodies (nested under a `notification` + * key) and returned at the top level in responses. */ fun notification(notification: NotificationTemplatePayload) = notification(JsonField.of(notification)) diff --git a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplatePayload.kt b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplatePayload.kt index 95c08055..dd90bfbe 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplatePayload.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplatePayload.kt @@ -21,8 +21,8 @@ import java.util.Optional import kotlin.jvm.optionals.getOrNull /** - * Full document shape used in POST and PUT request bodies, and returned inside the GET response - * envelope. + * Core template fields used in POST and PUT request bodies (nested under a `notification` key) and + * returned at the top level in responses. */ class NotificationTemplatePayload @JsonCreator(mode = JsonCreator.Mode.DISABLED) diff --git a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplateResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplateResponse.kt index 685a35ac..d7cfc009 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplateResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplateResponse.kt @@ -22,15 +22,21 @@ import java.util.Optional import kotlin.jvm.optionals.getOrNull /** - * Response for GET /notifications/{id}, POST /notifications, and PUT /notifications/{id}. Wraps the - * template payload inside a `notification` key alongside metadata. + * Response for GET /notifications/{id}, POST /notifications, and PUT /notifications/{id}. Returns + * all template fields at the top level. */ class NotificationTemplateResponse @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( + private val brand: JsonField, + private val content: JsonField, + private val name: JsonField, + private val routing: JsonField, + private val subscription: JsonField, + private val tags: JsonField>, + private val id: JsonField, private val created: JsonField, private val creator: JsonField, - private val notification: JsonField, private val state: JsonField, private val updated: JsonField, private val updater: JsonField, @@ -39,40 +45,124 @@ private constructor( @JsonCreator private constructor( + @JsonProperty("brand") + @ExcludeMissing + brand: JsonField = JsonMissing.of(), + @JsonProperty("content") + @ExcludeMissing + content: JsonField = JsonMissing.of(), + @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + @JsonProperty("routing") + @ExcludeMissing + routing: JsonField = JsonMissing.of(), + @JsonProperty("subscription") + @ExcludeMissing + subscription: JsonField = JsonMissing.of(), + @JsonProperty("tags") @ExcludeMissing tags: JsonField> = JsonMissing.of(), + @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(), @JsonProperty("created") @ExcludeMissing created: JsonField = JsonMissing.of(), @JsonProperty("creator") @ExcludeMissing creator: JsonField = JsonMissing.of(), - @JsonProperty("notification") - @ExcludeMissing - notification: JsonField = JsonMissing.of(), @JsonProperty("state") @ExcludeMissing state: JsonField = JsonMissing.of(), @JsonProperty("updated") @ExcludeMissing updated: JsonField = JsonMissing.of(), @JsonProperty("updater") @ExcludeMissing updater: JsonField = JsonMissing.of(), - ) : this(created, creator, notification, state, updated, updater, mutableMapOf()) + ) : this( + brand, + content, + name, + routing, + subscription, + tags, + id, + created, + creator, + state, + updated, + updater, + mutableMapOf(), + ) + + fun toNotificationTemplatePayload(): NotificationTemplatePayload = + NotificationTemplatePayload.builder() + .brand(brand) + .content(content) + .name(name) + .routing(routing) + .subscription(subscription) + .tags(tags) + .build() /** - * Epoch milliseconds when the template was created. + * Brand reference, or null for no brand. + * + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun brand(): Optional = brand.getOptional("brand") + + /** + * Elemental content definition. * * @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 created(): Long = created.getRequired("created") + fun content(): ElementalContent = content.getRequired("content") /** - * User ID of the creator. + * Display name for the template. * * @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 creator(): String = creator.getRequired("creator") + fun name(): String = name.getRequired("name") + + /** + * Routing strategy reference, or null for none. + * + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun routing(): Optional = routing.getOptional("routing") + + /** + * Subscription topic reference, or null for none. + * + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun subscription(): Optional = + subscription.getOptional("subscription") + + /** + * Tags for categorization. Send empty array for none. + * + * @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 tags(): List = tags.getRequired("tags") + + /** + * The template ID. + * + * @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 id(): String = id.getRequired("id") + + /** + * Epoch milliseconds when the template was created. + * + * @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 created(): Long = created.getRequired("created") /** - * Full document shape used in POST and PUT request bodies, and returned inside the GET response - * envelope. + * User ID of the creator. * * @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 notification(): Notification = notification.getRequired("notification") + fun creator(): String = creator.getRequired("creator") /** * The template state. Always uppercase. @@ -98,6 +188,61 @@ private constructor( */ fun updater(): Optional = updater.getOptional("updater") + /** + * Returns the raw JSON value of [brand]. + * + * Unlike [brand], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("brand") + @ExcludeMissing + fun _brand(): JsonField = brand + + /** + * Returns the raw JSON value of [content]. + * + * Unlike [content], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("content") @ExcludeMissing fun _content(): JsonField = content + + /** + * Returns the raw JSON value of [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + /** + * Returns the raw JSON value of [routing]. + * + * Unlike [routing], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("routing") + @ExcludeMissing + fun _routing(): JsonField = routing + + /** + * Returns the raw JSON value of [subscription]. + * + * Unlike [subscription], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("subscription") + @ExcludeMissing + fun _subscription(): JsonField = subscription + + /** + * Returns the raw JSON value of [tags]. + * + * Unlike [tags], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("tags") @ExcludeMissing fun _tags(): JsonField> = tags + + /** + * Returns the raw JSON value of [id]. + * + * Unlike [id], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id + /** * Returns the raw JSON value of [created]. * @@ -112,15 +257,6 @@ private constructor( */ @JsonProperty("creator") @ExcludeMissing fun _creator(): JsonField = creator - /** - * Returns the raw JSON value of [notification]. - * - * Unlike [notification], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("notification") - @ExcludeMissing - fun _notification(): JsonField = notification - /** * Returns the raw JSON value of [state]. * @@ -161,9 +297,15 @@ private constructor( * * The following fields are required: * ```java + * .brand() + * .content() + * .name() + * .routing() + * .subscription() + * .tags() + * .id() * .created() * .creator() - * .notification() * .state() * ``` */ @@ -173,9 +315,15 @@ private constructor( /** A builder for [NotificationTemplateResponse]. */ class Builder internal constructor() { + private var brand: JsonField? = null + private var content: JsonField? = null + private var name: JsonField? = null + private var routing: JsonField? = null + private var subscription: JsonField? = null + private var tags: JsonField>? = null + private var id: JsonField? = null private var created: JsonField? = null private var creator: JsonField? = null - private var notification: JsonField? = null private var state: JsonField? = null private var updated: JsonField = JsonMissing.of() private var updater: JsonField = JsonMissing.of() @@ -183,15 +331,134 @@ private constructor( @JvmSynthetic internal fun from(notificationTemplateResponse: NotificationTemplateResponse) = apply { + brand = notificationTemplateResponse.brand + content = notificationTemplateResponse.content + name = notificationTemplateResponse.name + routing = notificationTemplateResponse.routing + subscription = notificationTemplateResponse.subscription + tags = notificationTemplateResponse.tags.map { it.toMutableList() } + id = notificationTemplateResponse.id created = notificationTemplateResponse.created creator = notificationTemplateResponse.creator - notification = notificationTemplateResponse.notification state = notificationTemplateResponse.state updated = notificationTemplateResponse.updated updater = notificationTemplateResponse.updater additionalProperties = notificationTemplateResponse.additionalProperties.toMutableMap() } + /** Brand reference, or null for no brand. */ + fun brand(brand: NotificationTemplatePayload.Brand?) = brand(JsonField.ofNullable(brand)) + + /** Alias for calling [Builder.brand] with `brand.orElse(null)`. */ + fun brand(brand: Optional) = brand(brand.getOrNull()) + + /** + * Sets [Builder.brand] to an arbitrary JSON value. + * + * You should usually call [Builder.brand] with a well-typed + * [NotificationTemplatePayload.Brand] value instead. This method is primarily for setting + * the field to an undocumented or not yet supported value. + */ + fun brand(brand: JsonField) = apply { + this.brand = brand + } + + /** Elemental content definition. */ + fun content(content: ElementalContent) = content(JsonField.of(content)) + + /** + * Sets [Builder.content] to an arbitrary JSON value. + * + * You should usually call [Builder.content] with a well-typed [ElementalContent] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun content(content: JsonField) = apply { this.content = content } + + /** Display name for the template. */ + fun name(name: String) = name(JsonField.of(name)) + + /** + * Sets [Builder.name] to an arbitrary JSON value. + * + * You should usually call [Builder.name] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun name(name: JsonField) = apply { this.name = name } + + /** Routing strategy reference, or null for none. */ + fun routing(routing: NotificationTemplatePayload.Routing?) = + routing(JsonField.ofNullable(routing)) + + /** Alias for calling [Builder.routing] with `routing.orElse(null)`. */ + fun routing(routing: Optional) = + routing(routing.getOrNull()) + + /** + * Sets [Builder.routing] to an arbitrary JSON value. + * + * You should usually call [Builder.routing] with a well-typed + * [NotificationTemplatePayload.Routing] value instead. This method is primarily for setting + * the field to an undocumented or not yet supported value. + */ + fun routing(routing: JsonField) = apply { + this.routing = routing + } + + /** Subscription topic reference, or null for none. */ + fun subscription(subscription: NotificationTemplatePayload.Subscription?) = + subscription(JsonField.ofNullable(subscription)) + + /** Alias for calling [Builder.subscription] with `subscription.orElse(null)`. */ + fun subscription(subscription: Optional) = + subscription(subscription.getOrNull()) + + /** + * Sets [Builder.subscription] to an arbitrary JSON value. + * + * You should usually call [Builder.subscription] with a well-typed + * [NotificationTemplatePayload.Subscription] value instead. This method is primarily for + * setting the field to an undocumented or not yet supported value. + */ + fun subscription(subscription: JsonField) = + apply { + this.subscription = subscription + } + + /** Tags for categorization. Send empty array for none. */ + fun tags(tags: List) = tags(JsonField.of(tags)) + + /** + * Sets [Builder.tags] to an arbitrary JSON value. + * + * You should usually call [Builder.tags] with a well-typed `List` value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun tags(tags: JsonField>) = apply { + this.tags = tags.map { it.toMutableList() } + } + + /** + * Adds a single [String] to [tags]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addTag(tag: String) = apply { + tags = (tags ?: JsonField.of(mutableListOf())).also { checkKnown("tags", it).add(tag) } + } + + /** The template ID. */ + fun id(id: String) = id(JsonField.of(id)) + + /** + * Sets [Builder.id] to an arbitrary JSON value. + * + * You should usually call [Builder.id] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun id(id: JsonField) = apply { this.id = id } + /** Epoch milliseconds when the template was created. */ fun created(created: Long) = created(JsonField.of(created)) @@ -214,23 +481,6 @@ private constructor( */ fun creator(creator: JsonField) = apply { this.creator = creator } - /** - * Full document shape used in POST and PUT request bodies, and returned inside the GET - * response envelope. - */ - fun notification(notification: Notification) = notification(JsonField.of(notification)) - - /** - * Sets [Builder.notification] to an arbitrary JSON value. - * - * You should usually call [Builder.notification] with a well-typed [Notification] value - * instead. This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun notification(notification: JsonField) = apply { - this.notification = notification - } - /** The template state. Always uppercase. */ fun state(state: State) = state(JsonField.of(state)) @@ -290,9 +540,15 @@ private constructor( * * The following fields are required: * ```java + * .brand() + * .content() + * .name() + * .routing() + * .subscription() + * .tags() + * .id() * .created() * .creator() - * .notification() * .state() * ``` * @@ -300,9 +556,15 @@ private constructor( */ fun build(): NotificationTemplateResponse = NotificationTemplateResponse( + checkRequired("brand", brand), + checkRequired("content", content), + checkRequired("name", name), + checkRequired("routing", routing), + checkRequired("subscription", subscription), + checkRequired("tags", tags).map { it.toImmutable() }, + checkRequired("id", id), checkRequired("created", created), checkRequired("creator", creator), - checkRequired("notification", notification), checkRequired("state", state), updated, updater, @@ -317,9 +579,15 @@ private constructor( return@apply } + brand().ifPresent { it.validate() } + content().validate() + name() + routing().ifPresent { it.validate() } + subscription().ifPresent { it.validate() } + tags() + id() created() creator() - notification().validate() state().validate() updated() updater() @@ -341,473 +609,19 @@ private constructor( */ @JvmSynthetic internal fun validity(): Int = - (if (created.asKnown().isPresent) 1 else 0) + + (brand.asKnown().getOrNull()?.validity() ?: 0) + + (content.asKnown().getOrNull()?.validity() ?: 0) + + (if (name.asKnown().isPresent) 1 else 0) + + (routing.asKnown().getOrNull()?.validity() ?: 0) + + (subscription.asKnown().getOrNull()?.validity() ?: 0) + + (tags.asKnown().getOrNull()?.size ?: 0) + + (if (id.asKnown().isPresent) 1 else 0) + + (if (created.asKnown().isPresent) 1 else 0) + (if (creator.asKnown().isPresent) 1 else 0) + - (notification.asKnown().getOrNull()?.validity() ?: 0) + (state.asKnown().getOrNull()?.validity() ?: 0) + (if (updated.asKnown().isPresent) 1 else 0) + (if (updater.asKnown().isPresent) 1 else 0) - /** - * Full document shape used in POST and PUT request bodies, and returned inside the GET response - * envelope. - */ - class Notification - @JsonCreator(mode = JsonCreator.Mode.DISABLED) - private constructor( - private val brand: JsonField, - private val content: JsonField, - private val name: JsonField, - private val routing: JsonField, - private val subscription: JsonField, - private val tags: JsonField>, - private val id: JsonField, - private val additionalProperties: MutableMap, - ) { - - @JsonCreator - private constructor( - @JsonProperty("brand") - @ExcludeMissing - brand: JsonField = JsonMissing.of(), - @JsonProperty("content") - @ExcludeMissing - content: JsonField = JsonMissing.of(), - @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), - @JsonProperty("routing") - @ExcludeMissing - routing: JsonField = JsonMissing.of(), - @JsonProperty("subscription") - @ExcludeMissing - subscription: JsonField = JsonMissing.of(), - @JsonProperty("tags") @ExcludeMissing tags: JsonField> = JsonMissing.of(), - @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(), - ) : this(brand, content, name, routing, subscription, tags, id, mutableMapOf()) - - fun toNotificationTemplatePayload(): NotificationTemplatePayload = - NotificationTemplatePayload.builder() - .brand(brand) - .content(content) - .name(name) - .routing(routing) - .subscription(subscription) - .tags(tags) - .build() - - /** - * Brand reference, or null for no brand. - * - * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). - */ - fun brand(): Optional = brand.getOptional("brand") - - /** - * Elemental content definition. - * - * @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 content(): ElementalContent = content.getRequired("content") - - /** - * Display name for the template. - * - * @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 name(): String = name.getRequired("name") - - /** - * Routing strategy reference, or null for none. - * - * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). - */ - fun routing(): Optional = - routing.getOptional("routing") - - /** - * Subscription topic reference, or null for none. - * - * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). - */ - fun subscription(): Optional = - subscription.getOptional("subscription") - - /** - * Tags for categorization. Send empty array for none. - * - * @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 tags(): List = tags.getRequired("tags") - - /** - * The template ID. - * - * @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 id(): String = id.getRequired("id") - - /** - * Returns the raw JSON value of [brand]. - * - * Unlike [brand], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("brand") - @ExcludeMissing - fun _brand(): JsonField = brand - - /** - * Returns the raw JSON value of [content]. - * - * Unlike [content], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("content") - @ExcludeMissing - fun _content(): JsonField = content - - /** - * Returns the raw JSON value of [name]. - * - * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name - - /** - * Returns the raw JSON value of [routing]. - * - * Unlike [routing], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("routing") - @ExcludeMissing - fun _routing(): JsonField = routing - - /** - * Returns the raw JSON value of [subscription]. - * - * Unlike [subscription], this method doesn't throw if the JSON field has an unexpected - * type. - */ - @JsonProperty("subscription") - @ExcludeMissing - fun _subscription(): JsonField = subscription - - /** - * Returns the raw JSON value of [tags]. - * - * Unlike [tags], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("tags") @ExcludeMissing fun _tags(): JsonField> = tags - - /** - * Returns the raw JSON value of [id]. - * - * Unlike [id], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id - - @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 [Notification]. - * - * The following fields are required: - * ```java - * .brand() - * .content() - * .name() - * .routing() - * .subscription() - * .tags() - * .id() - * ``` - */ - @JvmStatic fun builder() = Builder() - } - - /** A builder for [Notification]. */ - class Builder internal constructor() { - - private var brand: JsonField? = null - private var content: JsonField? = null - private var name: JsonField? = null - private var routing: JsonField? = null - private var subscription: JsonField? = null - private var tags: JsonField>? = null - private var id: JsonField? = null - private var additionalProperties: MutableMap = mutableMapOf() - - @JvmSynthetic - internal fun from(notification: Notification) = apply { - brand = notification.brand - content = notification.content - name = notification.name - routing = notification.routing - subscription = notification.subscription - tags = notification.tags.map { it.toMutableList() } - id = notification.id - additionalProperties = notification.additionalProperties.toMutableMap() - } - - /** Brand reference, or null for no brand. */ - fun brand(brand: NotificationTemplatePayload.Brand?) = - brand(JsonField.ofNullable(brand)) - - /** Alias for calling [Builder.brand] with `brand.orElse(null)`. */ - fun brand(brand: Optional) = brand(brand.getOrNull()) - - /** - * Sets [Builder.brand] to an arbitrary JSON value. - * - * You should usually call [Builder.brand] with a well-typed - * [NotificationTemplatePayload.Brand] value instead. This method is primarily for - * setting the field to an undocumented or not yet supported value. - */ - fun brand(brand: JsonField) = apply { - this.brand = brand - } - - /** Elemental content definition. */ - fun content(content: ElementalContent) = content(JsonField.of(content)) - - /** - * Sets [Builder.content] to an arbitrary JSON value. - * - * You should usually call [Builder.content] with a well-typed [ElementalContent] value - * instead. This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun content(content: JsonField) = apply { this.content = content } - - /** Display name for the template. */ - fun name(name: String) = name(JsonField.of(name)) - - /** - * Sets [Builder.name] to an arbitrary JSON value. - * - * You should usually call [Builder.name] with a well-typed [String] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported - * value. - */ - fun name(name: JsonField) = apply { this.name = name } - - /** Routing strategy reference, or null for none. */ - fun routing(routing: NotificationTemplatePayload.Routing?) = - routing(JsonField.ofNullable(routing)) - - /** Alias for calling [Builder.routing] with `routing.orElse(null)`. */ - fun routing(routing: Optional) = - routing(routing.getOrNull()) - - /** - * Sets [Builder.routing] to an arbitrary JSON value. - * - * You should usually call [Builder.routing] with a well-typed - * [NotificationTemplatePayload.Routing] value instead. This method is primarily for - * setting the field to an undocumented or not yet supported value. - */ - fun routing(routing: JsonField) = apply { - this.routing = routing - } - - /** Subscription topic reference, or null for none. */ - fun subscription(subscription: NotificationTemplatePayload.Subscription?) = - subscription(JsonField.ofNullable(subscription)) - - /** Alias for calling [Builder.subscription] with `subscription.orElse(null)`. */ - fun subscription(subscription: Optional) = - subscription(subscription.getOrNull()) - - /** - * Sets [Builder.subscription] to an arbitrary JSON value. - * - * You should usually call [Builder.subscription] with a well-typed - * [NotificationTemplatePayload.Subscription] value instead. This method is primarily - * for setting the field to an undocumented or not yet supported value. - */ - fun subscription(subscription: JsonField) = - apply { - this.subscription = subscription - } - - /** Tags for categorization. Send empty array for none. */ - fun tags(tags: List) = tags(JsonField.of(tags)) - - /** - * Sets [Builder.tags] to an arbitrary JSON value. - * - * You should usually call [Builder.tags] with a well-typed `List` value - * instead. This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun tags(tags: JsonField>) = apply { - this.tags = tags.map { it.toMutableList() } - } - - /** - * Adds a single [String] to [tags]. - * - * @throws IllegalStateException if the field was previously set to a non-list. - */ - fun addTag(tag: String) = apply { - tags = - (tags ?: JsonField.of(mutableListOf())).also { checkKnown("tags", it).add(tag) } - } - - /** The template ID. */ - fun id(id: String) = id(JsonField.of(id)) - - /** - * Sets [Builder.id] to an arbitrary JSON value. - * - * You should usually call [Builder.id] with a well-typed [String] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported - * value. - */ - fun id(id: JsonField) = apply { this.id = id } - - 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 [Notification]. - * - * Further updates to this [Builder] will not mutate the returned instance. - * - * The following fields are required: - * ```java - * .brand() - * .content() - * .name() - * .routing() - * .subscription() - * .tags() - * .id() - * ``` - * - * @throws IllegalStateException if any required field is unset. - */ - fun build(): Notification = - Notification( - checkRequired("brand", brand), - checkRequired("content", content), - checkRequired("name", name), - checkRequired("routing", routing), - checkRequired("subscription", subscription), - checkRequired("tags", tags).map { it.toImmutable() }, - checkRequired("id", id), - additionalProperties.toMutableMap(), - ) - } - - private var validated: Boolean = false - - fun validate(): Notification = apply { - if (validated) { - return@apply - } - - brand().ifPresent { it.validate() } - content().validate() - name() - routing().ifPresent { it.validate() } - subscription().ifPresent { it.validate() } - tags() - id() - 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 = - (brand.asKnown().getOrNull()?.validity() ?: 0) + - (content.asKnown().getOrNull()?.validity() ?: 0) + - (if (name.asKnown().isPresent) 1 else 0) + - (routing.asKnown().getOrNull()?.validity() ?: 0) + - (subscription.asKnown().getOrNull()?.validity() ?: 0) + - (tags.asKnown().getOrNull()?.size ?: 0) + - (if (id.asKnown().isPresent) 1 else 0) - - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } - - return other is Notification && - brand == other.brand && - content == other.content && - name == other.name && - routing == other.routing && - subscription == other.subscription && - tags == other.tags && - id == other.id && - additionalProperties == other.additionalProperties - } - - private val hashCode: Int by lazy { - Objects.hash( - brand, - content, - name, - routing, - subscription, - tags, - id, - additionalProperties, - ) - } - - override fun hashCode(): Int = hashCode - - override fun toString() = - "Notification{brand=$brand, content=$content, name=$name, routing=$routing, subscription=$subscription, tags=$tags, id=$id, additionalProperties=$additionalProperties}" - } - /** The template state. Always uppercase. */ class State @JsonCreator private constructor(private val value: JsonField) : Enum { @@ -940,9 +754,15 @@ private constructor( } return other is NotificationTemplateResponse && + brand == other.brand && + content == other.content && + name == other.name && + routing == other.routing && + subscription == other.subscription && + tags == other.tags && + id == other.id && created == other.created && creator == other.creator && - notification == other.notification && state == other.state && updated == other.updated && updater == other.updater && @@ -950,11 +770,25 @@ private constructor( } private val hashCode: Int by lazy { - Objects.hash(created, creator, notification, state, updated, updater, additionalProperties) + Objects.hash( + brand, + content, + name, + routing, + subscription, + tags, + id, + created, + creator, + state, + updated, + updater, + additionalProperties, + ) } override fun hashCode(): Int = hashCode override fun toString() = - "NotificationTemplateResponse{created=$created, creator=$creator, notification=$notification, state=$state, updated=$updated, updater=$updater, additionalProperties=$additionalProperties}" + "NotificationTemplateResponse{brand=$brand, content=$content, name=$name, routing=$routing, subscription=$subscription, tags=$tags, id=$id, created=$created, creator=$creator, state=$state, updated=$updated, updater=$updater, additionalProperties=$additionalProperties}" } diff --git a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplateUpdateRequest.kt b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplateUpdateRequest.kt index 7e87677f..ef86b21d 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplateUpdateRequest.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplateUpdateRequest.kt @@ -39,8 +39,8 @@ private constructor( ) : this(notification, state, mutableMapOf()) /** - * Full document shape used in POST and PUT request bodies, and returned inside the GET response - * envelope. + * Core template fields used in POST and PUT request bodies (nested under a `notification` key) + * and returned at the top level in responses. * * @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). @@ -115,8 +115,8 @@ private constructor( } /** - * Full document shape used in POST and PUT request bodies, and returned inside the GET - * response envelope. + * Core template fields used in POST and PUT request bodies (nested under a `notification` + * key) and returned at the top level in responses. */ fun notification(notification: NotificationTemplatePayload) = notification(JsonField.of(notification)) diff --git a/courier-java-core/src/test/kotlin/com/courier/models/notifications/NotificationTemplateResponseTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/notifications/NotificationTemplateResponseTest.kt index f7dfc007..be40fe92 100644 --- a/courier-java-core/src/test/kotlin/com/courier/models/notifications/NotificationTemplateResponseTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/models/notifications/NotificationTemplateResponseTest.kt @@ -15,80 +15,67 @@ internal class NotificationTemplateResponseTest { fun create() { val notificationTemplateResponse = NotificationTemplateResponse.builder() - .created(0L) - .creator("creator") - .notification( - NotificationTemplateResponse.Notification.builder() - .brand(NotificationTemplatePayload.Brand.builder().id("id").build()) - .content( - ElementalContent.builder() - .addElement( - ElementalTextNodeWithType.builder() - .addChannel("string") - .if_("if") - .loop("loop") - .ref("ref") - .type(ElementalTextNodeWithType.Type.TEXT) - .build() - ) - .version("version") - .build() - ) - .name("name") - .routing( - NotificationTemplatePayload.Routing.builder() - .strategyId("strategy_id") + .brand(NotificationTemplatePayload.Brand.builder().id("id").build()) + .content( + ElementalContent.builder() + .addElement( + ElementalTextNodeWithType.builder() + .addChannel("string") + .if_("if") + .loop("loop") + .ref("ref") + .type(ElementalTextNodeWithType.Type.TEXT) .build() ) - .subscription( - NotificationTemplatePayload.Subscription.builder() - .topicId("topic_id") - .build() - ) - .addTag("string") - .id("id") + .version("version") .build() ) + .name("name") + .routing( + NotificationTemplatePayload.Routing.builder().strategyId("strategy_id").build() + ) + .subscription( + NotificationTemplatePayload.Subscription.builder().topicId("topic_id").build() + ) + .addTag("string") + .id("id") + .created(0L) + .creator("creator") .state(NotificationTemplateResponse.State.DRAFT) .updated(0L) .updater("updater") .build() - assertThat(notificationTemplateResponse.created()).isEqualTo(0L) - assertThat(notificationTemplateResponse.creator()).isEqualTo("creator") - assertThat(notificationTemplateResponse.notification()) + assertThat(notificationTemplateResponse.brand()) + .contains(NotificationTemplatePayload.Brand.builder().id("id").build()) + assertThat(notificationTemplateResponse.content()) .isEqualTo( - NotificationTemplateResponse.Notification.builder() - .brand(NotificationTemplatePayload.Brand.builder().id("id").build()) - .content( - ElementalContent.builder() - .addElement( - ElementalTextNodeWithType.builder() - .addChannel("string") - .if_("if") - .loop("loop") - .ref("ref") - .type(ElementalTextNodeWithType.Type.TEXT) - .build() - ) - .version("version") - .build() - ) - .name("name") - .routing( - NotificationTemplatePayload.Routing.builder() - .strategyId("strategy_id") - .build() - ) - .subscription( - NotificationTemplatePayload.Subscription.builder() - .topicId("topic_id") + ElementalContent.builder() + .addElement( + ElementalTextNodeWithType.builder() + .addChannel("string") + .if_("if") + .loop("loop") + .ref("ref") + .type(ElementalTextNodeWithType.Type.TEXT) .build() ) - .addTag("string") - .id("id") + .version("version") .build() ) + assertThat(notificationTemplateResponse.name()).isEqualTo("name") + assertThat(notificationTemplateResponse.routing()) + .contains( + NotificationTemplatePayload.Routing.builder().strategyId("strategy_id").build() + ) + assertThat(notificationTemplateResponse.subscription()) + .contains( + NotificationTemplatePayload.Subscription.builder().topicId("topic_id").build() + ) + assertThat(notificationTemplateResponse.tags()).containsExactly("string") + assertThat(notificationTemplateResponse.id()).isEqualTo("id") + assertThat(notificationTemplateResponse.created()).isEqualTo(0L) + assertThat(notificationTemplateResponse.creator()).isEqualTo("creator") assertThat(notificationTemplateResponse.state()) .isEqualTo(NotificationTemplateResponse.State.DRAFT) assertThat(notificationTemplateResponse.updated()).contains(0L) @@ -100,40 +87,32 @@ internal class NotificationTemplateResponseTest { val jsonMapper = jsonMapper() val notificationTemplateResponse = NotificationTemplateResponse.builder() - .created(0L) - .creator("creator") - .notification( - NotificationTemplateResponse.Notification.builder() - .brand(NotificationTemplatePayload.Brand.builder().id("id").build()) - .content( - ElementalContent.builder() - .addElement( - ElementalTextNodeWithType.builder() - .addChannel("string") - .if_("if") - .loop("loop") - .ref("ref") - .type(ElementalTextNodeWithType.Type.TEXT) - .build() - ) - .version("version") + .brand(NotificationTemplatePayload.Brand.builder().id("id").build()) + .content( + ElementalContent.builder() + .addElement( + ElementalTextNodeWithType.builder() + .addChannel("string") + .if_("if") + .loop("loop") + .ref("ref") + .type(ElementalTextNodeWithType.Type.TEXT) .build() ) - .name("name") - .routing( - NotificationTemplatePayload.Routing.builder() - .strategyId("strategy_id") - .build() - ) - .subscription( - NotificationTemplatePayload.Subscription.builder() - .topicId("topic_id") - .build() - ) - .addTag("string") - .id("id") + .version("version") .build() ) + .name("name") + .routing( + NotificationTemplatePayload.Routing.builder().strategyId("strategy_id").build() + ) + .subscription( + NotificationTemplatePayload.Subscription.builder().topicId("topic_id").build() + ) + .addTag("string") + .id("id") + .created(0L) + .creator("creator") .state(NotificationTemplateResponse.State.DRAFT) .updated(0L) .updater("updater") From 729f9aa5f5154c38a2d210e73aacb150cef2ee51 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 14 Apr 2026 16:55:06 +0000 Subject: [PATCH 3/3] release: 4.13.1 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 9 +++++++++ build.gradle.kts | 2 +- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 809fed12..ef0ce5df 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "4.13.0" + ".": "4.13.1" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index a6c2cb74..21698c5a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## 4.13.1 (2026-04-14) + +Full Changelog: [v4.13.0...v4.13.1](https://github.com/trycourier/courier-java/compare/v4.13.0...v4.13.1) + +### Bug Fixes + +* **types:** flatten response structure in NotificationTemplateResponse ([38b5307](https://github.com/trycourier/courier-java/commit/38b53079bd65f9813756e45cfbe7f8d4d5b27c99)) +* **types:** make note optional in notifications, flatten template response ([ba686ac](https://github.com/trycourier/courier-java/commit/ba686ac91e66e3f6979623246a9f9b01607839aa)) + ## 4.13.0 (2026-04-13) Full Changelog: [v4.12.0...v4.13.0](https://github.com/trycourier/courier-java/compare/v4.12.0...v4.13.0) diff --git a/build.gradle.kts b/build.gradle.kts index fd419759..5e5c1b36 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,7 +8,7 @@ repositories { allprojects { group = "com.courier" - version = "4.13.0" // x-release-please-version + version = "4.13.1" // x-release-please-version } subprojects {