diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index c412e97..52b3e83 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.1.0-alpha.29"
+ ".": "0.1.0-alpha.30"
}
\ No newline at end of file
diff --git a/.stats.yml b/.stats.yml
index 3c2db8b..a1fb573 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 15
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/brand-dev%2Fbrand.dev-10f7ae53f4fe4f2394c22788b648d9db742a178ed41a87beb39de741660e646b.yml
-openapi_spec_hash: 9885c47a02677471a38f16dddbad1823
-config_hash: 6f10592c7d0c3bafefc1271472283217
+configured_endpoints: 16
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/brand-dev%2Fbrand.dev-ec0e897d65bee0947046681fd3cd465ee5b44c98b020594736fb9f274ee2c00b.yml
+openapi_spec_hash: 9c76eb4b912f046fc93a030b9a7489a3
+config_hash: c3aaaa9794dba44d524c06591ab17894
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6b35897..d5c2e30 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,19 @@
# Changelog
+## 0.1.0-alpha.30 (2026-02-18)
+
+Full Changelog: [v0.1.0-alpha.29...v0.1.0-alpha.30](https://github.com/brand-dot-dev/java-sdk/compare/v0.1.0-alpha.29...v0.1.0-alpha.30)
+
+### Features
+
+* **api:** api update ([176daa6](https://github.com/brand-dot-dev/java-sdk/commit/176daa6ade5920957e1afb073ab0f14b2dc93705))
+* **api:** manual updates ([8588622](https://github.com/brand-dot-dev/java-sdk/commit/8588622a8b75ea541a9be7fc2a47a4ddd1554416))
+
+
+### Chores
+
+* **internal:** update `TestServerExtension` comment ([8ec7bbb](https://github.com/brand-dot-dev/java-sdk/commit/8ec7bbbdf6d8c8a3e62817f69120817f85a89f9f))
+
## 0.1.0-alpha.29 (2026-02-07)
Full Changelog: [v0.1.0-alpha.28...v0.1.0-alpha.29](https://github.com/brand-dot-dev/java-sdk/compare/v0.1.0-alpha.28...v0.1.0-alpha.29)
diff --git a/README.md b/README.md
index a597701..7e7531e 100644
--- a/README.md
+++ b/README.md
@@ -2,8 +2,8 @@
-[](https://central.sonatype.com/artifact/com.branddev.api/brand-dev-java/0.1.0-alpha.29)
-[](https://javadoc.io/doc/com.branddev.api/brand-dev-java/0.1.0-alpha.29)
+[](https://central.sonatype.com/artifact/com.branddev.api/brand-dev-java/0.1.0-alpha.30)
+[](https://javadoc.io/doc/com.branddev.api/brand-dev-java/0.1.0-alpha.30)
@@ -22,7 +22,7 @@ Use the Brand Dev MCP Server to enable AI assistants to interact with this API,
-The REST API documentation can be found on [docs.brand.dev](https://docs.brand.dev/). Javadocs are available on [javadoc.io](https://javadoc.io/doc/com.branddev.api/brand-dev-java/0.1.0-alpha.29).
+The REST API documentation can be found on [docs.brand.dev](https://docs.brand.dev/). Javadocs are available on [javadoc.io](https://javadoc.io/doc/com.branddev.api/brand-dev-java/0.1.0-alpha.30).
@@ -33,7 +33,7 @@ The REST API documentation can be found on [docs.brand.dev](https://docs.brand.d
### Gradle
```kotlin
-implementation("com.branddev.api:brand-dev-java:0.1.0-alpha.29")
+implementation("com.branddev.api:brand-dev-java:0.1.0-alpha.30")
```
### Maven
@@ -42,7 +42,7 @@ implementation("com.branddev.api:brand-dev-java:0.1.0-alpha.29")
com.branddev.api
brand-dev-java
- 0.1.0-alpha.29
+ 0.1.0-alpha.30
```
diff --git a/brand-dev-java-core/src/main/kotlin/com/branddev/api/models/brand/BrandAiProductParams.kt b/brand-dev-java-core/src/main/kotlin/com/branddev/api/models/brand/BrandAiProductParams.kt
new file mode 100644
index 0000000..8e1018b
--- /dev/null
+++ b/brand-dev-java-core/src/main/kotlin/com/branddev/api/models/brand/BrandAiProductParams.kt
@@ -0,0 +1,490 @@
+// File generated from our OpenAPI spec by Stainless.
+
+package com.branddev.api.models.brand
+
+import com.branddev.api.core.ExcludeMissing
+import com.branddev.api.core.JsonField
+import com.branddev.api.core.JsonMissing
+import com.branddev.api.core.JsonValue
+import com.branddev.api.core.Params
+import com.branddev.api.core.checkRequired
+import com.branddev.api.core.http.Headers
+import com.branddev.api.core.http.QueryParams
+import com.branddev.api.errors.BrandDevInvalidDataException
+import com.fasterxml.jackson.annotation.JsonAnyGetter
+import com.fasterxml.jackson.annotation.JsonAnySetter
+import com.fasterxml.jackson.annotation.JsonCreator
+import com.fasterxml.jackson.annotation.JsonProperty
+import java.util.Collections
+import java.util.Objects
+import java.util.Optional
+
+/**
+ * Beta feature: Given a single URL, determines if it is a product detail page, classifies the
+ * platform/product type, and extracts the product information. Supports Amazon, TikTok Shop, Etsy,
+ * and generic ecommerce sites.
+ */
+class BrandAiProductParams
+private constructor(
+ private val body: Body,
+ private val additionalHeaders: Headers,
+ private val additionalQueryParams: QueryParams,
+) : Params {
+
+ /**
+ * The product page URL to extract product data from.
+ *
+ * @throws BrandDevInvalidDataException 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 url(): String = body.url()
+
+ /**
+ * Optional timeout in milliseconds for the request. Maximum allowed value is 300000ms (5
+ * minutes).
+ *
+ * @throws BrandDevInvalidDataException if the JSON field has an unexpected type (e.g. if the
+ * server responded with an unexpected value).
+ */
+ fun timeoutMs(): Optional = body.timeoutMs()
+
+ /**
+ * Returns the raw JSON value of [url].
+ *
+ * Unlike [url], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ fun _url(): JsonField = body._url()
+
+ /**
+ * Returns the raw JSON value of [timeoutMs].
+ *
+ * Unlike [timeoutMs], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ fun _timeoutMs(): JsonField = body._timeoutMs()
+
+ fun _additionalBodyProperties(): Map = body._additionalProperties()
+
+ /** Additional headers to send with the request. */
+ fun _additionalHeaders(): Headers = additionalHeaders
+
+ /** Additional query param to send with the request. */
+ fun _additionalQueryParams(): QueryParams = additionalQueryParams
+
+ fun toBuilder() = Builder().from(this)
+
+ companion object {
+
+ /**
+ * Returns a mutable builder for constructing an instance of [BrandAiProductParams].
+ *
+ * The following fields are required:
+ * ```java
+ * .url()
+ * ```
+ */
+ @JvmStatic fun builder() = Builder()
+ }
+
+ /** A builder for [BrandAiProductParams]. */
+ class Builder internal constructor() {
+
+ private var body: Body.Builder = Body.builder()
+ private var additionalHeaders: Headers.Builder = Headers.builder()
+ private var additionalQueryParams: QueryParams.Builder = QueryParams.builder()
+
+ @JvmSynthetic
+ internal fun from(brandAiProductParams: BrandAiProductParams) = apply {
+ body = brandAiProductParams.body.toBuilder()
+ additionalHeaders = brandAiProductParams.additionalHeaders.toBuilder()
+ additionalQueryParams = brandAiProductParams.additionalQueryParams.toBuilder()
+ }
+
+ /**
+ * Sets the entire request body.
+ *
+ * This is generally only useful if you are already constructing the body separately.
+ * Otherwise, it's more convenient to use the top-level setters instead:
+ * - [url]
+ * - [timeoutMs]
+ */
+ fun body(body: Body) = apply { this.body = body.toBuilder() }
+
+ /** The product page URL to extract product data from. */
+ fun url(url: String) = apply { body.url(url) }
+
+ /**
+ * Sets [Builder.url] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.url] with a well-typed [String] value instead. This
+ * method is primarily for setting the field to an undocumented or not yet supported value.
+ */
+ fun url(url: JsonField) = apply { body.url(url) }
+
+ /**
+ * Optional timeout in milliseconds for the request. Maximum allowed value is 300000ms (5
+ * minutes).
+ */
+ fun timeoutMs(timeoutMs: Long) = apply { body.timeoutMs(timeoutMs) }
+
+ /**
+ * Sets [Builder.timeoutMs] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.timeoutMs] with a well-typed [Long] value instead. This
+ * method is primarily for setting the field to an undocumented or not yet supported value.
+ */
+ fun timeoutMs(timeoutMs: JsonField) = apply { body.timeoutMs(timeoutMs) }
+
+ fun additionalBodyProperties(additionalBodyProperties: Map) = apply {
+ body.additionalProperties(additionalBodyProperties)
+ }
+
+ fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply {
+ body.putAdditionalProperty(key, value)
+ }
+
+ fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) =
+ apply {
+ body.putAllAdditionalProperties(additionalBodyProperties)
+ }
+
+ fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) }
+
+ fun removeAllAdditionalBodyProperties(keys: Set) = apply {
+ body.removeAllAdditionalProperties(keys)
+ }
+
+ fun additionalHeaders(additionalHeaders: Headers) = apply {
+ this.additionalHeaders.clear()
+ putAllAdditionalHeaders(additionalHeaders)
+ }
+
+ fun additionalHeaders(additionalHeaders: Map>) = apply {
+ this.additionalHeaders.clear()
+ putAllAdditionalHeaders(additionalHeaders)
+ }
+
+ fun putAdditionalHeader(name: String, value: String) = apply {
+ additionalHeaders.put(name, value)
+ }
+
+ fun putAdditionalHeaders(name: String, values: Iterable) = apply {
+ additionalHeaders.put(name, values)
+ }
+
+ fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply {
+ this.additionalHeaders.putAll(additionalHeaders)
+ }
+
+ fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply {
+ this.additionalHeaders.putAll(additionalHeaders)
+ }
+
+ fun replaceAdditionalHeaders(name: String, value: String) = apply {
+ additionalHeaders.replace(name, value)
+ }
+
+ fun replaceAdditionalHeaders(name: String, values: Iterable) = apply {
+ additionalHeaders.replace(name, values)
+ }
+
+ fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply {
+ this.additionalHeaders.replaceAll(additionalHeaders)
+ }
+
+ fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply {
+ this.additionalHeaders.replaceAll(additionalHeaders)
+ }
+
+ fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) }
+
+ fun removeAllAdditionalHeaders(names: Set) = apply {
+ additionalHeaders.removeAll(names)
+ }
+
+ fun additionalQueryParams(additionalQueryParams: QueryParams) = apply {
+ this.additionalQueryParams.clear()
+ putAllAdditionalQueryParams(additionalQueryParams)
+ }
+
+ fun additionalQueryParams(additionalQueryParams: Map>) = apply {
+ this.additionalQueryParams.clear()
+ putAllAdditionalQueryParams(additionalQueryParams)
+ }
+
+ fun putAdditionalQueryParam(key: String, value: String) = apply {
+ additionalQueryParams.put(key, value)
+ }
+
+ fun putAdditionalQueryParams(key: String, values: Iterable) = apply {
+ additionalQueryParams.put(key, values)
+ }
+
+ fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply {
+ this.additionalQueryParams.putAll(additionalQueryParams)
+ }
+
+ fun putAllAdditionalQueryParams(additionalQueryParams: Map>) =
+ apply {
+ this.additionalQueryParams.putAll(additionalQueryParams)
+ }
+
+ fun replaceAdditionalQueryParams(key: String, value: String) = apply {
+ additionalQueryParams.replace(key, value)
+ }
+
+ fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply {
+ additionalQueryParams.replace(key, values)
+ }
+
+ fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply {
+ this.additionalQueryParams.replaceAll(additionalQueryParams)
+ }
+
+ fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) =
+ apply {
+ this.additionalQueryParams.replaceAll(additionalQueryParams)
+ }
+
+ fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) }
+
+ fun removeAllAdditionalQueryParams(keys: Set) = apply {
+ additionalQueryParams.removeAll(keys)
+ }
+
+ /**
+ * Returns an immutable instance of [BrandAiProductParams].
+ *
+ * Further updates to this [Builder] will not mutate the returned instance.
+ *
+ * The following fields are required:
+ * ```java
+ * .url()
+ * ```
+ *
+ * @throws IllegalStateException if any required field is unset.
+ */
+ fun build(): BrandAiProductParams =
+ BrandAiProductParams(
+ body.build(),
+ additionalHeaders.build(),
+ additionalQueryParams.build(),
+ )
+ }
+
+ fun _body(): Body = body
+
+ override fun _headers(): Headers = additionalHeaders
+
+ override fun _queryParams(): QueryParams = additionalQueryParams
+
+ class Body
+ @JsonCreator(mode = JsonCreator.Mode.DISABLED)
+ private constructor(
+ private val url: JsonField,
+ private val timeoutMs: JsonField,
+ private val additionalProperties: MutableMap,
+ ) {
+
+ @JsonCreator
+ private constructor(
+ @JsonProperty("url") @ExcludeMissing url: JsonField = JsonMissing.of(),
+ @JsonProperty("timeoutMS") @ExcludeMissing timeoutMs: JsonField = JsonMissing.of(),
+ ) : this(url, timeoutMs, mutableMapOf())
+
+ /**
+ * The product page URL to extract product data from.
+ *
+ * @throws BrandDevInvalidDataException 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 url(): String = url.getRequired("url")
+
+ /**
+ * Optional timeout in milliseconds for the request. Maximum allowed value is 300000ms (5
+ * minutes).
+ *
+ * @throws BrandDevInvalidDataException if the JSON field has an unexpected type (e.g. if
+ * the server responded with an unexpected value).
+ */
+ fun timeoutMs(): Optional = timeoutMs.getOptional("timeoutMS")
+
+ /**
+ * Returns the raw JSON value of [url].
+ *
+ * Unlike [url], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("url") @ExcludeMissing fun _url(): JsonField = url
+
+ /**
+ * Returns the raw JSON value of [timeoutMs].
+ *
+ * Unlike [timeoutMs], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("timeoutMS") @ExcludeMissing fun _timeoutMs(): JsonField = timeoutMs
+
+ @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 [Body].
+ *
+ * The following fields are required:
+ * ```java
+ * .url()
+ * ```
+ */
+ @JvmStatic fun builder() = Builder()
+ }
+
+ /** A builder for [Body]. */
+ class Builder internal constructor() {
+
+ private var url: JsonField? = null
+ private var timeoutMs: JsonField = JsonMissing.of()
+ private var additionalProperties: MutableMap = mutableMapOf()
+
+ @JvmSynthetic
+ internal fun from(body: Body) = apply {
+ url = body.url
+ timeoutMs = body.timeoutMs
+ additionalProperties = body.additionalProperties.toMutableMap()
+ }
+
+ /** The product page URL to extract product data from. */
+ fun url(url: String) = url(JsonField.of(url))
+
+ /**
+ * Sets [Builder.url] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.url] with a well-typed [String] value instead. This
+ * method is primarily for setting the field to an undocumented or not yet supported
+ * value.
+ */
+ fun url(url: JsonField) = apply { this.url = url }
+
+ /**
+ * Optional timeout in milliseconds for the request. Maximum allowed value is 300000ms
+ * (5 minutes).
+ */
+ fun timeoutMs(timeoutMs: Long) = timeoutMs(JsonField.of(timeoutMs))
+
+ /**
+ * Sets [Builder.timeoutMs] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.timeoutMs] with a well-typed [Long] value instead.
+ * This method is primarily for setting the field to an undocumented or not yet
+ * supported value.
+ */
+ fun timeoutMs(timeoutMs: JsonField) = apply { this.timeoutMs = timeoutMs }
+
+ 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 [Body].
+ *
+ * Further updates to this [Builder] will not mutate the returned instance.
+ *
+ * The following fields are required:
+ * ```java
+ * .url()
+ * ```
+ *
+ * @throws IllegalStateException if any required field is unset.
+ */
+ fun build(): Body =
+ Body(checkRequired("url", url), timeoutMs, additionalProperties.toMutableMap())
+ }
+
+ private var validated: Boolean = false
+
+ fun validate(): Body = apply {
+ if (validated) {
+ return@apply
+ }
+
+ url()
+ timeoutMs()
+ validated = true
+ }
+
+ fun isValid(): Boolean =
+ try {
+ validate()
+ true
+ } catch (e: BrandDevInvalidDataException) {
+ false
+ }
+
+ /**
+ * Returns a score indicating how many valid values are contained in this object
+ * recursively.
+ *
+ * Used for best match union deserialization.
+ */
+ @JvmSynthetic
+ internal fun validity(): Int =
+ (if (url.asKnown().isPresent) 1 else 0) + (if (timeoutMs.asKnown().isPresent) 1 else 0)
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) {
+ return true
+ }
+
+ return other is Body &&
+ url == other.url &&
+ timeoutMs == other.timeoutMs &&
+ additionalProperties == other.additionalProperties
+ }
+
+ private val hashCode: Int by lazy { Objects.hash(url, timeoutMs, additionalProperties) }
+
+ override fun hashCode(): Int = hashCode
+
+ override fun toString() =
+ "Body{url=$url, timeoutMs=$timeoutMs, additionalProperties=$additionalProperties}"
+ }
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) {
+ return true
+ }
+
+ return other is BrandAiProductParams &&
+ body == other.body &&
+ additionalHeaders == other.additionalHeaders &&
+ additionalQueryParams == other.additionalQueryParams
+ }
+
+ override fun hashCode(): Int = Objects.hash(body, additionalHeaders, additionalQueryParams)
+
+ override fun toString() =
+ "BrandAiProductParams{body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}"
+}
diff --git a/brand-dev-java-core/src/main/kotlin/com/branddev/api/models/brand/BrandAiProductResponse.kt b/brand-dev-java-core/src/main/kotlin/com/branddev/api/models/brand/BrandAiProductResponse.kt
new file mode 100644
index 0000000..3beb8ee
--- /dev/null
+++ b/brand-dev-java-core/src/main/kotlin/com/branddev/api/models/brand/BrandAiProductResponse.kt
@@ -0,0 +1,1382 @@
+// File generated from our OpenAPI spec by Stainless.
+
+package com.branddev.api.models.brand
+
+import com.branddev.api.core.Enum
+import com.branddev.api.core.ExcludeMissing
+import com.branddev.api.core.JsonField
+import com.branddev.api.core.JsonMissing
+import com.branddev.api.core.JsonValue
+import com.branddev.api.core.checkKnown
+import com.branddev.api.core.checkRequired
+import com.branddev.api.core.toImmutable
+import com.branddev.api.errors.BrandDevInvalidDataException
+import com.fasterxml.jackson.annotation.JsonAnyGetter
+import com.fasterxml.jackson.annotation.JsonAnySetter
+import com.fasterxml.jackson.annotation.JsonCreator
+import com.fasterxml.jackson.annotation.JsonProperty
+import java.util.Collections
+import java.util.Objects
+import java.util.Optional
+import kotlin.jvm.optionals.getOrNull
+
+class BrandAiProductResponse
+@JsonCreator(mode = JsonCreator.Mode.DISABLED)
+private constructor(
+ private val isProductPage: JsonField,
+ private val platform: JsonField,
+ private val product: JsonField,
+ private val additionalProperties: MutableMap,
+) {
+
+ @JsonCreator
+ private constructor(
+ @JsonProperty("is_product_page")
+ @ExcludeMissing
+ isProductPage: JsonField = JsonMissing.of(),
+ @JsonProperty("platform") @ExcludeMissing platform: JsonField = JsonMissing.of(),
+ @JsonProperty("product") @ExcludeMissing product: JsonField = JsonMissing.of(),
+ ) : this(isProductPage, platform, product, mutableMapOf())
+
+ /**
+ * Whether the given URL is a product detail page
+ *
+ * @throws BrandDevInvalidDataException if the JSON field has an unexpected type (e.g. if the
+ * server responded with an unexpected value).
+ */
+ fun isProductPage(): Optional = isProductPage.getOptional("is_product_page")
+
+ /**
+ * The detected ecommerce platform, or null if not a product page
+ *
+ * @throws BrandDevInvalidDataException if the JSON field has an unexpected type (e.g. if the
+ * server responded with an unexpected value).
+ */
+ fun platform(): Optional = platform.getOptional("platform")
+
+ /**
+ * The extracted product data, or null if not a product page
+ *
+ * @throws BrandDevInvalidDataException if the JSON field has an unexpected type (e.g. if the
+ * server responded with an unexpected value).
+ */
+ fun product(): Optional = product.getOptional("product")
+
+ /**
+ * Returns the raw JSON value of [isProductPage].
+ *
+ * Unlike [isProductPage], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("is_product_page")
+ @ExcludeMissing
+ fun _isProductPage(): JsonField = isProductPage
+
+ /**
+ * Returns the raw JSON value of [platform].
+ *
+ * Unlike [platform], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("platform") @ExcludeMissing fun _platform(): JsonField = platform
+
+ /**
+ * Returns the raw JSON value of [product].
+ *
+ * Unlike [product], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("product") @ExcludeMissing fun _product(): JsonField = product
+
+ @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 [BrandAiProductResponse]. */
+ @JvmStatic fun builder() = Builder()
+ }
+
+ /** A builder for [BrandAiProductResponse]. */
+ class Builder internal constructor() {
+
+ private var isProductPage: JsonField = JsonMissing.of()
+ private var platform: JsonField = JsonMissing.of()
+ private var product: JsonField = JsonMissing.of()
+ private var additionalProperties: MutableMap = mutableMapOf()
+
+ @JvmSynthetic
+ internal fun from(brandAiProductResponse: BrandAiProductResponse) = apply {
+ isProductPage = brandAiProductResponse.isProductPage
+ platform = brandAiProductResponse.platform
+ product = brandAiProductResponse.product
+ additionalProperties = brandAiProductResponse.additionalProperties.toMutableMap()
+ }
+
+ /** Whether the given URL is a product detail page */
+ fun isProductPage(isProductPage: Boolean) = isProductPage(JsonField.of(isProductPage))
+
+ /**
+ * Sets [Builder.isProductPage] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.isProductPage] with a well-typed [Boolean] value
+ * instead. This method is primarily for setting the field to an undocumented or not yet
+ * supported value.
+ */
+ fun isProductPage(isProductPage: JsonField) = apply {
+ this.isProductPage = isProductPage
+ }
+
+ /** The detected ecommerce platform, or null if not a product page */
+ fun platform(platform: Platform?) = platform(JsonField.ofNullable(platform))
+
+ /** Alias for calling [Builder.platform] with `platform.orElse(null)`. */
+ fun platform(platform: Optional) = platform(platform.getOrNull())
+
+ /**
+ * Sets [Builder.platform] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.platform] with a well-typed [Platform] value instead.
+ * This method is primarily for setting the field to an undocumented or not yet supported
+ * value.
+ */
+ fun platform(platform: JsonField) = apply { this.platform = platform }
+
+ /** The extracted product data, or null if not a product page */
+ fun product(product: Product?) = product(JsonField.ofNullable(product))
+
+ /** Alias for calling [Builder.product] with `product.orElse(null)`. */
+ fun product(product: Optional) = product(product.getOrNull())
+
+ /**
+ * Sets [Builder.product] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.product] with a well-typed [Product] value instead. This
+ * method is primarily for setting the field to an undocumented or not yet supported value.
+ */
+ fun product(product: JsonField) = apply { this.product = product }
+
+ 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 [BrandAiProductResponse].
+ *
+ * Further updates to this [Builder] will not mutate the returned instance.
+ */
+ fun build(): BrandAiProductResponse =
+ BrandAiProductResponse(
+ isProductPage,
+ platform,
+ product,
+ additionalProperties.toMutableMap(),
+ )
+ }
+
+ private var validated: Boolean = false
+
+ fun validate(): BrandAiProductResponse = apply {
+ if (validated) {
+ return@apply
+ }
+
+ isProductPage()
+ platform().ifPresent { it.validate() }
+ product().ifPresent { it.validate() }
+ validated = true
+ }
+
+ fun isValid(): Boolean =
+ try {
+ validate()
+ true
+ } catch (e: BrandDevInvalidDataException) {
+ false
+ }
+
+ /**
+ * Returns a score indicating how many valid values are contained in this object recursively.
+ *
+ * Used for best match union deserialization.
+ */
+ @JvmSynthetic
+ internal fun validity(): Int =
+ (if (isProductPage.asKnown().isPresent) 1 else 0) +
+ (platform.asKnown().getOrNull()?.validity() ?: 0) +
+ (product.asKnown().getOrNull()?.validity() ?: 0)
+
+ /** The detected ecommerce platform, or null if not a product page */
+ class Platform @JsonCreator private constructor(private val value: JsonField) : Enum {
+
+ /**
+ * Returns this class instance's raw value.
+ *
+ * This is usually only useful if this instance was deserialized from data that doesn't
+ * match any known member, and you want to know that value. For example, if the SDK is on an
+ * older version than the API, then the API may respond with new members that the SDK is
+ * unaware of.
+ */
+ @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value
+
+ companion object {
+
+ @JvmField val AMAZON = of("amazon")
+
+ @JvmField val TIKTOK_SHOP = of("tiktok_shop")
+
+ @JvmField val ETSY = of("etsy")
+
+ @JvmField val GENERIC = of("generic")
+
+ @JvmStatic fun of(value: String) = Platform(JsonField.of(value))
+ }
+
+ /** An enum containing [Platform]'s known values. */
+ enum class Known {
+ AMAZON,
+ TIKTOK_SHOP,
+ ETSY,
+ GENERIC,
+ }
+
+ /**
+ * An enum containing [Platform]'s known values, as well as an [_UNKNOWN] member.
+ *
+ * An instance of [Platform] can contain an unknown value in a couple of cases:
+ * - It was deserialized from data that doesn't match any known member. For example, if the
+ * SDK is on an older version than the API, then the API may respond with new members that
+ * the SDK is unaware of.
+ * - It was constructed with an arbitrary value using the [of] method.
+ */
+ enum class Value {
+ AMAZON,
+ TIKTOK_SHOP,
+ ETSY,
+ GENERIC,
+ /** An enum member indicating that [Platform] was instantiated with an unknown value. */
+ _UNKNOWN,
+ }
+
+ /**
+ * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN]
+ * if the class was instantiated with an unknown value.
+ *
+ * Use the [known] method instead if you're certain the value is always known or if you want
+ * to throw for the unknown case.
+ */
+ fun value(): Value =
+ when (this) {
+ AMAZON -> Value.AMAZON
+ TIKTOK_SHOP -> Value.TIKTOK_SHOP
+ ETSY -> Value.ETSY
+ GENERIC -> Value.GENERIC
+ else -> Value._UNKNOWN
+ }
+
+ /**
+ * Returns an enum member corresponding to this class instance's value.
+ *
+ * Use the [value] method instead if you're uncertain the value is always known and don't
+ * want to throw for the unknown case.
+ *
+ * @throws BrandDevInvalidDataException if this class instance's value is a not a known
+ * member.
+ */
+ fun known(): Known =
+ when (this) {
+ AMAZON -> Known.AMAZON
+ TIKTOK_SHOP -> Known.TIKTOK_SHOP
+ ETSY -> Known.ETSY
+ GENERIC -> Known.GENERIC
+ else -> throw BrandDevInvalidDataException("Unknown Platform: $value")
+ }
+
+ /**
+ * Returns this class instance's primitive wire representation.
+ *
+ * This differs from the [toString] method because that method is primarily for debugging
+ * and generally doesn't throw.
+ *
+ * @throws BrandDevInvalidDataException if this class instance's value does not have the
+ * expected primitive type.
+ */
+ fun asString(): String =
+ _value().asString().orElseThrow {
+ BrandDevInvalidDataException("Value is not a String")
+ }
+
+ private var validated: Boolean = false
+
+ fun validate(): Platform = apply {
+ if (validated) {
+ return@apply
+ }
+
+ known()
+ validated = true
+ }
+
+ fun isValid(): Boolean =
+ try {
+ validate()
+ true
+ } catch (e: BrandDevInvalidDataException) {
+ false
+ }
+
+ /**
+ * Returns a score indicating how many valid values are contained in this object
+ * recursively.
+ *
+ * Used for best match union deserialization.
+ */
+ @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) {
+ return true
+ }
+
+ return other is Platform && value == other.value
+ }
+
+ override fun hashCode() = value.hashCode()
+
+ override fun toString() = value.toString()
+ }
+
+ /** The extracted product data, or null if not a product page */
+ class Product
+ @JsonCreator(mode = JsonCreator.Mode.DISABLED)
+ private constructor(
+ private val description: JsonField,
+ private val features: JsonField>,
+ private val name: JsonField,
+ private val tags: JsonField>,
+ private val targetAudience: JsonField>,
+ private val billingFrequency: JsonField,
+ private val category: JsonField,
+ private val currency: JsonField,
+ private val imageUrl: JsonField,
+ private val price: JsonField,
+ private val pricingModel: JsonField,
+ private val url: JsonField,
+ private val additionalProperties: MutableMap,
+ ) {
+
+ @JsonCreator
+ private constructor(
+ @JsonProperty("description")
+ @ExcludeMissing
+ description: JsonField = JsonMissing.of(),
+ @JsonProperty("features")
+ @ExcludeMissing
+ features: JsonField> = JsonMissing.of(),
+ @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(),
+ @JsonProperty("tags") @ExcludeMissing tags: JsonField> = JsonMissing.of(),
+ @JsonProperty("target_audience")
+ @ExcludeMissing
+ targetAudience: JsonField> = JsonMissing.of(),
+ @JsonProperty("billing_frequency")
+ @ExcludeMissing
+ billingFrequency: JsonField = JsonMissing.of(),
+ @JsonProperty("category")
+ @ExcludeMissing
+ category: JsonField = JsonMissing.of(),
+ @JsonProperty("currency")
+ @ExcludeMissing
+ currency: JsonField = JsonMissing.of(),
+ @JsonProperty("image_url")
+ @ExcludeMissing
+ imageUrl: JsonField = JsonMissing.of(),
+ @JsonProperty("price") @ExcludeMissing price: JsonField = JsonMissing.of(),
+ @JsonProperty("pricing_model")
+ @ExcludeMissing
+ pricingModel: JsonField = JsonMissing.of(),
+ @JsonProperty("url") @ExcludeMissing url: JsonField = JsonMissing.of(),
+ ) : this(
+ description,
+ features,
+ name,
+ tags,
+ targetAudience,
+ billingFrequency,
+ category,
+ currency,
+ imageUrl,
+ price,
+ pricingModel,
+ url,
+ mutableMapOf(),
+ )
+
+ /**
+ * Description of the product
+ *
+ * @throws BrandDevInvalidDataException 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 description(): String = description.getRequired("description")
+
+ /**
+ * List of product features
+ *
+ * @throws BrandDevInvalidDataException 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 features(): List = features.getRequired("features")
+
+ /**
+ * Name of the product
+ *
+ * @throws BrandDevInvalidDataException 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")
+
+ /**
+ * Tags associated with the product
+ *
+ * @throws BrandDevInvalidDataException 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")
+
+ /**
+ * Target audience for the product (array of strings)
+ *
+ * @throws BrandDevInvalidDataException 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 targetAudience(): List = targetAudience.getRequired("target_audience")
+
+ /**
+ * Billing frequency for the product
+ *
+ * @throws BrandDevInvalidDataException if the JSON field has an unexpected type (e.g. if
+ * the server responded with an unexpected value).
+ */
+ fun billingFrequency(): Optional =
+ billingFrequency.getOptional("billing_frequency")
+
+ /**
+ * Category of the product
+ *
+ * @throws BrandDevInvalidDataException if the JSON field has an unexpected type (e.g. if
+ * the server responded with an unexpected value).
+ */
+ fun category(): Optional = category.getOptional("category")
+
+ /**
+ * Currency code for the price (e.g., USD, EUR)
+ *
+ * @throws BrandDevInvalidDataException if the JSON field has an unexpected type (e.g. if
+ * the server responded with an unexpected value).
+ */
+ fun currency(): Optional = currency.getOptional("currency")
+
+ /**
+ * URL to the product image
+ *
+ * @throws BrandDevInvalidDataException if the JSON field has an unexpected type (e.g. if
+ * the server responded with an unexpected value).
+ */
+ fun imageUrl(): Optional = imageUrl.getOptional("image_url")
+
+ /**
+ * Price of the product
+ *
+ * @throws BrandDevInvalidDataException if the JSON field has an unexpected type (e.g. if
+ * the server responded with an unexpected value).
+ */
+ fun price(): Optional = price.getOptional("price")
+
+ /**
+ * Pricing model for the product
+ *
+ * @throws BrandDevInvalidDataException if the JSON field has an unexpected type (e.g. if
+ * the server responded with an unexpected value).
+ */
+ fun pricingModel(): Optional = pricingModel.getOptional("pricing_model")
+
+ /**
+ * URL to the product page
+ *
+ * @throws BrandDevInvalidDataException if the JSON field has an unexpected type (e.g. if
+ * the server responded with an unexpected value).
+ */
+ fun url(): Optional = url.getOptional("url")
+
+ /**
+ * Returns the raw JSON value of [description].
+ *
+ * Unlike [description], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("description")
+ @ExcludeMissing
+ fun _description(): JsonField = description
+
+ /**
+ * Returns the raw JSON value of [features].
+ *
+ * Unlike [features], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("features")
+ @ExcludeMissing
+ fun _features(): JsonField> = features
+
+ /**
+ * 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 [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 [targetAudience].
+ *
+ * Unlike [targetAudience], this method doesn't throw if the JSON field has an unexpected
+ * type.
+ */
+ @JsonProperty("target_audience")
+ @ExcludeMissing
+ fun _targetAudience(): JsonField> = targetAudience
+
+ /**
+ * Returns the raw JSON value of [billingFrequency].
+ *
+ * Unlike [billingFrequency], this method doesn't throw if the JSON field has an unexpected
+ * type.
+ */
+ @JsonProperty("billing_frequency")
+ @ExcludeMissing
+ fun _billingFrequency(): JsonField = billingFrequency
+
+ /**
+ * Returns the raw JSON value of [category].
+ *
+ * Unlike [category], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("category") @ExcludeMissing fun _category(): JsonField = category
+
+ /**
+ * Returns the raw JSON value of [currency].
+ *
+ * Unlike [currency], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("currency") @ExcludeMissing fun _currency(): JsonField = currency
+
+ /**
+ * Returns the raw JSON value of [imageUrl].
+ *
+ * Unlike [imageUrl], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("image_url") @ExcludeMissing fun _imageUrl(): JsonField = imageUrl
+
+ /**
+ * Returns the raw JSON value of [price].
+ *
+ * Unlike [price], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("price") @ExcludeMissing fun _price(): JsonField = price
+
+ /**
+ * Returns the raw JSON value of [pricingModel].
+ *
+ * Unlike [pricingModel], this method doesn't throw if the JSON field has an unexpected
+ * type.
+ */
+ @JsonProperty("pricing_model")
+ @ExcludeMissing
+ fun _pricingModel(): JsonField = pricingModel
+
+ /**
+ * Returns the raw JSON value of [url].
+ *
+ * Unlike [url], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("url") @ExcludeMissing fun _url(): JsonField = url
+
+ @JsonAnySetter
+ private fun putAdditionalProperty(key: String, value: JsonValue) {
+ additionalProperties.put(key, value)
+ }
+
+ @JsonAnyGetter
+ @ExcludeMissing
+ fun _additionalProperties(): Map =
+ Collections.unmodifiableMap(additionalProperties)
+
+ fun toBuilder() = Builder().from(this)
+
+ companion object {
+
+ /**
+ * Returns a mutable builder for constructing an instance of [Product].
+ *
+ * The following fields are required:
+ * ```java
+ * .description()
+ * .features()
+ * .name()
+ * .tags()
+ * .targetAudience()
+ * ```
+ */
+ @JvmStatic fun builder() = Builder()
+ }
+
+ /** A builder for [Product]. */
+ class Builder internal constructor() {
+
+ private var description: JsonField? = null
+ private var features: JsonField>? = null
+ private var name: JsonField? = null
+ private var tags: JsonField>? = null
+ private var targetAudience: JsonField>? = null
+ private var billingFrequency: JsonField = JsonMissing.of()
+ private var category: JsonField = JsonMissing.of()
+ private var currency: JsonField = JsonMissing.of()
+ private var imageUrl: JsonField = JsonMissing.of()
+ private var price: JsonField = JsonMissing.of()
+ private var pricingModel: JsonField = JsonMissing.of()
+ private var url: JsonField = JsonMissing.of()
+ private var additionalProperties: MutableMap = mutableMapOf()
+
+ @JvmSynthetic
+ internal fun from(product: Product) = apply {
+ description = product.description
+ features = product.features.map { it.toMutableList() }
+ name = product.name
+ tags = product.tags.map { it.toMutableList() }
+ targetAudience = product.targetAudience.map { it.toMutableList() }
+ billingFrequency = product.billingFrequency
+ category = product.category
+ currency = product.currency
+ imageUrl = product.imageUrl
+ price = product.price
+ pricingModel = product.pricingModel
+ url = product.url
+ additionalProperties = product.additionalProperties.toMutableMap()
+ }
+
+ /** Description of the product */
+ fun description(description: String) = description(JsonField.of(description))
+
+ /**
+ * Sets [Builder.description] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.description] with a well-typed [String] value
+ * instead. This method is primarily for setting the field to an undocumented or not yet
+ * supported value.
+ */
+ fun description(description: JsonField) = apply {
+ this.description = description
+ }
+
+ /** List of product features */
+ fun features(features: List) = features(JsonField.of(features))
+
+ /**
+ * Sets [Builder.features] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.features] with a well-typed `List` value
+ * instead. This method is primarily for setting the field to an undocumented or not yet
+ * supported value.
+ */
+ fun features(features: JsonField>) = apply {
+ this.features = features.map { it.toMutableList() }
+ }
+
+ /**
+ * Adds a single [String] to [features].
+ *
+ * @throws IllegalStateException if the field was previously set to a non-list.
+ */
+ fun addFeature(feature: String) = apply {
+ features =
+ (features ?: JsonField.of(mutableListOf())).also {
+ checkKnown("features", it).add(feature)
+ }
+ }
+
+ /** Name of the product */
+ 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 }
+
+ /** Tags associated with the product */
+ 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) }
+ }
+
+ /** Target audience for the product (array of strings) */
+ fun targetAudience(targetAudience: List) =
+ targetAudience(JsonField.of(targetAudience))
+
+ /**
+ * Sets [Builder.targetAudience] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.targetAudience] with a well-typed `List`
+ * value instead. This method is primarily for setting the field to an undocumented or
+ * not yet supported value.
+ */
+ fun targetAudience(targetAudience: JsonField>) = apply {
+ this.targetAudience = targetAudience.map { it.toMutableList() }
+ }
+
+ /**
+ * Adds a single [String] to [Builder.targetAudience].
+ *
+ * @throws IllegalStateException if the field was previously set to a non-list.
+ */
+ fun addTargetAudience(targetAudience: String) = apply {
+ this.targetAudience =
+ (this.targetAudience ?: JsonField.of(mutableListOf())).also {
+ checkKnown("targetAudience", it).add(targetAudience)
+ }
+ }
+
+ /** Billing frequency for the product */
+ fun billingFrequency(billingFrequency: BillingFrequency?) =
+ billingFrequency(JsonField.ofNullable(billingFrequency))
+
+ /**
+ * Alias for calling [Builder.billingFrequency] with `billingFrequency.orElse(null)`.
+ */
+ fun billingFrequency(billingFrequency: Optional) =
+ billingFrequency(billingFrequency.getOrNull())
+
+ /**
+ * Sets [Builder.billingFrequency] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.billingFrequency] with a well-typed
+ * [BillingFrequency] value instead. This method is primarily for setting the field to
+ * an undocumented or not yet supported value.
+ */
+ fun billingFrequency(billingFrequency: JsonField) = apply {
+ this.billingFrequency = billingFrequency
+ }
+
+ /** Category of the product */
+ fun category(category: String?) = category(JsonField.ofNullable(category))
+
+ /** Alias for calling [Builder.category] with `category.orElse(null)`. */
+ fun category(category: Optional) = category(category.getOrNull())
+
+ /**
+ * Sets [Builder.category] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.category] with a well-typed [String] value instead.
+ * This method is primarily for setting the field to an undocumented or not yet
+ * supported value.
+ */
+ fun category(category: JsonField) = apply { this.category = category }
+
+ /** Currency code for the price (e.g., USD, EUR) */
+ fun currency(currency: String?) = currency(JsonField.ofNullable(currency))
+
+ /** Alias for calling [Builder.currency] with `currency.orElse(null)`. */
+ fun currency(currency: Optional) = currency(currency.getOrNull())
+
+ /**
+ * Sets [Builder.currency] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.currency] with a well-typed [String] value instead.
+ * This method is primarily for setting the field to an undocumented or not yet
+ * supported value.
+ */
+ fun currency(currency: JsonField) = apply { this.currency = currency }
+
+ /** URL to the product image */
+ fun imageUrl(imageUrl: String?) = imageUrl(JsonField.ofNullable(imageUrl))
+
+ /** Alias for calling [Builder.imageUrl] with `imageUrl.orElse(null)`. */
+ fun imageUrl(imageUrl: Optional) = imageUrl(imageUrl.getOrNull())
+
+ /**
+ * Sets [Builder.imageUrl] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.imageUrl] with a well-typed [String] value instead.
+ * This method is primarily for setting the field to an undocumented or not yet
+ * supported value.
+ */
+ fun imageUrl(imageUrl: JsonField) = apply { this.imageUrl = imageUrl }
+
+ /** Price of the product */
+ fun price(price: Double?) = price(JsonField.ofNullable(price))
+
+ /**
+ * Alias for [Builder.price].
+ *
+ * This unboxed primitive overload exists for backwards compatibility.
+ */
+ fun price(price: Double) = price(price as Double?)
+
+ /** Alias for calling [Builder.price] with `price.orElse(null)`. */
+ fun price(price: Optional) = price(price.getOrNull())
+
+ /**
+ * Sets [Builder.price] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.price] with a well-typed [Double] value instead.
+ * This method is primarily for setting the field to an undocumented or not yet
+ * supported value.
+ */
+ fun price(price: JsonField) = apply { this.price = price }
+
+ /** Pricing model for the product */
+ fun pricingModel(pricingModel: PricingModel?) =
+ pricingModel(JsonField.ofNullable(pricingModel))
+
+ /** Alias for calling [Builder.pricingModel] with `pricingModel.orElse(null)`. */
+ fun pricingModel(pricingModel: Optional) =
+ pricingModel(pricingModel.getOrNull())
+
+ /**
+ * Sets [Builder.pricingModel] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.pricingModel] with a well-typed [PricingModel] value
+ * instead. This method is primarily for setting the field to an undocumented or not yet
+ * supported value.
+ */
+ fun pricingModel(pricingModel: JsonField) = apply {
+ this.pricingModel = pricingModel
+ }
+
+ /** URL to the product page */
+ fun url(url: String?) = url(JsonField.ofNullable(url))
+
+ /** Alias for calling [Builder.url] with `url.orElse(null)`. */
+ fun url(url: Optional) = url(url.getOrNull())
+
+ /**
+ * Sets [Builder.url] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.url] with a well-typed [String] value instead. This
+ * method is primarily for setting the field to an undocumented or not yet supported
+ * value.
+ */
+ fun url(url: JsonField) = apply { this.url = url }
+
+ fun additionalProperties(additionalProperties: Map) = apply {
+ this.additionalProperties.clear()
+ putAllAdditionalProperties(additionalProperties)
+ }
+
+ fun putAdditionalProperty(key: String, value: JsonValue) = apply {
+ additionalProperties.put(key, value)
+ }
+
+ fun putAllAdditionalProperties(additionalProperties: Map) = apply {
+ this.additionalProperties.putAll(additionalProperties)
+ }
+
+ fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) }
+
+ fun removeAllAdditionalProperties(keys: Set) = apply {
+ keys.forEach(::removeAdditionalProperty)
+ }
+
+ /**
+ * Returns an immutable instance of [Product].
+ *
+ * Further updates to this [Builder] will not mutate the returned instance.
+ *
+ * The following fields are required:
+ * ```java
+ * .description()
+ * .features()
+ * .name()
+ * .tags()
+ * .targetAudience()
+ * ```
+ *
+ * @throws IllegalStateException if any required field is unset.
+ */
+ fun build(): Product =
+ Product(
+ checkRequired("description", description),
+ checkRequired("features", features).map { it.toImmutable() },
+ checkRequired("name", name),
+ checkRequired("tags", tags).map { it.toImmutable() },
+ checkRequired("targetAudience", targetAudience).map { it.toImmutable() },
+ billingFrequency,
+ category,
+ currency,
+ imageUrl,
+ price,
+ pricingModel,
+ url,
+ additionalProperties.toMutableMap(),
+ )
+ }
+
+ private var validated: Boolean = false
+
+ fun validate(): Product = apply {
+ if (validated) {
+ return@apply
+ }
+
+ description()
+ features()
+ name()
+ tags()
+ targetAudience()
+ billingFrequency().ifPresent { it.validate() }
+ category()
+ currency()
+ imageUrl()
+ price()
+ pricingModel().ifPresent { it.validate() }
+ url()
+ validated = true
+ }
+
+ fun isValid(): Boolean =
+ try {
+ validate()
+ true
+ } catch (e: BrandDevInvalidDataException) {
+ false
+ }
+
+ /**
+ * Returns a score indicating how many valid values are contained in this object
+ * recursively.
+ *
+ * Used for best match union deserialization.
+ */
+ @JvmSynthetic
+ internal fun validity(): Int =
+ (if (description.asKnown().isPresent) 1 else 0) +
+ (features.asKnown().getOrNull()?.size ?: 0) +
+ (if (name.asKnown().isPresent) 1 else 0) +
+ (tags.asKnown().getOrNull()?.size ?: 0) +
+ (targetAudience.asKnown().getOrNull()?.size ?: 0) +
+ (billingFrequency.asKnown().getOrNull()?.validity() ?: 0) +
+ (if (category.asKnown().isPresent) 1 else 0) +
+ (if (currency.asKnown().isPresent) 1 else 0) +
+ (if (imageUrl.asKnown().isPresent) 1 else 0) +
+ (if (price.asKnown().isPresent) 1 else 0) +
+ (pricingModel.asKnown().getOrNull()?.validity() ?: 0) +
+ (if (url.asKnown().isPresent) 1 else 0)
+
+ /** Billing frequency for the product */
+ class BillingFrequency
+ @JsonCreator
+ private constructor(private val value: JsonField) : Enum {
+
+ /**
+ * Returns this class instance's raw value.
+ *
+ * This is usually only useful if this instance was deserialized from data that doesn't
+ * match any known member, and you want to know that value. For example, if the SDK is
+ * on an older version than the API, then the API may respond with new members that the
+ * SDK is unaware of.
+ */
+ @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value
+
+ companion object {
+
+ @JvmField val MONTHLY = of("monthly")
+
+ @JvmField val YEARLY = of("yearly")
+
+ @JvmField val ONE_TIME = of("one_time")
+
+ @JvmField val USAGE_BASED = of("usage_based")
+
+ @JvmStatic fun of(value: String) = BillingFrequency(JsonField.of(value))
+ }
+
+ /** An enum containing [BillingFrequency]'s known values. */
+ enum class Known {
+ MONTHLY,
+ YEARLY,
+ ONE_TIME,
+ USAGE_BASED,
+ }
+
+ /**
+ * An enum containing [BillingFrequency]'s known values, as well as an [_UNKNOWN]
+ * member.
+ *
+ * An instance of [BillingFrequency] can contain an unknown value in a couple of cases:
+ * - It was deserialized from data that doesn't match any known member. For example, if
+ * the SDK is on an older version than the API, then the API may respond with new
+ * members that the SDK is unaware of.
+ * - It was constructed with an arbitrary value using the [of] method.
+ */
+ enum class Value {
+ MONTHLY,
+ YEARLY,
+ ONE_TIME,
+ USAGE_BASED,
+ /**
+ * An enum member indicating that [BillingFrequency] was instantiated with an
+ * unknown value.
+ */
+ _UNKNOWN,
+ }
+
+ /**
+ * Returns an enum member corresponding to this class instance's value, or
+ * [Value._UNKNOWN] if the class was instantiated with an unknown value.
+ *
+ * Use the [known] method instead if you're certain the value is always known or if you
+ * want to throw for the unknown case.
+ */
+ fun value(): Value =
+ when (this) {
+ MONTHLY -> Value.MONTHLY
+ YEARLY -> Value.YEARLY
+ ONE_TIME -> Value.ONE_TIME
+ USAGE_BASED -> Value.USAGE_BASED
+ else -> Value._UNKNOWN
+ }
+
+ /**
+ * Returns an enum member corresponding to this class instance's value.
+ *
+ * Use the [value] method instead if you're uncertain the value is always known and
+ * don't want to throw for the unknown case.
+ *
+ * @throws BrandDevInvalidDataException if this class instance's value is a not a known
+ * member.
+ */
+ fun known(): Known =
+ when (this) {
+ MONTHLY -> Known.MONTHLY
+ YEARLY -> Known.YEARLY
+ ONE_TIME -> Known.ONE_TIME
+ USAGE_BASED -> Known.USAGE_BASED
+ else -> throw BrandDevInvalidDataException("Unknown BillingFrequency: $value")
+ }
+
+ /**
+ * Returns this class instance's primitive wire representation.
+ *
+ * This differs from the [toString] method because that method is primarily for
+ * debugging and generally doesn't throw.
+ *
+ * @throws BrandDevInvalidDataException if this class instance's value does not have the
+ * expected primitive type.
+ */
+ fun asString(): String =
+ _value().asString().orElseThrow {
+ BrandDevInvalidDataException("Value is not a String")
+ }
+
+ private var validated: Boolean = false
+
+ fun validate(): BillingFrequency = apply {
+ if (validated) {
+ return@apply
+ }
+
+ known()
+ validated = true
+ }
+
+ fun isValid(): Boolean =
+ try {
+ validate()
+ true
+ } catch (e: BrandDevInvalidDataException) {
+ false
+ }
+
+ /**
+ * Returns a score indicating how many valid values are contained in this object
+ * recursively.
+ *
+ * Used for best match union deserialization.
+ */
+ @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) {
+ return true
+ }
+
+ return other is BillingFrequency && value == other.value
+ }
+
+ override fun hashCode() = value.hashCode()
+
+ override fun toString() = value.toString()
+ }
+
+ /** Pricing model for the product */
+ class PricingModel @JsonCreator private constructor(private val value: JsonField) :
+ Enum {
+
+ /**
+ * Returns this class instance's raw value.
+ *
+ * This is usually only useful if this instance was deserialized from data that doesn't
+ * match any known member, and you want to know that value. For example, if the SDK is
+ * on an older version than the API, then the API may respond with new members that the
+ * SDK is unaware of.
+ */
+ @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value
+
+ companion object {
+
+ @JvmField val PER_SEAT = of("per_seat")
+
+ @JvmField val FLAT = of("flat")
+
+ @JvmField val TIERED = of("tiered")
+
+ @JvmField val FREEMIUM = of("freemium")
+
+ @JvmField val CUSTOM = of("custom")
+
+ @JvmStatic fun of(value: String) = PricingModel(JsonField.of(value))
+ }
+
+ /** An enum containing [PricingModel]'s known values. */
+ enum class Known {
+ PER_SEAT,
+ FLAT,
+ TIERED,
+ FREEMIUM,
+ CUSTOM,
+ }
+
+ /**
+ * An enum containing [PricingModel]'s known values, as well as an [_UNKNOWN] member.
+ *
+ * An instance of [PricingModel] can contain an unknown value in a couple of cases:
+ * - It was deserialized from data that doesn't match any known member. For example, if
+ * the SDK is on an older version than the API, then the API may respond with new
+ * members that the SDK is unaware of.
+ * - It was constructed with an arbitrary value using the [of] method.
+ */
+ enum class Value {
+ PER_SEAT,
+ FLAT,
+ TIERED,
+ FREEMIUM,
+ CUSTOM,
+ /**
+ * An enum member indicating that [PricingModel] was instantiated with an unknown
+ * value.
+ */
+ _UNKNOWN,
+ }
+
+ /**
+ * Returns an enum member corresponding to this class instance's value, or
+ * [Value._UNKNOWN] if the class was instantiated with an unknown value.
+ *
+ * Use the [known] method instead if you're certain the value is always known or if you
+ * want to throw for the unknown case.
+ */
+ fun value(): Value =
+ when (this) {
+ PER_SEAT -> Value.PER_SEAT
+ FLAT -> Value.FLAT
+ TIERED -> Value.TIERED
+ FREEMIUM -> Value.FREEMIUM
+ CUSTOM -> Value.CUSTOM
+ else -> Value._UNKNOWN
+ }
+
+ /**
+ * Returns an enum member corresponding to this class instance's value.
+ *
+ * Use the [value] method instead if you're uncertain the value is always known and
+ * don't want to throw for the unknown case.
+ *
+ * @throws BrandDevInvalidDataException if this class instance's value is a not a known
+ * member.
+ */
+ fun known(): Known =
+ when (this) {
+ PER_SEAT -> Known.PER_SEAT
+ FLAT -> Known.FLAT
+ TIERED -> Known.TIERED
+ FREEMIUM -> Known.FREEMIUM
+ CUSTOM -> Known.CUSTOM
+ else -> throw BrandDevInvalidDataException("Unknown PricingModel: $value")
+ }
+
+ /**
+ * Returns this class instance's primitive wire representation.
+ *
+ * This differs from the [toString] method because that method is primarily for
+ * debugging and generally doesn't throw.
+ *
+ * @throws BrandDevInvalidDataException if this class instance's value does not have the
+ * expected primitive type.
+ */
+ fun asString(): String =
+ _value().asString().orElseThrow {
+ BrandDevInvalidDataException("Value is not a String")
+ }
+
+ private var validated: Boolean = false
+
+ fun validate(): PricingModel = apply {
+ if (validated) {
+ return@apply
+ }
+
+ known()
+ validated = true
+ }
+
+ fun isValid(): Boolean =
+ try {
+ validate()
+ true
+ } catch (e: BrandDevInvalidDataException) {
+ false
+ }
+
+ /**
+ * Returns a score indicating how many valid values are contained in this object
+ * recursively.
+ *
+ * Used for best match union deserialization.
+ */
+ @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) {
+ return true
+ }
+
+ return other is PricingModel && value == other.value
+ }
+
+ override fun hashCode() = value.hashCode()
+
+ override fun toString() = value.toString()
+ }
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) {
+ return true
+ }
+
+ return other is Product &&
+ description == other.description &&
+ features == other.features &&
+ name == other.name &&
+ tags == other.tags &&
+ targetAudience == other.targetAudience &&
+ billingFrequency == other.billingFrequency &&
+ category == other.category &&
+ currency == other.currency &&
+ imageUrl == other.imageUrl &&
+ price == other.price &&
+ pricingModel == other.pricingModel &&
+ url == other.url &&
+ additionalProperties == other.additionalProperties
+ }
+
+ private val hashCode: Int by lazy {
+ Objects.hash(
+ description,
+ features,
+ name,
+ tags,
+ targetAudience,
+ billingFrequency,
+ category,
+ currency,
+ imageUrl,
+ price,
+ pricingModel,
+ url,
+ additionalProperties,
+ )
+ }
+
+ override fun hashCode(): Int = hashCode
+
+ override fun toString() =
+ "Product{description=$description, features=$features, name=$name, tags=$tags, targetAudience=$targetAudience, billingFrequency=$billingFrequency, category=$category, currency=$currency, imageUrl=$imageUrl, price=$price, pricingModel=$pricingModel, url=$url, additionalProperties=$additionalProperties}"
+ }
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) {
+ return true
+ }
+
+ return other is BrandAiProductResponse &&
+ isProductPage == other.isProductPage &&
+ platform == other.platform &&
+ product == other.product &&
+ additionalProperties == other.additionalProperties
+ }
+
+ private val hashCode: Int by lazy {
+ Objects.hash(isProductPage, platform, product, additionalProperties)
+ }
+
+ override fun hashCode(): Int = hashCode
+
+ override fun toString() =
+ "BrandAiProductResponse{isProductPage=$isProductPage, platform=$platform, product=$product, additionalProperties=$additionalProperties}"
+}
diff --git a/brand-dev-java-core/src/main/kotlin/com/branddev/api/services/async/BrandServiceAsync.kt b/brand-dev-java-core/src/main/kotlin/com/branddev/api/services/async/BrandServiceAsync.kt
index 4500458..55778f1 100644
--- a/brand-dev-java-core/src/main/kotlin/com/branddev/api/services/async/BrandServiceAsync.kt
+++ b/brand-dev-java-core/src/main/kotlin/com/branddev/api/services/async/BrandServiceAsync.kt
@@ -5,6 +5,8 @@ package com.branddev.api.services.async
import com.branddev.api.core.ClientOptions
import com.branddev.api.core.RequestOptions
import com.branddev.api.core.http.HttpResponseFor
+import com.branddev.api.models.brand.BrandAiProductParams
+import com.branddev.api.models.brand.BrandAiProductResponse
import com.branddev.api.models.brand.BrandAiProductsParams
import com.branddev.api.models.brand.BrandAiProductsResponse
import com.branddev.api.models.brand.BrandAiQueryParams
@@ -62,6 +64,20 @@ interface BrandServiceAsync {
requestOptions: RequestOptions = RequestOptions.none(),
): CompletableFuture
+ /**
+ * Beta feature: Given a single URL, determines if it is a product detail page, classifies the
+ * platform/product type, and extracts the product information. Supports Amazon, TikTok Shop,
+ * Etsy, and generic ecommerce sites.
+ */
+ fun aiProduct(params: BrandAiProductParams): CompletableFuture =
+ aiProduct(params, RequestOptions.none())
+
+ /** @see aiProduct */
+ fun aiProduct(
+ params: BrandAiProductParams,
+ requestOptions: RequestOptions = RequestOptions.none(),
+ ): CompletableFuture
+
/**
* Beta feature: Extract product information from a brand's website. Brand.dev will analyze the
* website and return a list of products with details such as name, description, image, pricing,
@@ -293,6 +309,21 @@ interface BrandServiceAsync {
requestOptions: RequestOptions = RequestOptions.none(),
): CompletableFuture>
+ /**
+ * Returns a raw HTTP response for `post /brand/ai/product`, but is otherwise the same as
+ * [BrandServiceAsync.aiProduct].
+ */
+ fun aiProduct(
+ params: BrandAiProductParams
+ ): CompletableFuture> =
+ aiProduct(params, RequestOptions.none())
+
+ /** @see aiProduct */
+ fun aiProduct(
+ params: BrandAiProductParams,
+ requestOptions: RequestOptions = RequestOptions.none(),
+ ): CompletableFuture>
+
/**
* Returns a raw HTTP response for `post /brand/ai/products`, but is otherwise the same as
* [BrandServiceAsync.aiProducts].
diff --git a/brand-dev-java-core/src/main/kotlin/com/branddev/api/services/async/BrandServiceAsyncImpl.kt b/brand-dev-java-core/src/main/kotlin/com/branddev/api/services/async/BrandServiceAsyncImpl.kt
index b041b94..4592ca1 100644
--- a/brand-dev-java-core/src/main/kotlin/com/branddev/api/services/async/BrandServiceAsyncImpl.kt
+++ b/brand-dev-java-core/src/main/kotlin/com/branddev/api/services/async/BrandServiceAsyncImpl.kt
@@ -15,6 +15,8 @@ import com.branddev.api.core.http.HttpResponseFor
import com.branddev.api.core.http.json
import com.branddev.api.core.http.parseable
import com.branddev.api.core.prepareAsync
+import com.branddev.api.models.brand.BrandAiProductParams
+import com.branddev.api.models.brand.BrandAiProductResponse
import com.branddev.api.models.brand.BrandAiProductsParams
import com.branddev.api.models.brand.BrandAiProductsResponse
import com.branddev.api.models.brand.BrandAiQueryParams
@@ -67,6 +69,13 @@ class BrandServiceAsyncImpl internal constructor(private val clientOptions: Clie
// get /brand/retrieve
withRawResponse().retrieve(params, requestOptions).thenApply { it.parse() }
+ override fun aiProduct(
+ params: BrandAiProductParams,
+ requestOptions: RequestOptions,
+ ): CompletableFuture =
+ // post /brand/ai/product
+ withRawResponse().aiProduct(params, requestOptions).thenApply { it.parse() }
+
override fun aiProducts(
params: BrandAiProductsParams,
requestOptions: RequestOptions,
@@ -208,6 +217,37 @@ class BrandServiceAsyncImpl internal constructor(private val clientOptions: Clie
}
}
+ private val aiProductHandler: Handler =
+ jsonHandler(clientOptions.jsonMapper)
+
+ override fun aiProduct(
+ params: BrandAiProductParams,
+ requestOptions: RequestOptions,
+ ): CompletableFuture> {
+ val request =
+ HttpRequest.builder()
+ .method(HttpMethod.POST)
+ .baseUrl(clientOptions.baseUrl())
+ .addPathSegments("brand", "ai", "product")
+ .body(json(clientOptions.jsonMapper, params._body()))
+ .build()
+ .prepareAsync(clientOptions, params)
+ val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions))
+ return request
+ .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) }
+ .thenApply { response ->
+ errorHandler.handle(response).parseable {
+ response
+ .use { aiProductHandler.handle(it) }
+ .also {
+ if (requestOptions.responseValidation!!) {
+ it.validate()
+ }
+ }
+ }
+ }
+ }
+
private val aiProductsHandler: Handler =
jsonHandler(clientOptions.jsonMapper)
diff --git a/brand-dev-java-core/src/main/kotlin/com/branddev/api/services/blocking/BrandService.kt b/brand-dev-java-core/src/main/kotlin/com/branddev/api/services/blocking/BrandService.kt
index b467fc0..e1b4d44 100644
--- a/brand-dev-java-core/src/main/kotlin/com/branddev/api/services/blocking/BrandService.kt
+++ b/brand-dev-java-core/src/main/kotlin/com/branddev/api/services/blocking/BrandService.kt
@@ -5,6 +5,8 @@ package com.branddev.api.services.blocking
import com.branddev.api.core.ClientOptions
import com.branddev.api.core.RequestOptions
import com.branddev.api.core.http.HttpResponseFor
+import com.branddev.api.models.brand.BrandAiProductParams
+import com.branddev.api.models.brand.BrandAiProductResponse
import com.branddev.api.models.brand.BrandAiProductsParams
import com.branddev.api.models.brand.BrandAiProductsResponse
import com.branddev.api.models.brand.BrandAiQueryParams
@@ -62,6 +64,20 @@ interface BrandService {
requestOptions: RequestOptions = RequestOptions.none(),
): BrandRetrieveResponse
+ /**
+ * Beta feature: Given a single URL, determines if it is a product detail page, classifies the
+ * platform/product type, and extracts the product information. Supports Amazon, TikTok Shop,
+ * Etsy, and generic ecommerce sites.
+ */
+ fun aiProduct(params: BrandAiProductParams): BrandAiProductResponse =
+ aiProduct(params, RequestOptions.none())
+
+ /** @see aiProduct */
+ fun aiProduct(
+ params: BrandAiProductParams,
+ requestOptions: RequestOptions = RequestOptions.none(),
+ ): BrandAiProductResponse
+
/**
* Beta feature: Extract product information from a brand's website. Brand.dev will analyze the
* website and return a list of products with details such as name, description, image, pricing,
@@ -276,6 +292,21 @@ interface BrandService {
requestOptions: RequestOptions = RequestOptions.none(),
): HttpResponseFor
+ /**
+ * Returns a raw HTTP response for `post /brand/ai/product`, but is otherwise the same as
+ * [BrandService.aiProduct].
+ */
+ @MustBeClosed
+ fun aiProduct(params: BrandAiProductParams): HttpResponseFor =
+ aiProduct(params, RequestOptions.none())
+
+ /** @see aiProduct */
+ @MustBeClosed
+ fun aiProduct(
+ params: BrandAiProductParams,
+ requestOptions: RequestOptions = RequestOptions.none(),
+ ): HttpResponseFor
+
/**
* Returns a raw HTTP response for `post /brand/ai/products`, but is otherwise the same as
* [BrandService.aiProducts].
diff --git a/brand-dev-java-core/src/main/kotlin/com/branddev/api/services/blocking/BrandServiceImpl.kt b/brand-dev-java-core/src/main/kotlin/com/branddev/api/services/blocking/BrandServiceImpl.kt
index 7881de3..1fa6a43 100644
--- a/brand-dev-java-core/src/main/kotlin/com/branddev/api/services/blocking/BrandServiceImpl.kt
+++ b/brand-dev-java-core/src/main/kotlin/com/branddev/api/services/blocking/BrandServiceImpl.kt
@@ -15,6 +15,8 @@ import com.branddev.api.core.http.HttpResponseFor
import com.branddev.api.core.http.json
import com.branddev.api.core.http.parseable
import com.branddev.api.core.prepare
+import com.branddev.api.models.brand.BrandAiProductParams
+import com.branddev.api.models.brand.BrandAiProductResponse
import com.branddev.api.models.brand.BrandAiProductsParams
import com.branddev.api.models.brand.BrandAiProductsResponse
import com.branddev.api.models.brand.BrandAiQueryParams
@@ -66,6 +68,13 @@ class BrandServiceImpl internal constructor(private val clientOptions: ClientOpt
// get /brand/retrieve
withRawResponse().retrieve(params, requestOptions).parse()
+ override fun aiProduct(
+ params: BrandAiProductParams,
+ requestOptions: RequestOptions,
+ ): BrandAiProductResponse =
+ // post /brand/ai/product
+ withRawResponse().aiProduct(params, requestOptions).parse()
+
override fun aiProducts(
params: BrandAiProductsParams,
requestOptions: RequestOptions,
@@ -204,6 +213,34 @@ class BrandServiceImpl internal constructor(private val clientOptions: ClientOpt
}
}
+ private val aiProductHandler: Handler =
+ jsonHandler(clientOptions.jsonMapper)
+
+ override fun aiProduct(
+ params: BrandAiProductParams,
+ requestOptions: RequestOptions,
+ ): HttpResponseFor {
+ val request =
+ HttpRequest.builder()
+ .method(HttpMethod.POST)
+ .baseUrl(clientOptions.baseUrl())
+ .addPathSegments("brand", "ai", "product")
+ .body(json(clientOptions.jsonMapper, params._body()))
+ .build()
+ .prepare(clientOptions, params)
+ val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions))
+ val response = clientOptions.httpClient.execute(request, requestOptions)
+ return errorHandler.handle(response).parseable {
+ response
+ .use { aiProductHandler.handle(it) }
+ .also {
+ if (requestOptions.responseValidation!!) {
+ it.validate()
+ }
+ }
+ }
+ }
+
private val aiProductsHandler: Handler =
jsonHandler(clientOptions.jsonMapper)
diff --git a/brand-dev-java-core/src/test/kotlin/com/branddev/api/TestServerExtension.kt b/brand-dev-java-core/src/test/kotlin/com/branddev/api/TestServerExtension.kt
index 89c422f..9813639 100644
--- a/brand-dev-java-core/src/test/kotlin/com/branddev/api/TestServerExtension.kt
+++ b/brand-dev-java-core/src/test/kotlin/com/branddev/api/TestServerExtension.kt
@@ -15,25 +15,12 @@ class TestServerExtension : BeforeAllCallback, ExecutionCondition {
} catch (e: Exception) {
throw RuntimeException(
"""
- The test suite will not run without a mock Prism server running against your OpenAPI spec.
+ The test suite will not run without a mock server running against your OpenAPI spec.
You can set the environment variable `SKIP_MOCK_TESTS` to `true` to skip running any tests
that require the mock server.
- To fix:
-
- 1. Install Prism (requires Node 16+):
-
- With npm:
- $ npm install -g @stoplight/prism-cli
-
- With yarn:
- $ yarn global add @stoplight/prism-cli
-
- 2. Run the mock server
-
- To run the server, pass in the path of your OpenAPI spec to the prism command:
- $ prism mock path/to/your.openapi.yml
+ To fix run `./scripts/mock` in a separate terminal.
"""
.trimIndent(),
e,
diff --git a/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandAiProductParamsTest.kt b/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandAiProductParamsTest.kt
new file mode 100644
index 0000000..56369c7
--- /dev/null
+++ b/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandAiProductParamsTest.kt
@@ -0,0 +1,34 @@
+// File generated from our OpenAPI spec by Stainless.
+
+package com.branddev.api.models.brand
+
+import org.assertj.core.api.Assertions.assertThat
+import org.junit.jupiter.api.Test
+
+internal class BrandAiProductParamsTest {
+
+ @Test
+ fun create() {
+ BrandAiProductParams.builder().url("https://example.com").timeoutMs(1000L).build()
+ }
+
+ @Test
+ fun body() {
+ val params =
+ BrandAiProductParams.builder().url("https://example.com").timeoutMs(1000L).build()
+
+ val body = params._body()
+
+ assertThat(body.url()).isEqualTo("https://example.com")
+ assertThat(body.timeoutMs()).contains(1000L)
+ }
+
+ @Test
+ fun bodyWithoutOptionalFields() {
+ val params = BrandAiProductParams.builder().url("https://example.com").build()
+
+ val body = params._body()
+
+ assertThat(body.url()).isEqualTo("https://example.com")
+ }
+}
diff --git a/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandAiProductResponseTest.kt b/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandAiProductResponseTest.kt
new file mode 100644
index 0000000..7c9676c
--- /dev/null
+++ b/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandAiProductResponseTest.kt
@@ -0,0 +1,91 @@
+// File generated from our OpenAPI spec by Stainless.
+
+package com.branddev.api.models.brand
+
+import com.branddev.api.core.jsonMapper
+import com.fasterxml.jackson.module.kotlin.jacksonTypeRef
+import org.assertj.core.api.Assertions.assertThat
+import org.junit.jupiter.api.Test
+
+internal class BrandAiProductResponseTest {
+
+ @Test
+ fun create() {
+ val brandAiProductResponse =
+ BrandAiProductResponse.builder()
+ .isProductPage(true)
+ .platform(BrandAiProductResponse.Platform.AMAZON)
+ .product(
+ BrandAiProductResponse.Product.builder()
+ .description("description")
+ .addFeature("string")
+ .name("name")
+ .addTag("string")
+ .addTargetAudience("string")
+ .billingFrequency(BrandAiProductResponse.Product.BillingFrequency.MONTHLY)
+ .category("category")
+ .currency("currency")
+ .imageUrl("image_url")
+ .price(0.0)
+ .pricingModel(BrandAiProductResponse.Product.PricingModel.PER_SEAT)
+ .url("url")
+ .build()
+ )
+ .build()
+
+ assertThat(brandAiProductResponse.isProductPage()).contains(true)
+ assertThat(brandAiProductResponse.platform())
+ .contains(BrandAiProductResponse.Platform.AMAZON)
+ assertThat(brandAiProductResponse.product())
+ .contains(
+ BrandAiProductResponse.Product.builder()
+ .description("description")
+ .addFeature("string")
+ .name("name")
+ .addTag("string")
+ .addTargetAudience("string")
+ .billingFrequency(BrandAiProductResponse.Product.BillingFrequency.MONTHLY)
+ .category("category")
+ .currency("currency")
+ .imageUrl("image_url")
+ .price(0.0)
+ .pricingModel(BrandAiProductResponse.Product.PricingModel.PER_SEAT)
+ .url("url")
+ .build()
+ )
+ }
+
+ @Test
+ fun roundtrip() {
+ val jsonMapper = jsonMapper()
+ val brandAiProductResponse =
+ BrandAiProductResponse.builder()
+ .isProductPage(true)
+ .platform(BrandAiProductResponse.Platform.AMAZON)
+ .product(
+ BrandAiProductResponse.Product.builder()
+ .description("description")
+ .addFeature("string")
+ .name("name")
+ .addTag("string")
+ .addTargetAudience("string")
+ .billingFrequency(BrandAiProductResponse.Product.BillingFrequency.MONTHLY)
+ .category("category")
+ .currency("currency")
+ .imageUrl("image_url")
+ .price(0.0)
+ .pricingModel(BrandAiProductResponse.Product.PricingModel.PER_SEAT)
+ .url("url")
+ .build()
+ )
+ .build()
+
+ val roundtrippedBrandAiProductResponse =
+ jsonMapper.readValue(
+ jsonMapper.writeValueAsString(brandAiProductResponse),
+ jacksonTypeRef(),
+ )
+
+ assertThat(roundtrippedBrandAiProductResponse).isEqualTo(brandAiProductResponse)
+ }
+}
diff --git a/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandAiProductsParamsTest.kt b/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandAiProductsParamsTest.kt
index 5d5ad09..fb23d73 100644
--- a/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandAiProductsParamsTest.kt
+++ b/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandAiProductsParamsTest.kt
@@ -14,7 +14,7 @@ internal class BrandAiProductsParamsTest {
BrandAiProductsParams.Body.ByDomain.builder()
.domain("domain")
.maxProducts(1L)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
)
.build()
@@ -28,7 +28,7 @@ internal class BrandAiProductsParamsTest {
BrandAiProductsParams.Body.ByDomain.builder()
.domain("domain")
.maxProducts(1L)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
)
.build()
@@ -41,7 +41,7 @@ internal class BrandAiProductsParamsTest {
BrandAiProductsParams.Body.ByDomain.builder()
.domain("domain")
.maxProducts(1L)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
)
)
diff --git a/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandAiQueryParamsTest.kt b/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandAiQueryParamsTest.kt
index 7449dd8..e721f3e 100644
--- a/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandAiQueryParamsTest.kt
+++ b/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandAiQueryParamsTest.kt
@@ -40,7 +40,7 @@ internal class BrandAiQueryParamsTest {
.termsAndConditions(true)
.build()
)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
}
@@ -82,7 +82,7 @@ internal class BrandAiQueryParamsTest {
.termsAndConditions(true)
.build()
)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
val body = params._body()
@@ -118,7 +118,7 @@ internal class BrandAiQueryParamsTest {
.termsAndConditions(true)
.build()
)
- assertThat(body.timeoutMs()).contains(1L)
+ assertThat(body.timeoutMs()).contains(1000L)
}
@Test
diff --git a/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandFontsParamsTest.kt b/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandFontsParamsTest.kt
index 9ce2e95..5e6e635 100644
--- a/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandFontsParamsTest.kt
+++ b/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandFontsParamsTest.kt
@@ -10,17 +10,19 @@ internal class BrandFontsParamsTest {
@Test
fun create() {
- BrandFontsParams.builder().domain("domain").timeoutMs(1L).build()
+ BrandFontsParams.builder().domain("domain").timeoutMs(1000L).build()
}
@Test
fun queryParams() {
- val params = BrandFontsParams.builder().domain("domain").timeoutMs(1L).build()
+ val params = BrandFontsParams.builder().domain("domain").timeoutMs(1000L).build()
val queryParams = params._queryParams()
assertThat(queryParams)
- .isEqualTo(QueryParams.builder().put("domain", "domain").put("timeoutMS", "1").build())
+ .isEqualTo(
+ QueryParams.builder().put("domain", "domain").put("timeoutMS", "1000").build()
+ )
}
@Test
diff --git a/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandIdentifyFromTransactionParamsTest.kt b/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandIdentifyFromTransactionParamsTest.kt
index 3b04b9a..a8dc9df 100644
--- a/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandIdentifyFromTransactionParamsTest.kt
+++ b/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandIdentifyFromTransactionParamsTest.kt
@@ -18,7 +18,7 @@ internal class BrandIdentifyFromTransactionParamsTest {
.maxSpeed(true)
.mcc("mcc")
.phone(0.0)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
}
@@ -33,7 +33,7 @@ internal class BrandIdentifyFromTransactionParamsTest {
.maxSpeed(true)
.mcc("mcc")
.phone(0.0)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
val queryParams = params._queryParams()
@@ -48,7 +48,7 @@ internal class BrandIdentifyFromTransactionParamsTest {
.put("maxSpeed", "true")
.put("mcc", "mcc")
.put("phone", "0.0")
- .put("timeoutMS", "1")
+ .put("timeoutMS", "1000")
.build()
)
}
diff --git a/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandPrefetchByEmailParamsTest.kt b/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandPrefetchByEmailParamsTest.kt
index 8a47dd9..8ecbb92 100644
--- a/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandPrefetchByEmailParamsTest.kt
+++ b/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandPrefetchByEmailParamsTest.kt
@@ -9,18 +9,18 @@ internal class BrandPrefetchByEmailParamsTest {
@Test
fun create() {
- BrandPrefetchByEmailParams.builder().email("dev@stainless.com").timeoutMs(1L).build()
+ BrandPrefetchByEmailParams.builder().email("dev@stainless.com").timeoutMs(1000L).build()
}
@Test
fun body() {
val params =
- BrandPrefetchByEmailParams.builder().email("dev@stainless.com").timeoutMs(1L).build()
+ BrandPrefetchByEmailParams.builder().email("dev@stainless.com").timeoutMs(1000L).build()
val body = params._body()
assertThat(body.email()).isEqualTo("dev@stainless.com")
- assertThat(body.timeoutMs()).contains(1L)
+ assertThat(body.timeoutMs()).contains(1000L)
}
@Test
diff --git a/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandPrefetchParamsTest.kt b/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandPrefetchParamsTest.kt
index b2ef496..6d48741 100644
--- a/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandPrefetchParamsTest.kt
+++ b/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandPrefetchParamsTest.kt
@@ -9,17 +9,17 @@ internal class BrandPrefetchParamsTest {
@Test
fun create() {
- BrandPrefetchParams.builder().domain("domain").timeoutMs(1L).build()
+ BrandPrefetchParams.builder().domain("domain").timeoutMs(1000L).build()
}
@Test
fun body() {
- val params = BrandPrefetchParams.builder().domain("domain").timeoutMs(1L).build()
+ val params = BrandPrefetchParams.builder().domain("domain").timeoutMs(1000L).build()
val body = params._body()
assertThat(body.domain()).isEqualTo("domain")
- assertThat(body.timeoutMs()).contains(1L)
+ assertThat(body.timeoutMs()).contains(1000L)
}
@Test
diff --git a/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandRetrieveByEmailParamsTest.kt b/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandRetrieveByEmailParamsTest.kt
index 91df822..7623105 100644
--- a/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandRetrieveByEmailParamsTest.kt
+++ b/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandRetrieveByEmailParamsTest.kt
@@ -14,7 +14,7 @@ internal class BrandRetrieveByEmailParamsTest {
.email("dev@stainless.com")
.forceLanguage(BrandRetrieveByEmailParams.ForceLanguage.ALBANIAN)
.maxSpeed(true)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
}
@@ -25,7 +25,7 @@ internal class BrandRetrieveByEmailParamsTest {
.email("dev@stainless.com")
.forceLanguage(BrandRetrieveByEmailParams.ForceLanguage.ALBANIAN)
.maxSpeed(true)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
val queryParams = params._queryParams()
@@ -36,7 +36,7 @@ internal class BrandRetrieveByEmailParamsTest {
.put("email", "dev@stainless.com")
.put("force_language", "albanian")
.put("maxSpeed", "true")
- .put("timeoutMS", "1")
+ .put("timeoutMS", "1000")
.build()
)
}
diff --git a/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandRetrieveByIsinParamsTest.kt b/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandRetrieveByIsinParamsTest.kt
index a0c5032..482fdc9 100644
--- a/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandRetrieveByIsinParamsTest.kt
+++ b/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandRetrieveByIsinParamsTest.kt
@@ -14,7 +14,7 @@ internal class BrandRetrieveByIsinParamsTest {
.isin("SE60513A9993")
.forceLanguage(BrandRetrieveByIsinParams.ForceLanguage.ALBANIAN)
.maxSpeed(true)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
}
@@ -25,7 +25,7 @@ internal class BrandRetrieveByIsinParamsTest {
.isin("SE60513A9993")
.forceLanguage(BrandRetrieveByIsinParams.ForceLanguage.ALBANIAN)
.maxSpeed(true)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
val queryParams = params._queryParams()
@@ -36,7 +36,7 @@ internal class BrandRetrieveByIsinParamsTest {
.put("isin", "SE60513A9993")
.put("force_language", "albanian")
.put("maxSpeed", "true")
- .put("timeoutMS", "1")
+ .put("timeoutMS", "1000")
.build()
)
}
diff --git a/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandRetrieveByNameParamsTest.kt b/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandRetrieveByNameParamsTest.kt
index 6a8c443..bd3d663 100644
--- a/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandRetrieveByNameParamsTest.kt
+++ b/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandRetrieveByNameParamsTest.kt
@@ -14,7 +14,7 @@ internal class BrandRetrieveByNameParamsTest {
.name("xxx")
.forceLanguage(BrandRetrieveByNameParams.ForceLanguage.ALBANIAN)
.maxSpeed(true)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
}
@@ -25,7 +25,7 @@ internal class BrandRetrieveByNameParamsTest {
.name("xxx")
.forceLanguage(BrandRetrieveByNameParams.ForceLanguage.ALBANIAN)
.maxSpeed(true)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
val queryParams = params._queryParams()
@@ -36,7 +36,7 @@ internal class BrandRetrieveByNameParamsTest {
.put("name", "xxx")
.put("force_language", "albanian")
.put("maxSpeed", "true")
- .put("timeoutMS", "1")
+ .put("timeoutMS", "1000")
.build()
)
}
diff --git a/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandRetrieveByTickerParamsTest.kt b/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandRetrieveByTickerParamsTest.kt
index a8abcba..da35924 100644
--- a/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandRetrieveByTickerParamsTest.kt
+++ b/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandRetrieveByTickerParamsTest.kt
@@ -15,7 +15,7 @@ internal class BrandRetrieveByTickerParamsTest {
.forceLanguage(BrandRetrieveByTickerParams.ForceLanguage.ALBANIAN)
.maxSpeed(true)
.tickerExchange(BrandRetrieveByTickerParams.TickerExchange.AMEX)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
}
@@ -27,7 +27,7 @@ internal class BrandRetrieveByTickerParamsTest {
.forceLanguage(BrandRetrieveByTickerParams.ForceLanguage.ALBANIAN)
.maxSpeed(true)
.tickerExchange(BrandRetrieveByTickerParams.TickerExchange.AMEX)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
val queryParams = params._queryParams()
@@ -39,7 +39,7 @@ internal class BrandRetrieveByTickerParamsTest {
.put("force_language", "albanian")
.put("maxSpeed", "true")
.put("ticker_exchange", "AMEX")
- .put("timeoutMS", "1")
+ .put("timeoutMS", "1000")
.build()
)
}
diff --git a/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandRetrieveNaicsParamsTest.kt b/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandRetrieveNaicsParamsTest.kt
index e785ab4..287374f 100644
--- a/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandRetrieveNaicsParamsTest.kt
+++ b/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandRetrieveNaicsParamsTest.kt
@@ -14,7 +14,7 @@ internal class BrandRetrieveNaicsParamsTest {
.input("input")
.maxResults(1L)
.minResults(1L)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
}
@@ -25,7 +25,7 @@ internal class BrandRetrieveNaicsParamsTest {
.input("input")
.maxResults(1L)
.minResults(1L)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
val queryParams = params._queryParams()
@@ -36,7 +36,7 @@ internal class BrandRetrieveNaicsParamsTest {
.put("input", "input")
.put("maxResults", "1")
.put("minResults", "1")
- .put("timeoutMS", "1")
+ .put("timeoutMS", "1000")
.build()
)
}
diff --git a/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandRetrieveParamsTest.kt b/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandRetrieveParamsTest.kt
index 5f9b0b2..6da63ce 100644
--- a/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandRetrieveParamsTest.kt
+++ b/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandRetrieveParamsTest.kt
@@ -14,7 +14,7 @@ internal class BrandRetrieveParamsTest {
.domain("domain")
.forceLanguage(BrandRetrieveParams.ForceLanguage.ALBANIAN)
.maxSpeed(true)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
}
@@ -25,7 +25,7 @@ internal class BrandRetrieveParamsTest {
.domain("domain")
.forceLanguage(BrandRetrieveParams.ForceLanguage.ALBANIAN)
.maxSpeed(true)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
val queryParams = params._queryParams()
@@ -36,7 +36,7 @@ internal class BrandRetrieveParamsTest {
.put("domain", "domain")
.put("force_language", "albanian")
.put("maxSpeed", "true")
- .put("timeoutMS", "1")
+ .put("timeoutMS", "1000")
.build()
)
}
diff --git a/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandRetrieveSimplifiedParamsTest.kt b/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandRetrieveSimplifiedParamsTest.kt
index 07f3ffa..85d2603 100644
--- a/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandRetrieveSimplifiedParamsTest.kt
+++ b/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandRetrieveSimplifiedParamsTest.kt
@@ -10,17 +10,20 @@ internal class BrandRetrieveSimplifiedParamsTest {
@Test
fun create() {
- BrandRetrieveSimplifiedParams.builder().domain("domain").timeoutMs(1L).build()
+ BrandRetrieveSimplifiedParams.builder().domain("domain").timeoutMs(1000L).build()
}
@Test
fun queryParams() {
- val params = BrandRetrieveSimplifiedParams.builder().domain("domain").timeoutMs(1L).build()
+ val params =
+ BrandRetrieveSimplifiedParams.builder().domain("domain").timeoutMs(1000L).build()
val queryParams = params._queryParams()
assertThat(queryParams)
- .isEqualTo(QueryParams.builder().put("domain", "domain").put("timeoutMS", "1").build())
+ .isEqualTo(
+ QueryParams.builder().put("domain", "domain").put("timeoutMS", "1000").build()
+ )
}
@Test
diff --git a/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandStyleguideParamsTest.kt b/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandStyleguideParamsTest.kt
index 768b6e5..55ded8f 100644
--- a/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandStyleguideParamsTest.kt
+++ b/brand-dev-java-core/src/test/kotlin/com/branddev/api/models/brand/BrandStyleguideParamsTest.kt
@@ -13,7 +13,7 @@ internal class BrandStyleguideParamsTest {
BrandStyleguideParams.builder()
.domain("domain")
.prioritize(BrandStyleguideParams.Prioritize.SPEED)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
}
@@ -23,7 +23,7 @@ internal class BrandStyleguideParamsTest {
BrandStyleguideParams.builder()
.domain("domain")
.prioritize(BrandStyleguideParams.Prioritize.SPEED)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
val queryParams = params._queryParams()
@@ -33,7 +33,7 @@ internal class BrandStyleguideParamsTest {
QueryParams.builder()
.put("domain", "domain")
.put("prioritize", "speed")
- .put("timeoutMS", "1")
+ .put("timeoutMS", "1000")
.build()
)
}
diff --git a/brand-dev-java-core/src/test/kotlin/com/branddev/api/services/ErrorHandlingTest.kt b/brand-dev-java-core/src/test/kotlin/com/branddev/api/services/ErrorHandlingTest.kt
index 5b14671..1e62e5f 100644
--- a/brand-dev-java-core/src/test/kotlin/com/branddev/api/services/ErrorHandlingTest.kt
+++ b/brand-dev-java-core/src/test/kotlin/com/branddev/api/services/ErrorHandlingTest.kt
@@ -75,7 +75,7 @@ internal class ErrorHandlingTest {
.domain("domain")
.forceLanguage(BrandRetrieveParams.ForceLanguage.ALBANIAN)
.maxSpeed(true)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
)
}
@@ -102,7 +102,7 @@ internal class ErrorHandlingTest {
.domain("domain")
.forceLanguage(BrandRetrieveParams.ForceLanguage.ALBANIAN)
.maxSpeed(true)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
)
}
@@ -129,7 +129,7 @@ internal class ErrorHandlingTest {
.domain("domain")
.forceLanguage(BrandRetrieveParams.ForceLanguage.ALBANIAN)
.maxSpeed(true)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
)
}
@@ -156,7 +156,7 @@ internal class ErrorHandlingTest {
.domain("domain")
.forceLanguage(BrandRetrieveParams.ForceLanguage.ALBANIAN)
.maxSpeed(true)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
)
}
@@ -183,7 +183,7 @@ internal class ErrorHandlingTest {
.domain("domain")
.forceLanguage(BrandRetrieveParams.ForceLanguage.ALBANIAN)
.maxSpeed(true)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
)
}
@@ -210,7 +210,7 @@ internal class ErrorHandlingTest {
.domain("domain")
.forceLanguage(BrandRetrieveParams.ForceLanguage.ALBANIAN)
.maxSpeed(true)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
)
}
@@ -237,7 +237,7 @@ internal class ErrorHandlingTest {
.domain("domain")
.forceLanguage(BrandRetrieveParams.ForceLanguage.ALBANIAN)
.maxSpeed(true)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
)
}
@@ -264,7 +264,7 @@ internal class ErrorHandlingTest {
.domain("domain")
.forceLanguage(BrandRetrieveParams.ForceLanguage.ALBANIAN)
.maxSpeed(true)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
)
}
@@ -291,7 +291,7 @@ internal class ErrorHandlingTest {
.domain("domain")
.forceLanguage(BrandRetrieveParams.ForceLanguage.ALBANIAN)
.maxSpeed(true)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
)
}
@@ -318,7 +318,7 @@ internal class ErrorHandlingTest {
.domain("domain")
.forceLanguage(BrandRetrieveParams.ForceLanguage.ALBANIAN)
.maxSpeed(true)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
)
}
@@ -345,7 +345,7 @@ internal class ErrorHandlingTest {
.domain("domain")
.forceLanguage(BrandRetrieveParams.ForceLanguage.ALBANIAN)
.maxSpeed(true)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
)
}
@@ -372,7 +372,7 @@ internal class ErrorHandlingTest {
.domain("domain")
.forceLanguage(BrandRetrieveParams.ForceLanguage.ALBANIAN)
.maxSpeed(true)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
)
}
@@ -399,7 +399,7 @@ internal class ErrorHandlingTest {
.domain("domain")
.forceLanguage(BrandRetrieveParams.ForceLanguage.ALBANIAN)
.maxSpeed(true)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
)
}
@@ -426,7 +426,7 @@ internal class ErrorHandlingTest {
.domain("domain")
.forceLanguage(BrandRetrieveParams.ForceLanguage.ALBANIAN)
.maxSpeed(true)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
)
}
@@ -453,7 +453,7 @@ internal class ErrorHandlingTest {
.domain("domain")
.forceLanguage(BrandRetrieveParams.ForceLanguage.ALBANIAN)
.maxSpeed(true)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
)
}
@@ -480,7 +480,7 @@ internal class ErrorHandlingTest {
.domain("domain")
.forceLanguage(BrandRetrieveParams.ForceLanguage.ALBANIAN)
.maxSpeed(true)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
)
}
@@ -505,7 +505,7 @@ internal class ErrorHandlingTest {
.domain("domain")
.forceLanguage(BrandRetrieveParams.ForceLanguage.ALBANIAN)
.maxSpeed(true)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
)
}
diff --git a/brand-dev-java-core/src/test/kotlin/com/branddev/api/services/ServiceParamsTest.kt b/brand-dev-java-core/src/test/kotlin/com/branddev/api/services/ServiceParamsTest.kt
index 4788b35..853772d 100644
--- a/brand-dev-java-core/src/test/kotlin/com/branddev/api/services/ServiceParamsTest.kt
+++ b/brand-dev-java-core/src/test/kotlin/com/branddev/api/services/ServiceParamsTest.kt
@@ -45,7 +45,7 @@ internal class ServiceParamsTest {
.domain("domain")
.forceLanguage(BrandRetrieveParams.ForceLanguage.ALBANIAN)
.maxSpeed(true)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.putAdditionalHeader("Secret-Header", "42")
.putAdditionalQueryParam("secret_query_param", "42")
.build()
diff --git a/brand-dev-java-core/src/test/kotlin/com/branddev/api/services/async/BrandServiceAsyncTest.kt b/brand-dev-java-core/src/test/kotlin/com/branddev/api/services/async/BrandServiceAsyncTest.kt
index e600a78..faf3bc2 100644
--- a/brand-dev-java-core/src/test/kotlin/com/branddev/api/services/async/BrandServiceAsyncTest.kt
+++ b/brand-dev-java-core/src/test/kotlin/com/branddev/api/services/async/BrandServiceAsyncTest.kt
@@ -5,6 +5,7 @@ package com.branddev.api.services.async
import com.branddev.api.TestServerExtension
import com.branddev.api.client.okhttp.BrandDevOkHttpClientAsync
import com.branddev.api.core.JsonValue
+import com.branddev.api.models.brand.BrandAiProductParams
import com.branddev.api.models.brand.BrandAiProductsParams
import com.branddev.api.models.brand.BrandAiQueryParams
import com.branddev.api.models.brand.BrandFontsParams
@@ -43,7 +44,7 @@ internal class BrandServiceAsyncTest {
.domain("domain")
.forceLanguage(BrandRetrieveParams.ForceLanguage.ALBANIAN)
.maxSpeed(true)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
)
@@ -51,6 +52,25 @@ internal class BrandServiceAsyncTest {
brand.validate()
}
+ @Disabled("Prism tests are disabled")
+ @Test
+ fun aiProduct() {
+ val client =
+ BrandDevOkHttpClientAsync.builder()
+ .baseUrl(TestServerExtension.BASE_URL)
+ .apiKey("My API Key")
+ .build()
+ val brandServiceAsync = client.brand()
+
+ val responseFuture =
+ brandServiceAsync.aiProduct(
+ BrandAiProductParams.builder().url("https://example.com").timeoutMs(1000L).build()
+ )
+
+ val response = responseFuture.get()
+ response.validate()
+ }
+
@Disabled("Prism tests are disabled")
@Test
fun aiProducts() {
@@ -68,7 +88,7 @@ internal class BrandServiceAsyncTest {
BrandAiProductsParams.Body.ByDomain.builder()
.domain("domain")
.maxProducts(1L)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
)
.build()
@@ -128,7 +148,7 @@ internal class BrandServiceAsyncTest {
.termsAndConditions(true)
.build()
)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
)
@@ -148,7 +168,7 @@ internal class BrandServiceAsyncTest {
val responseFuture =
brandServiceAsync.fonts(
- BrandFontsParams.builder().domain("domain").timeoutMs(1L).build()
+ BrandFontsParams.builder().domain("domain").timeoutMs(1000L).build()
)
val response = responseFuture.get()
@@ -175,7 +195,7 @@ internal class BrandServiceAsyncTest {
.maxSpeed(true)
.mcc("mcc")
.phone(0.0)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
)
@@ -195,7 +215,7 @@ internal class BrandServiceAsyncTest {
val responseFuture =
brandServiceAsync.prefetch(
- BrandPrefetchParams.builder().domain("domain").timeoutMs(1L).build()
+ BrandPrefetchParams.builder().domain("domain").timeoutMs(1000L).build()
)
val response = responseFuture.get()
@@ -216,7 +236,7 @@ internal class BrandServiceAsyncTest {
brandServiceAsync.prefetchByEmail(
BrandPrefetchByEmailParams.builder()
.email("dev@stainless.com")
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
)
@@ -240,7 +260,7 @@ internal class BrandServiceAsyncTest {
.email("dev@stainless.com")
.forceLanguage(BrandRetrieveByEmailParams.ForceLanguage.ALBANIAN)
.maxSpeed(true)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
)
@@ -264,7 +284,7 @@ internal class BrandServiceAsyncTest {
.isin("SE60513A9993")
.forceLanguage(BrandRetrieveByIsinParams.ForceLanguage.ALBANIAN)
.maxSpeed(true)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
)
@@ -288,7 +308,7 @@ internal class BrandServiceAsyncTest {
.name("xxx")
.forceLanguage(BrandRetrieveByNameParams.ForceLanguage.ALBANIAN)
.maxSpeed(true)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
)
@@ -313,7 +333,7 @@ internal class BrandServiceAsyncTest {
.forceLanguage(BrandRetrieveByTickerParams.ForceLanguage.ALBANIAN)
.maxSpeed(true)
.tickerExchange(BrandRetrieveByTickerParams.TickerExchange.AMEX)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
)
@@ -337,7 +357,7 @@ internal class BrandServiceAsyncTest {
.input("input")
.maxResults(1L)
.minResults(1L)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
)
@@ -357,7 +377,7 @@ internal class BrandServiceAsyncTest {
val responseFuture =
brandServiceAsync.retrieveSimplified(
- BrandRetrieveSimplifiedParams.builder().domain("domain").timeoutMs(1L).build()
+ BrandRetrieveSimplifiedParams.builder().domain("domain").timeoutMs(1000L).build()
)
val response = responseFuture.get()
@@ -403,7 +423,7 @@ internal class BrandServiceAsyncTest {
BrandStyleguideParams.builder()
.domain("domain")
.prioritize(BrandStyleguideParams.Prioritize.SPEED)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
)
diff --git a/brand-dev-java-core/src/test/kotlin/com/branddev/api/services/blocking/BrandServiceTest.kt b/brand-dev-java-core/src/test/kotlin/com/branddev/api/services/blocking/BrandServiceTest.kt
index c042765..ad019f9 100644
--- a/brand-dev-java-core/src/test/kotlin/com/branddev/api/services/blocking/BrandServiceTest.kt
+++ b/brand-dev-java-core/src/test/kotlin/com/branddev/api/services/blocking/BrandServiceTest.kt
@@ -5,6 +5,7 @@ package com.branddev.api.services.blocking
import com.branddev.api.TestServerExtension
import com.branddev.api.client.okhttp.BrandDevOkHttpClient
import com.branddev.api.core.JsonValue
+import com.branddev.api.models.brand.BrandAiProductParams
import com.branddev.api.models.brand.BrandAiProductsParams
import com.branddev.api.models.brand.BrandAiQueryParams
import com.branddev.api.models.brand.BrandFontsParams
@@ -43,13 +44,31 @@ internal class BrandServiceTest {
.domain("domain")
.forceLanguage(BrandRetrieveParams.ForceLanguage.ALBANIAN)
.maxSpeed(true)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
)
brand.validate()
}
+ @Disabled("Prism tests are disabled")
+ @Test
+ fun aiProduct() {
+ val client =
+ BrandDevOkHttpClient.builder()
+ .baseUrl(TestServerExtension.BASE_URL)
+ .apiKey("My API Key")
+ .build()
+ val brandService = client.brand()
+
+ val response =
+ brandService.aiProduct(
+ BrandAiProductParams.builder().url("https://example.com").timeoutMs(1000L).build()
+ )
+
+ response.validate()
+ }
+
@Disabled("Prism tests are disabled")
@Test
fun aiProducts() {
@@ -67,7 +86,7 @@ internal class BrandServiceTest {
BrandAiProductsParams.Body.ByDomain.builder()
.domain("domain")
.maxProducts(1L)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
)
.build()
@@ -126,7 +145,7 @@ internal class BrandServiceTest {
.termsAndConditions(true)
.build()
)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
)
@@ -144,7 +163,7 @@ internal class BrandServiceTest {
val brandService = client.brand()
val response =
- brandService.fonts(BrandFontsParams.builder().domain("domain").timeoutMs(1L).build())
+ brandService.fonts(BrandFontsParams.builder().domain("domain").timeoutMs(1000L).build())
response.validate()
}
@@ -169,7 +188,7 @@ internal class BrandServiceTest {
.maxSpeed(true)
.mcc("mcc")
.phone(0.0)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
)
@@ -188,7 +207,7 @@ internal class BrandServiceTest {
val response =
brandService.prefetch(
- BrandPrefetchParams.builder().domain("domain").timeoutMs(1L).build()
+ BrandPrefetchParams.builder().domain("domain").timeoutMs(1000L).build()
)
response.validate()
@@ -208,7 +227,7 @@ internal class BrandServiceTest {
brandService.prefetchByEmail(
BrandPrefetchByEmailParams.builder()
.email("dev@stainless.com")
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
)
@@ -231,7 +250,7 @@ internal class BrandServiceTest {
.email("dev@stainless.com")
.forceLanguage(BrandRetrieveByEmailParams.ForceLanguage.ALBANIAN)
.maxSpeed(true)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
)
@@ -254,7 +273,7 @@ internal class BrandServiceTest {
.isin("SE60513A9993")
.forceLanguage(BrandRetrieveByIsinParams.ForceLanguage.ALBANIAN)
.maxSpeed(true)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
)
@@ -277,7 +296,7 @@ internal class BrandServiceTest {
.name("xxx")
.forceLanguage(BrandRetrieveByNameParams.ForceLanguage.ALBANIAN)
.maxSpeed(true)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
)
@@ -301,7 +320,7 @@ internal class BrandServiceTest {
.forceLanguage(BrandRetrieveByTickerParams.ForceLanguage.ALBANIAN)
.maxSpeed(true)
.tickerExchange(BrandRetrieveByTickerParams.TickerExchange.AMEX)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
)
@@ -324,7 +343,7 @@ internal class BrandServiceTest {
.input("input")
.maxResults(1L)
.minResults(1L)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
)
@@ -343,7 +362,7 @@ internal class BrandServiceTest {
val response =
brandService.retrieveSimplified(
- BrandRetrieveSimplifiedParams.builder().domain("domain").timeoutMs(1L).build()
+ BrandRetrieveSimplifiedParams.builder().domain("domain").timeoutMs(1000L).build()
)
response.validate()
@@ -387,7 +406,7 @@ internal class BrandServiceTest {
BrandStyleguideParams.builder()
.domain("domain")
.prioritize(BrandStyleguideParams.Prioritize.SPEED)
- .timeoutMs(1L)
+ .timeoutMs(1000L)
.build()
)
diff --git a/build.gradle.kts b/build.gradle.kts
index 0f41d01..ce30364 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -9,7 +9,7 @@ repositories {
allprojects {
group = "com.branddev.api"
- version = "0.1.0-alpha.29" // x-release-please-version
+ version = "0.1.0-alpha.30" // x-release-please-version
}
subprojects {