All Downloads are FREE. Search and download functionalities are using the official Maven repository.

algoliasearch.api.SearchClient.scala Maven / Gradle / Ivy

There is a newer version: 2.9.2
Show newest version
/** Code generated by OpenAPI Generator (https://openapi-generator.tech), manual changes will be lost - read more on
  * https://github.com/algolia/api-clients-automation. DO NOT EDIT.
  */
package algoliasearch.api

import algoliasearch.search.Action._
import algoliasearch.search.AddApiKeyResponse
import algoliasearch.search.ApiKey
import algoliasearch.search.ApiKeyOperation._
import algoliasearch.search.AssignUserIdParams
import algoliasearch.search.BatchAssignUserIdsParams
import algoliasearch.search.BatchDictionaryEntriesParams
import algoliasearch.search.BatchParams
import algoliasearch.search.BatchResponse
import algoliasearch.search.BatchWriteParams
import algoliasearch.search.BrowseParams
import algoliasearch.search.BrowseParamsObject
import algoliasearch.search.BrowseResponse
import algoliasearch.search.CreatedAtResponse
import algoliasearch.search.DeleteApiKeyResponse
import algoliasearch.search.DeleteByParams
import algoliasearch.search.DeleteSourceResponse
import algoliasearch.search.DeletedAtResponse
import algoliasearch.search.DictionarySettingsParams
import algoliasearch.search.DictionaryType._
import algoliasearch.search.ErrorBase
import algoliasearch.search.GetApiKeyResponse
import algoliasearch.search.GetDictionarySettingsResponse
import algoliasearch.search.GetLogsResponse
import algoliasearch.search.GetObjectsParams
import algoliasearch.search.GetObjectsResponse
import algoliasearch.search.GetTaskResponse
import algoliasearch.search.GetTopUserIdsResponse
import algoliasearch.search.HasPendingMappingsResponse
import algoliasearch.search.IndexSettings
import algoliasearch.search.Languages
import algoliasearch.search.ListApiKeysResponse
import algoliasearch.search.ListClustersResponse
import algoliasearch.search.ListIndicesResponse
import algoliasearch.search.ListUserIdsResponse
import algoliasearch.search.LogType._
import algoliasearch.search.MultipleBatchResponse
import algoliasearch.search.OperationIndexParams
import algoliasearch.search.RemoveUserIdResponse
import algoliasearch.search.ReplaceAllObjectsResponse
import algoliasearch.search.ReplaceSourceResponse
import algoliasearch.search.Rule
import algoliasearch.search.SaveObjectResponse
import algoliasearch.search.SaveSynonymResponse
import algoliasearch.search.SearchDictionaryEntriesParams
import algoliasearch.search.SearchDictionaryEntriesResponse
import algoliasearch.search.SearchForFacetValuesRequest
import algoliasearch.search.SearchForFacetValuesResponse
import algoliasearch.search.SearchMethodParams
import algoliasearch.search.SearchParams
import algoliasearch.search.SearchResponse
import algoliasearch.search.SearchResponses
import algoliasearch.search.SearchRulesParams
import algoliasearch.search.SearchRulesResponse
import algoliasearch.search.SearchSynonymsParams
import algoliasearch.search.SearchSynonymsResponse
import algoliasearch.search.SearchUserIdsParams
import algoliasearch.search.SearchUserIdsResponse
import algoliasearch.search.SecuredApiKeyRestrictions
import algoliasearch.search.SettingsResponse
import algoliasearch.search.Source
import algoliasearch.search.SynonymHit
import algoliasearch.search.UpdateApiKeyResponse
import algoliasearch.search.UpdatedAtResponse
import algoliasearch.search.UpdatedAtWithObjectIdResponse
import algoliasearch.search.UpdatedRuleResponse
import algoliasearch.search.UserId
import algoliasearch.search._
import algoliasearch.ApiClient
import algoliasearch.api.SearchClient.hosts
import algoliasearch.config._
import algoliasearch.internal.util._

import scala.concurrent.{ExecutionContext, Future}
import scala.util.Random

object SearchClient {

  /** Creates a new SearchApi instance using default hosts.
    *
    * @param appId
    *   application ID
    * @param apiKey
    *   api key
    *
    * @param clientOptions
    *   client options
    */
  def apply(
      appId: String,
      apiKey: String,
      clientOptions: ClientOptions = ClientOptions()
  ) = new SearchClient(
    appId = appId,
    apiKey = apiKey,
    clientOptions = clientOptions
  )

  private def hosts(appId: String): Seq[Host] = {
    val commonHosts = Random.shuffle(
      List(
        Host(appId + "-1.algolianet.com", Set(CallType.Read, CallType.Write)),
        Host(appId + "-2.algolianet.com", Set(CallType.Read, CallType.Write)),
        Host(appId + "-3.algolianet.com", Set(CallType.Read, CallType.Write))
      )
    )
    List(
      Host(appId + "-dsn.algolia.net", Set(CallType.Read)),
      Host(appId + ".algolia.net", Set(CallType.Write))
    ) ++ commonHosts
  }
}

class SearchClient(
    appId: String,
    apiKey: String,
    clientOptions: ClientOptions = ClientOptions()
) extends ApiClient(
      appId = appId,
      apiKey = apiKey,
      clientName = "Search",
      defaultHosts = hosts(appId),
      formats = JsonSupport.format,
      options = clientOptions
    ) {

  /** Creates a new API key with specific permissions and restrictions.
    *
    * Required API Key ACLs:
    *   - admin
    */
  def addApiKey(apiKey: ApiKey, requestOptions: Option[RequestOptions] = None)(implicit
      ec: ExecutionContext
  ): Future[AddApiKeyResponse] = Future {
    requireNotNull(apiKey, "Parameter `apiKey` is required when calling `addApiKey`.")

    val request = HttpRequest
      .builder()
      .withMethod("POST")
      .withPath(s"/1/keys")
      .withBody(apiKey)
      .build()
    execute[AddApiKeyResponse](request, requestOptions)
  }

  /** If a record with the specified object ID exists, the existing record is replaced. Otherwise, a new record is added
    * to the index. To update _some_ attributes of an existing record, use the [`partial`
    * operation](#tag/Records/operation/partialUpdateObject) instead. To add, update, or replace multiple records, use
    * the [`batch` operation](#tag/Records/operation/batch).
    *
    * Required API Key ACLs:
    *   - addObject
    *
    * @param indexName
    *   Name of the index on which to perform the operation.
    * @param objectID
    *   Unique record identifier.
    * @param body
    *   The record, a schemaless object with attributes that are useful in the context of search and discovery.
    */
  def addOrUpdateObject(indexName: String, objectID: String, body: Any, requestOptions: Option[RequestOptions] = None)(
      implicit ec: ExecutionContext
  ): Future[UpdatedAtWithObjectIdResponse] = Future {
    requireNotNull(indexName, "Parameter `indexName` is required when calling `addOrUpdateObject`.")
    requireNotNull(objectID, "Parameter `objectID` is required when calling `addOrUpdateObject`.")
    requireNotNull(body, "Parameter `body` is required when calling `addOrUpdateObject`.")

    val request = HttpRequest
      .builder()
      .withMethod("PUT")
      .withPath(s"/1/indexes/${escape(indexName)}/${escape(objectID)}")
      .withBody(body)
      .build()
    execute[UpdatedAtWithObjectIdResponse](request, requestOptions)
  }

  /** Adds a source to the list of allowed sources.
    *
    * Required API Key ACLs:
    *   - admin
    *
    * @param source
    *   Source to add.
    */
  def appendSource(source: Source, requestOptions: Option[RequestOptions] = None)(implicit
      ec: ExecutionContext
  ): Future[CreatedAtResponse] = Future {
    requireNotNull(source, "Parameter `source` is required when calling `appendSource`.")

    val request = HttpRequest
      .builder()
      .withMethod("POST")
      .withPath(s"/1/security/sources/append")
      .withBody(source)
      .build()
    execute[CreatedAtResponse](request, requestOptions)
  }

  /** Assigns or moves a user ID to a cluster. The time it takes to move a user is proportional to the amount of data
    * linked to the user ID.
    *
    * Required API Key ACLs:
    *   - admin
    *
    * @param xAlgoliaUserID
    *   Unique identifier of the user who makes the search request.
    */
  def assignUserId(
      xAlgoliaUserID: String,
      assignUserIdParams: AssignUserIdParams,
      requestOptions: Option[RequestOptions] = None
  )(implicit ec: ExecutionContext): Future[CreatedAtResponse] = Future {
    requireNotNull(xAlgoliaUserID, "Parameter `xAlgoliaUserID` is required when calling `assignUserId`.")
    requireNotNull(assignUserIdParams, "Parameter `assignUserIdParams` is required when calling `assignUserId`.")

    val request = HttpRequest
      .builder()
      .withMethod("POST")
      .withPath(s"/1/clusters/mapping")
      .withBody(assignUserIdParams)
      .withHeader("X-Algolia-User-ID", xAlgoliaUserID)
      .build()
    execute[CreatedAtResponse](request, requestOptions)
  }

  /** Adds, updates, or deletes records in one index with a single API request. Batching index updates reduces latency
    * and increases data integrity. - Actions are applied in the order they're specified. - Actions are equivalent to
    * the individual API requests of the same name.
    *
    * @param indexName
    *   Name of the index on which to perform the operation.
    */
  def batch(indexName: String, batchWriteParams: BatchWriteParams, requestOptions: Option[RequestOptions] = None)(
      implicit ec: ExecutionContext
  ): Future[BatchResponse] = Future {
    requireNotNull(indexName, "Parameter `indexName` is required when calling `batch`.")
    requireNotNull(batchWriteParams, "Parameter `batchWriteParams` is required when calling `batch`.")

    val request = HttpRequest
      .builder()
      .withMethod("POST")
      .withPath(s"/1/indexes/${escape(indexName)}/batch")
      .withBody(batchWriteParams)
      .build()
    execute[BatchResponse](request, requestOptions)
  }

  /** Assigns multiple user IDs to a cluster. **You can't move users with this operation**.
    *
    * Required API Key ACLs:
    *   - admin
    *
    * @param xAlgoliaUserID
    *   Unique identifier of the user who makes the search request.
    */
  def batchAssignUserIds(
      xAlgoliaUserID: String,
      batchAssignUserIdsParams: BatchAssignUserIdsParams,
      requestOptions: Option[RequestOptions] = None
  )(implicit ec: ExecutionContext): Future[CreatedAtResponse] = Future {
    requireNotNull(xAlgoliaUserID, "Parameter `xAlgoliaUserID` is required when calling `batchAssignUserIds`.")
    requireNotNull(
      batchAssignUserIdsParams,
      "Parameter `batchAssignUserIdsParams` is required when calling `batchAssignUserIds`."
    )

    val request = HttpRequest
      .builder()
      .withMethod("POST")
      .withPath(s"/1/clusters/mapping/batch")
      .withBody(batchAssignUserIdsParams)
      .withHeader("X-Algolia-User-ID", xAlgoliaUserID)
      .build()
    execute[CreatedAtResponse](request, requestOptions)
  }

  /** Adds or deletes multiple entries from your plurals, segmentation, or stop word dictionaries.
    *
    * Required API Key ACLs:
    *   - editSettings
    *
    * @param dictionaryName
    *   Dictionary type in which to search.
    */
  def batchDictionaryEntries(
      dictionaryName: DictionaryType,
      batchDictionaryEntriesParams: BatchDictionaryEntriesParams,
      requestOptions: Option[RequestOptions] = None
  )(implicit ec: ExecutionContext): Future[UpdatedAtResponse] = Future {
    requireNotNull(dictionaryName, "Parameter `dictionaryName` is required when calling `batchDictionaryEntries`.")
    requireNotNull(
      batchDictionaryEntriesParams,
      "Parameter `batchDictionaryEntriesParams` is required when calling `batchDictionaryEntries`."
    )

    val request = HttpRequest
      .builder()
      .withMethod("POST")
      .withPath(s"/1/dictionaries/${escape(dictionaryName)}/batch")
      .withBody(batchDictionaryEntriesParams)
      .build()
    execute[UpdatedAtResponse](request, requestOptions)
  }

  /** Retrieves records from an index, up to 1,000 per request. While searching retrieves _hits_ (records augmented with
    * attributes for highlighting and ranking details), browsing _just_ returns matching records. This can be useful if
    * you want to export your indices. - The Analytics API doesn't collect data when using `browse`. - Records are
    * ranked by attributes and custom ranking. - There's no ranking for: typo-tolerance, number of matched words,
    * proximity, geo distance. Browse requests automatically apply these settings: - `advancedSyntax`: `false` -
    * `attributesToHighlight`: `[]` - `attributesToSnippet`: `[]` - `distinct`: `false` - `enablePersonalization`:
    * `false` - `enableRules`: `false` - `facets`: `[]` - `getRankingInfo`: `false` - `ignorePlurals`: `false` -
    * `optionalFilters`: `[]` - `typoTolerance`: `true` or `false` (`min` and `strict` is evaluated to `true`) If you
    * send these parameters with your browse requests, they'll be ignored.
    *
    * Required API Key ACLs:
    *   - browse
    *
    * @param indexName
    *   Name of the index on which to perform the operation.
    */
  def browse(
      indexName: String,
      browseParams: Option[BrowseParams] = None,
      requestOptions: Option[RequestOptions] = None
  )(implicit ec: ExecutionContext): Future[BrowseResponse] = Future {
    requireNotNull(indexName, "Parameter `indexName` is required when calling `browse`.")

    val request = HttpRequest
      .builder()
      .withMethod("POST")
      .withPath(s"/1/indexes/${escape(indexName)}/browse")
      .withBody(browseParams)
      .build()
    execute[BrowseResponse](request, requestOptions)
  }

  /** Deletes only the records from an index while keeping settings, synonyms, and rules.
    *
    * Required API Key ACLs:
    *   - deleteIndex
    *
    * @param indexName
    *   Name of the index on which to perform the operation.
    */
  def clearObjects(indexName: String, requestOptions: Option[RequestOptions] = None)(implicit
      ec: ExecutionContext
  ): Future[UpdatedAtResponse] = Future {
    requireNotNull(indexName, "Parameter `indexName` is required when calling `clearObjects`.")

    val request = HttpRequest
      .builder()
      .withMethod("POST")
      .withPath(s"/1/indexes/${escape(indexName)}/clear")
      .build()
    execute[UpdatedAtResponse](request, requestOptions)
  }

  /** Deletes all rules from the index.
    *
    * Required API Key ACLs:
    *   - editSettings
    *
    * @param indexName
    *   Name of the index on which to perform the operation.
    * @param forwardToReplicas
    *   Whether changes are applied to replica indices.
    */
  def clearRules(
      indexName: String,
      forwardToReplicas: Option[Boolean] = None,
      requestOptions: Option[RequestOptions] = None
  )(implicit ec: ExecutionContext): Future[UpdatedAtResponse] = Future {
    requireNotNull(indexName, "Parameter `indexName` is required when calling `clearRules`.")

    val request = HttpRequest
      .builder()
      .withMethod("POST")
      .withPath(s"/1/indexes/${escape(indexName)}/rules/clear")
      .withQueryParameter("forwardToReplicas", forwardToReplicas)
      .build()
    execute[UpdatedAtResponse](request, requestOptions)
  }

  /** Deletes all synonyms from the index.
    *
    * Required API Key ACLs:
    *   - editSettings
    *
    * @param indexName
    *   Name of the index on which to perform the operation.
    * @param forwardToReplicas
    *   Whether changes are applied to replica indices.
    */
  def clearSynonyms(
      indexName: String,
      forwardToReplicas: Option[Boolean] = None,
      requestOptions: Option[RequestOptions] = None
  )(implicit ec: ExecutionContext): Future[UpdatedAtResponse] = Future {
    requireNotNull(indexName, "Parameter `indexName` is required when calling `clearSynonyms`.")

    val request = HttpRequest
      .builder()
      .withMethod("POST")
      .withPath(s"/1/indexes/${escape(indexName)}/synonyms/clear")
      .withQueryParameter("forwardToReplicas", forwardToReplicas)
      .build()
    execute[UpdatedAtResponse](request, requestOptions)
  }

  /** This method allow you to send requests to the Algolia REST API.
    *
    * @param path
    *   Path of the endpoint, anything after \"/1\" must be specified.
    * @param parameters
    *   Query parameters to apply to the current query.
    */
  def customDelete[T: Manifest](
      path: String,
      parameters: Option[Map[String, Any]] = None,
      requestOptions: Option[RequestOptions] = None
  )(implicit ec: ExecutionContext): Future[T] = Future {
    requireNotNull(path, "Parameter `path` is required when calling `customDelete`.")

    val request = HttpRequest
      .builder()
      .withMethod("DELETE")
      .withPath(s"/${path}")
      .withQueryParameters(parameters)
      .build()
    execute[T](request, requestOptions)
  }

  /** This method allow you to send requests to the Algolia REST API.
    *
    * @param path
    *   Path of the endpoint, anything after \"/1\" must be specified.
    * @param parameters
    *   Query parameters to apply to the current query.
    */
  def customGet[T: Manifest](
      path: String,
      parameters: Option[Map[String, Any]] = None,
      requestOptions: Option[RequestOptions] = None
  )(implicit ec: ExecutionContext): Future[T] = Future {
    requireNotNull(path, "Parameter `path` is required when calling `customGet`.")

    val request = HttpRequest
      .builder()
      .withMethod("GET")
      .withPath(s"/${path}")
      .withQueryParameters(parameters)
      .build()
    execute[T](request, requestOptions)
  }

  /** This method allow you to send requests to the Algolia REST API.
    *
    * @param path
    *   Path of the endpoint, anything after \"/1\" must be specified.
    * @param parameters
    *   Query parameters to apply to the current query.
    * @param body
    *   Parameters to send with the custom request.
    */
  def customPost[T: Manifest](
      path: String,
      parameters: Option[Map[String, Any]] = None,
      body: Option[Any] = None,
      requestOptions: Option[RequestOptions] = None
  )(implicit ec: ExecutionContext): Future[T] = Future {
    requireNotNull(path, "Parameter `path` is required when calling `customPost`.")

    val request = HttpRequest
      .builder()
      .withMethod("POST")
      .withPath(s"/${path}")
      .withBody(body)
      .withQueryParameters(parameters)
      .build()
    execute[T](request, requestOptions)
  }

  /** This method allow you to send requests to the Algolia REST API.
    *
    * @param path
    *   Path of the endpoint, anything after \"/1\" must be specified.
    * @param parameters
    *   Query parameters to apply to the current query.
    * @param body
    *   Parameters to send with the custom request.
    */
  def customPut[T: Manifest](
      path: String,
      parameters: Option[Map[String, Any]] = None,
      body: Option[Any] = None,
      requestOptions: Option[RequestOptions] = None
  )(implicit ec: ExecutionContext): Future[T] = Future {
    requireNotNull(path, "Parameter `path` is required when calling `customPut`.")

    val request = HttpRequest
      .builder()
      .withMethod("PUT")
      .withPath(s"/${path}")
      .withBody(body)
      .withQueryParameters(parameters)
      .build()
    execute[T](request, requestOptions)
  }

  /** Deletes the API key.
    *
    * Required API Key ACLs:
    *   - admin
    *
    * @param key
    *   API key.
    */
  def deleteApiKey(key: String, requestOptions: Option[RequestOptions] = None)(implicit
      ec: ExecutionContext
  ): Future[DeleteApiKeyResponse] = Future {
    requireNotNull(key, "Parameter `key` is required when calling `deleteApiKey`.")

    val request = HttpRequest
      .builder()
      .withMethod("DELETE")
      .withPath(s"/1/keys/${escape(key)}")
      .build()
    execute[DeleteApiKeyResponse](request, requestOptions)
  }

  /** This operation doesn't accept empty queries or filters. It's more efficient to get a list of object IDs with the
    * [`browse` operation](#tag/Search/operation/browse), and then delete the records using the [`batch`
    * operation](#tag/Records/operation/batch).
    *
    * Required API Key ACLs:
    *   - deleteIndex
    *
    * @param indexName
    *   Name of the index on which to perform the operation.
    */
  def deleteBy(indexName: String, deleteByParams: DeleteByParams, requestOptions: Option[RequestOptions] = None)(
      implicit ec: ExecutionContext
  ): Future[DeletedAtResponse] = Future {
    requireNotNull(indexName, "Parameter `indexName` is required when calling `deleteBy`.")
    requireNotNull(deleteByParams, "Parameter `deleteByParams` is required when calling `deleteBy`.")

    val request = HttpRequest
      .builder()
      .withMethod("POST")
      .withPath(s"/1/indexes/${escape(indexName)}/deleteByQuery")
      .withBody(deleteByParams)
      .build()
    execute[DeletedAtResponse](request, requestOptions)
  }

  /** Deletes an index and all its settings. - Deleting an index doesn't delete its analytics data. - If you try to
    * delete a non-existing index, the operation is ignored without warning. - If the index you want to delete has
    * replica indices, the replicas become independent indices. - If the index you want to delete is a replica index,
    * you must first unlink it from its primary index before you can delete it. For more information, see [Delete
    * replica
    * indices](https://www.algolia.com/doc/guides/managing-results/refine-results/sorting/how-to/deleting-replicas/).
    *
    * Required API Key ACLs:
    *   - deleteIndex
    *
    * @param indexName
    *   Name of the index on which to perform the operation.
    */
  def deleteIndex(indexName: String, requestOptions: Option[RequestOptions] = None)(implicit
      ec: ExecutionContext
  ): Future[DeletedAtResponse] = Future {
    requireNotNull(indexName, "Parameter `indexName` is required when calling `deleteIndex`.")

    val request = HttpRequest
      .builder()
      .withMethod("DELETE")
      .withPath(s"/1/indexes/${escape(indexName)}")
      .build()
    execute[DeletedAtResponse](request, requestOptions)
  }

  /** Deletes a record by its object ID. To delete more than one record, use the [`batch`
    * operation](#tag/Records/operation/batch). To delete records matching a query, use the [`deleteByQuery`
    * operation](#tag/Records/operation/deleteBy).
    *
    * Required API Key ACLs:
    *   - deleteObject
    *
    * @param indexName
    *   Name of the index on which to perform the operation.
    * @param objectID
    *   Unique record identifier.
    */
  def deleteObject(indexName: String, objectID: String, requestOptions: Option[RequestOptions] = None)(implicit
      ec: ExecutionContext
  ): Future[DeletedAtResponse] = Future {
    requireNotNull(indexName, "Parameter `indexName` is required when calling `deleteObject`.")
    requireNotNull(objectID, "Parameter `objectID` is required when calling `deleteObject`.")

    val request = HttpRequest
      .builder()
      .withMethod("DELETE")
      .withPath(s"/1/indexes/${escape(indexName)}/${escape(objectID)}")
      .build()
    execute[DeletedAtResponse](request, requestOptions)
  }

  /** Deletes a rule by its ID. To find the object ID for rules, use the [`search`
    * operation](#tag/Rules/operation/searchRules).
    *
    * Required API Key ACLs:
    *   - editSettings
    *
    * @param indexName
    *   Name of the index on which to perform the operation.
    * @param objectID
    *   Unique identifier of a rule object.
    * @param forwardToReplicas
    *   Whether changes are applied to replica indices.
    */
  def deleteRule(
      indexName: String,
      objectID: String,
      forwardToReplicas: Option[Boolean] = None,
      requestOptions: Option[RequestOptions] = None
  )(implicit ec: ExecutionContext): Future[UpdatedAtResponse] = Future {
    requireNotNull(indexName, "Parameter `indexName` is required when calling `deleteRule`.")
    requireNotNull(objectID, "Parameter `objectID` is required when calling `deleteRule`.")

    val request = HttpRequest
      .builder()
      .withMethod("DELETE")
      .withPath(s"/1/indexes/${escape(indexName)}/rules/${escape(objectID)}")
      .withQueryParameter("forwardToReplicas", forwardToReplicas)
      .build()
    execute[UpdatedAtResponse](request, requestOptions)
  }

  /** Deletes a source from the list of allowed sources.
    *
    * Required API Key ACLs:
    *   - admin
    *
    * @param source
    *   IP address range of the source.
    */
  def deleteSource(source: String, requestOptions: Option[RequestOptions] = None)(implicit
      ec: ExecutionContext
  ): Future[DeleteSourceResponse] = Future {
    requireNotNull(source, "Parameter `source` is required when calling `deleteSource`.")

    val request = HttpRequest
      .builder()
      .withMethod("DELETE")
      .withPath(s"/1/security/sources/${escape(source)}")
      .build()
    execute[DeleteSourceResponse](request, requestOptions)
  }

  /** Deletes a synonym by its ID. To find the object IDs of your synonyms, use the [`search`
    * operation](#tag/Synonyms/operation/searchSynonyms).
    *
    * Required API Key ACLs:
    *   - editSettings
    *
    * @param indexName
    *   Name of the index on which to perform the operation.
    * @param objectID
    *   Unique identifier of a synonym object.
    * @param forwardToReplicas
    *   Whether changes are applied to replica indices.
    */
  def deleteSynonym(
      indexName: String,
      objectID: String,
      forwardToReplicas: Option[Boolean] = None,
      requestOptions: Option[RequestOptions] = None
  )(implicit ec: ExecutionContext): Future[DeletedAtResponse] = Future {
    requireNotNull(indexName, "Parameter `indexName` is required when calling `deleteSynonym`.")
    requireNotNull(objectID, "Parameter `objectID` is required when calling `deleteSynonym`.")

    val request = HttpRequest
      .builder()
      .withMethod("DELETE")
      .withPath(s"/1/indexes/${escape(indexName)}/synonyms/${escape(objectID)}")
      .withQueryParameter("forwardToReplicas", forwardToReplicas)
      .build()
    execute[DeletedAtResponse](request, requestOptions)
  }

  /** Gets the permissions and restrictions of an API key. When authenticating with the admin API key, you can request
    * information for any of your application's keys. When authenticating with other API keys, you can only retrieve
    * information for that key.
    *
    * @param key
    *   API key.
    */
  def getApiKey(key: String, requestOptions: Option[RequestOptions] = None)(implicit
      ec: ExecutionContext
  ): Future[GetApiKeyResponse] = Future {
    requireNotNull(key, "Parameter `key` is required when calling `getApiKey`.")

    val request = HttpRequest
      .builder()
      .withMethod("GET")
      .withPath(s"/1/keys/${escape(key)}")
      .build()
    execute[GetApiKeyResponse](request, requestOptions)
  }

  /** Checks the status of a given application task.
    *
    * Required API Key ACLs:
    *   - editSettings
    *
    * @param taskID
    *   Unique task identifier.
    */
  def getAppTask(taskID: Long, requestOptions: Option[RequestOptions] = None)(implicit
      ec: ExecutionContext
  ): Future[GetTaskResponse] = Future {
    requireNotNull(taskID, "Parameter `taskID` is required when calling `getAppTask`.")

    val request = HttpRequest
      .builder()
      .withMethod("GET")
      .withPath(s"/1/task/${escape(taskID)}")
      .build()
    execute[GetTaskResponse](request, requestOptions)
  }

  /** Lists supported languages with their supported dictionary types and number of custom entries.
    *
    * Required API Key ACLs:
    *   - settings
    */
  def getDictionaryLanguages(
      requestOptions: Option[RequestOptions] = None
  )(implicit ec: ExecutionContext): Future[Map[String, Languages]] = Future {

    val request = HttpRequest
      .builder()
      .withMethod("GET")
      .withPath(s"/1/dictionaries/*/languages")
      .build()
    execute[Map[String, Languages]](request, requestOptions)
  }

  /** Retrieves the languages for which standard dictionary entries are turned off.
    *
    * Required API Key ACLs:
    *   - settings
    */
  def getDictionarySettings(
      requestOptions: Option[RequestOptions] = None
  )(implicit ec: ExecutionContext): Future[GetDictionarySettingsResponse] = Future {

    val request = HttpRequest
      .builder()
      .withMethod("GET")
      .withPath(s"/1/dictionaries/*/settings")
      .build()
    execute[GetDictionarySettingsResponse](request, requestOptions)
  }

  /** The request must be authenticated by an API key with the [`logs`
    * ACL](https://www.algolia.com/doc/guides/security/api-keys/#access-control-list-acl). - Logs are held for the last
    * seven days. - Up to 1,000 API requests per server are logged. - This request counts towards your [operations
    * quota](https://support.algolia.com/hc/en-us/articles/4406981829777-How-does-Algolia-count-records-and-operations-)
    * but doesn't appear in the logs itself.
    *
    * Required API Key ACLs:
    *   - logs
    *
    * @param offset
    *   First log entry to retrieve. The most recent entries are listed first.
    * @param length
    *   Maximum number of entries to retrieve.
    * @param indexName
    *   Index for which to retrieve log entries. By default, log entries are retrieved for all indices.
    * @param `type`
    *   Type of log entries to retrieve. By default, all log entries are retrieved.
    */
  def getLogs(
      offset: Option[Int] = None,
      length: Option[Int] = None,
      indexName: Option[String] = None,
      `type`: Option[LogType] = None,
      requestOptions: Option[RequestOptions] = None
  )(implicit ec: ExecutionContext): Future[GetLogsResponse] = Future {

    val request = HttpRequest
      .builder()
      .withMethod("GET")
      .withPath(s"/1/logs")
      .withQueryParameter("offset", offset)
      .withQueryParameter("length", length)
      .withQueryParameter("indexName", indexName)
      .withQueryParameter("type", `type`)
      .build()
    execute[GetLogsResponse](request, requestOptions)
  }

  /** Retrieves one record by its object ID. To retrieve more than one record, use the [`objects`
    * operation](#tag/Records/operation/getObjects).
    *
    * Required API Key ACLs:
    *   - search
    *
    * @param indexName
    *   Name of the index on which to perform the operation.
    * @param objectID
    *   Unique record identifier.
    * @param attributesToRetrieve
    *   Attributes to include with the records in the response. This is useful to reduce the size of the API response.
    *   By default, all retrievable attributes are returned. `objectID` is always retrieved. Attributes included in
    *   `unretrievableAttributes` won't be retrieved unless the request is authenticated with the admin API key.
    */
  def getObject(
      indexName: String,
      objectID: String,
      attributesToRetrieve: Option[Seq[String]] = None,
      requestOptions: Option[RequestOptions] = None
  )(implicit ec: ExecutionContext): Future[Any] = Future {
    requireNotNull(indexName, "Parameter `indexName` is required when calling `getObject`.")
    requireNotNull(objectID, "Parameter `objectID` is required when calling `getObject`.")

    val request = HttpRequest
      .builder()
      .withMethod("GET")
      .withPath(s"/1/indexes/${escape(indexName)}/${escape(objectID)}")
      .withQueryParameter("attributesToRetrieve", attributesToRetrieve)
      .build()
    execute[Any](request, requestOptions)
  }

  /** Retrieves one or more records, potentially from different indices. Records are returned in the same order as the
    * requests.
    *
    * Required API Key ACLs:
    *   - search
    *
    * @param getObjectsParams
    *   Request object.
    */
  def getObjects(getObjectsParams: GetObjectsParams, requestOptions: Option[RequestOptions] = None)(implicit
      ec: ExecutionContext
  ): Future[GetObjectsResponse] = Future {
    requireNotNull(getObjectsParams, "Parameter `getObjectsParams` is required when calling `getObjects`.")

    val request = HttpRequest
      .builder()
      .withMethod("POST")
      .withPath(s"/1/indexes/*/objects")
      .withBody(getObjectsParams)
      .withRead(true)
      .build()
    execute[GetObjectsResponse](request, requestOptions)
  }

  /** Retrieves a rule by its ID. To find the object ID of rules, use the [`search`
    * operation](#tag/Rules/operation/searchRules).
    *
    * Required API Key ACLs:
    *   - settings
    *
    * @param indexName
    *   Name of the index on which to perform the operation.
    * @param objectID
    *   Unique identifier of a rule object.
    */
  def getRule(indexName: String, objectID: String, requestOptions: Option[RequestOptions] = None)(implicit
      ec: ExecutionContext
  ): Future[Rule] = Future {
    requireNotNull(indexName, "Parameter `indexName` is required when calling `getRule`.")
    requireNotNull(objectID, "Parameter `objectID` is required when calling `getRule`.")

    val request = HttpRequest
      .builder()
      .withMethod("GET")
      .withPath(s"/1/indexes/${escape(indexName)}/rules/${escape(objectID)}")
      .build()
    execute[Rule](request, requestOptions)
  }

  /** Retrieves an object with non-null index settings.
    *
    * Required API Key ACLs:
    *   - search
    *
    * @param indexName
    *   Name of the index on which to perform the operation.
    */
  def getSettings(indexName: String, requestOptions: Option[RequestOptions] = None)(implicit
      ec: ExecutionContext
  ): Future[SettingsResponse] = Future {
    requireNotNull(indexName, "Parameter `indexName` is required when calling `getSettings`.")

    val request = HttpRequest
      .builder()
      .withMethod("GET")
      .withPath(s"/1/indexes/${escape(indexName)}/settings")
      .build()
    execute[SettingsResponse](request, requestOptions)
  }

  /** Retrieves all allowed IP addresses with access to your application.
    *
    * Required API Key ACLs:
    *   - admin
    */
  def getSources(requestOptions: Option[RequestOptions] = None)(implicit ec: ExecutionContext): Future[Seq[Source]] =
    Future {

      val request = HttpRequest
        .builder()
        .withMethod("GET")
        .withPath(s"/1/security/sources")
        .build()
      execute[Seq[Source]](request, requestOptions)
    }

  /** Retrieves a syonym by its ID. To find the object IDs for your synonyms, use the [`search`
    * operation](#tag/Synonyms/operation/searchSynonyms).
    *
    * Required API Key ACLs:
    *   - settings
    *
    * @param indexName
    *   Name of the index on which to perform the operation.
    * @param objectID
    *   Unique identifier of a synonym object.
    */
  def getSynonym(indexName: String, objectID: String, requestOptions: Option[RequestOptions] = None)(implicit
      ec: ExecutionContext
  ): Future[SynonymHit] = Future {
    requireNotNull(indexName, "Parameter `indexName` is required when calling `getSynonym`.")
    requireNotNull(objectID, "Parameter `objectID` is required when calling `getSynonym`.")

    val request = HttpRequest
      .builder()
      .withMethod("GET")
      .withPath(s"/1/indexes/${escape(indexName)}/synonyms/${escape(objectID)}")
      .build()
    execute[SynonymHit](request, requestOptions)
  }

  /** Checks the status of a given task. Indexing tasks are asynchronous. When you add, update, or delete records or
    * indices, a task is created on a queue and completed depending on the load on the server. The indexing tasks'
    * responses include a task ID that you can use to check the status.
    *
    * Required API Key ACLs:
    *   - addObject
    *
    * @param indexName
    *   Name of the index on which to perform the operation.
    * @param taskID
    *   Unique task identifier.
    */
  def getTask(indexName: String, taskID: Long, requestOptions: Option[RequestOptions] = None)(implicit
      ec: ExecutionContext
  ): Future[GetTaskResponse] = Future {
    requireNotNull(indexName, "Parameter `indexName` is required when calling `getTask`.")
    requireNotNull(taskID, "Parameter `taskID` is required when calling `getTask`.")

    val request = HttpRequest
      .builder()
      .withMethod("GET")
      .withPath(s"/1/indexes/${escape(indexName)}/task/${escape(taskID)}")
      .build()
    execute[GetTaskResponse](request, requestOptions)
  }

  /** Get the IDs of the 10 users with the highest number of records per cluster. Since it can take a few seconds to get
    * the data from the different clusters, the response isn't real-time.
    *
    * Required API Key ACLs:
    *   - admin
    */
  def getTopUserIds(
      requestOptions: Option[RequestOptions] = None
  )(implicit ec: ExecutionContext): Future[GetTopUserIdsResponse] = Future {

    val request = HttpRequest
      .builder()
      .withMethod("GET")
      .withPath(s"/1/clusters/mapping/top")
      .build()
    execute[GetTopUserIdsResponse](request, requestOptions)
  }

  /** Returns the user ID data stored in the mapping. Since it can take a few seconds to get the data from the different
    * clusters, the response isn't real-time.
    *
    * Required API Key ACLs:
    *   - admin
    *
    * @param userID
    *   Unique identifier of the user who makes the search request.
    */
  def getUserId(userID: String, requestOptions: Option[RequestOptions] = None)(implicit
      ec: ExecutionContext
  ): Future[UserId] = Future {
    requireNotNull(userID, "Parameter `userID` is required when calling `getUserId`.")

    val request = HttpRequest
      .builder()
      .withMethod("GET")
      .withPath(s"/1/clusters/mapping/${escape(userID)}")
      .build()
    execute[UserId](request, requestOptions)
  }

  /** To determine when the time-consuming process of creating a large batch of users or migrating users from one
    * cluster to another is complete, this operation retrieves the status of the process.
    *
    * Required API Key ACLs:
    *   - admin
    *
    * @param getClusters
    *   Whether to include the cluster's pending mapping state in the response.
    */
  def hasPendingMappings(getClusters: Option[Boolean] = None, requestOptions: Option[RequestOptions] = None)(implicit
      ec: ExecutionContext
  ): Future[HasPendingMappingsResponse] = Future {

    val request = HttpRequest
      .builder()
      .withMethod("GET")
      .withPath(s"/1/clusters/mapping/pending")
      .withQueryParameter("getClusters", getClusters)
      .build()
    execute[HasPendingMappingsResponse](request, requestOptions)
  }

  /** Lists all API keys associated with your Algolia application, including their permissions and restrictions.
    *
    * Required API Key ACLs:
    *   - admin
    */
  def listApiKeys(
      requestOptions: Option[RequestOptions] = None
  )(implicit ec: ExecutionContext): Future[ListApiKeysResponse] = Future {

    val request = HttpRequest
      .builder()
      .withMethod("GET")
      .withPath(s"/1/keys")
      .build()
    execute[ListApiKeysResponse](request, requestOptions)
  }

  /** Lists the available clusters in a multi-cluster setup.
    *
    * Required API Key ACLs:
    *   - admin
    */
  def listClusters(
      requestOptions: Option[RequestOptions] = None
  )(implicit ec: ExecutionContext): Future[ListClustersResponse] = Future {

    val request = HttpRequest
      .builder()
      .withMethod("GET")
      .withPath(s"/1/clusters")
      .build()
    execute[ListClustersResponse](request, requestOptions)
  }

  /** Lists all indices in the current Algolia application. The request follows any index restrictions of the API key
    * you use to make the request.
    *
    * Required API Key ACLs:
    *   - listIndexes
    *
    * @param page
    *   Requested page of the API response. If `null`, the API response is not paginated.
    * @param hitsPerPage
    *   Number of hits per page.
    */
  def listIndices(
      page: Option[Int] = None,
      hitsPerPage: Option[Int] = None,
      requestOptions: Option[RequestOptions] = None
  )(implicit ec: ExecutionContext): Future[ListIndicesResponse] = Future {

    val request = HttpRequest
      .builder()
      .withMethod("GET")
      .withPath(s"/1/indexes")
      .withQueryParameter("page", page)
      .withQueryParameter("hitsPerPage", hitsPerPage)
      .build()
    execute[ListIndicesResponse](request, requestOptions)
  }

  /** Lists the userIDs assigned to a multi-cluster application. Since it can take a few seconds to get the data from
    * the different clusters, the response isn't real-time.
    *
    * Required API Key ACLs:
    *   - admin
    *
    * @param page
    *   Requested page of the API response. If `null`, the API response is not paginated.
    * @param hitsPerPage
    *   Number of hits per page.
    */
  def listUserIds(
      page: Option[Int] = None,
      hitsPerPage: Option[Int] = None,
      requestOptions: Option[RequestOptions] = None
  )(implicit ec: ExecutionContext): Future[ListUserIdsResponse] = Future {

    val request = HttpRequest
      .builder()
      .withMethod("GET")
      .withPath(s"/1/clusters/mapping")
      .withQueryParameter("page", page)
      .withQueryParameter("hitsPerPage", hitsPerPage)
      .build()
    execute[ListUserIdsResponse](request, requestOptions)
  }

  /** Adds, updates, or deletes records in multiple indices with a single API request. - Actions are applied in the
    * order they are specified. - Actions are equivalent to the individual API requests of the same name.
    */
  def multipleBatch(batchParams: BatchParams, requestOptions: Option[RequestOptions] = None)(implicit
      ec: ExecutionContext
  ): Future[MultipleBatchResponse] = Future {
    requireNotNull(batchParams, "Parameter `batchParams` is required when calling `multipleBatch`.")

    val request = HttpRequest
      .builder()
      .withMethod("POST")
      .withPath(s"/1/indexes/*/batch")
      .withBody(batchParams)
      .build()
    execute[MultipleBatchResponse](request, requestOptions)
  }

  /** Copies or moves (renames) an index within the same Algolia application. - Existing destination indices are
    * overwritten, except for their analytics data. - If the destination index doesn't exist yet, it'll be created.
    * **Copy** - Copying a source index that doesn't exist creates a new index with 0 records and default settings. -
    * The API keys of the source index are merged with the existing keys in the destination index. - You can't copy the
    * `enableReRanking`, `mode`, and `replicas` settings. - You can't copy to a destination index that already has
    * replicas. - Be aware of the [size
    * limits](https://www.algolia.com/doc/guides/scaling/algolia-service-limits/#application-record-and-index-limits). -
    * Related guide: [Copy
    * indices](https://www.algolia.com/doc/guides/sending-and-managing-data/manage-indices-and-apps/manage-indices/how-to/copy-indices/)
    * **Move** - Moving a source index that doesn't exist is ignored without returning an error. - When moving an index,
    * the analytics data keep their original name and a new set of analytics data is started for the new name. To access
    * the original analytics in the dashboard, create an index with the original name. - If the destination index has
    * replicas, moving will overwrite the existing index and copy the data to the replica indices. - Related guide:
    * [Move
    * indices](https://www.algolia.com/doc/guides/sending-and-managing-data/manage-indices-and-apps/manage-indices/how-to/move-indices/).
    *
    * Required API Key ACLs:
    *   - addObject
    *
    * @param indexName
    *   Name of the index on which to perform the operation.
    */
  def operationIndex(
      indexName: String,
      operationIndexParams: OperationIndexParams,
      requestOptions: Option[RequestOptions] = None
  )(implicit ec: ExecutionContext): Future[UpdatedAtResponse] = Future {
    requireNotNull(indexName, "Parameter `indexName` is required when calling `operationIndex`.")
    requireNotNull(operationIndexParams, "Parameter `operationIndexParams` is required when calling `operationIndex`.")

    val request = HttpRequest
      .builder()
      .withMethod("POST")
      .withPath(s"/1/indexes/${escape(indexName)}/operation")
      .withBody(operationIndexParams)
      .build()
    execute[UpdatedAtResponse](request, requestOptions)
  }

  /** Adds new attributes to a record, or update existing ones. - If a record with the specified object ID doesn't
    * exist, a new record is added to the index **if** `createIfNotExists` is true. - If the index doesn't exist yet,
    * this method creates a new index. - You can use any first-level attribute but not nested attributes. If you specify
    * a nested attribute, the engine treats it as a replacement for its first-level ancestor. To update an attribute
    * without pushing the entire record, you can use these built-in operations. These operations can be helpful if you
    * don't have access to your initial data. - Increment: increment a numeric attribute - Decrement: decrement a
    * numeric attribute - Add: append a number or string element to an array attribute - Remove: remove all matching
    * number or string elements from an array attribute made of numbers or strings - AddUnique: add a number or string
    * element to an array attribute made of numbers or strings only if it's not already present - IncrementFrom:
    * increment a numeric integer attribute only if the provided value matches the current value, and otherwise ignore
    * the whole object update. For example, if you pass an IncrementFrom value of 2 for the version attribute, but the
    * current value of the attribute is 1, the engine ignores the update. If the object doesn't exist, the engine only
    * creates it if you pass an IncrementFrom value of 0. - IncrementSet: increment a numeric integer attribute only if
    * the provided value is greater than the current value, and otherwise ignore the whole object update. For example,
    * if you pass an IncrementSet value of 2 for the version attribute, and the current value of the attribute is 1, the
    * engine updates the object. If the object doesn't exist yet, the engine only creates it if you pass an IncrementSet
    * value that's greater than 0. You can specify an operation by providing an object with the attribute to update as
    * the key and its value being an object with the following properties: - _operation: the operation to apply on the
    * attribute - value: the right-hand side argument to the operation, for example, increment or decrement step, value
    * to add or remove.
    *
    * Required API Key ACLs:
    *   - addObject
    *
    * @param indexName
    *   Name of the index on which to perform the operation.
    * @param objectID
    *   Unique record identifier.
    * @param attributesToUpdate
    *   Attributes with their values.
    * @param createIfNotExists
    *   Whether to create a new record if it doesn't exist.
    */
  def partialUpdateObject(
      indexName: String,
      objectID: String,
      attributesToUpdate: Any,
      createIfNotExists: Option[Boolean] = None,
      requestOptions: Option[RequestOptions] = None
  )(implicit ec: ExecutionContext): Future[UpdatedAtWithObjectIdResponse] = Future {
    requireNotNull(indexName, "Parameter `indexName` is required when calling `partialUpdateObject`.")
    requireNotNull(objectID, "Parameter `objectID` is required when calling `partialUpdateObject`.")
    requireNotNull(attributesToUpdate, "Parameter `attributesToUpdate` is required when calling `partialUpdateObject`.")

    val request = HttpRequest
      .builder()
      .withMethod("POST")
      .withPath(s"/1/indexes/${escape(indexName)}/${escape(objectID)}/partial")
      .withBody(attributesToUpdate)
      .withQueryParameter("createIfNotExists", createIfNotExists)
      .build()
    execute[UpdatedAtWithObjectIdResponse](request, requestOptions)
  }

  /** Deletes a user ID and its associated data from the clusters.
    *
    * Required API Key ACLs:
    *   - admin
    *
    * @param userID
    *   Unique identifier of the user who makes the search request.
    */
  def removeUserId(userID: String, requestOptions: Option[RequestOptions] = None)(implicit
      ec: ExecutionContext
  ): Future[RemoveUserIdResponse] = Future {
    requireNotNull(userID, "Parameter `userID` is required when calling `removeUserId`.")

    val request = HttpRequest
      .builder()
      .withMethod("DELETE")
      .withPath(s"/1/clusters/mapping/${escape(userID)}")
      .build()
    execute[RemoveUserIdResponse](request, requestOptions)
  }

  /** Replaces the list of allowed sources.
    *
    * Required API Key ACLs:
    *   - admin
    *
    * @param source
    *   Allowed sources.
    */
  def replaceSources(source: Seq[Source], requestOptions: Option[RequestOptions] = None)(implicit
      ec: ExecutionContext
  ): Future[ReplaceSourceResponse] = Future {
    requireNotNull(source, "Parameter `source` is required when calling `replaceSources`.")

    val request = HttpRequest
      .builder()
      .withMethod("PUT")
      .withPath(s"/1/security/sources")
      .withBody(source)
      .build()
    execute[ReplaceSourceResponse](request, requestOptions)
  }

  /** Restores a deleted API key. Restoring resets the `validity` attribute to `0`. Algolia stores up to 1,000 API keys
    * per application. If you create more, the oldest API keys are deleted and can't be restored.
    *
    * Required API Key ACLs:
    *   - admin
    *
    * @param key
    *   API key.
    */
  def restoreApiKey(key: String, requestOptions: Option[RequestOptions] = None)(implicit
      ec: ExecutionContext
  ): Future[AddApiKeyResponse] = Future {
    requireNotNull(key, "Parameter `key` is required when calling `restoreApiKey`.")

    val request = HttpRequest
      .builder()
      .withMethod("POST")
      .withPath(s"/1/keys/${escape(key)}/restore")
      .build()
    execute[AddApiKeyResponse](request, requestOptions)
  }

  /** Adds a record to an index or replace it. - If the record doesn't have an object ID, a new record with an
    * auto-generated object ID is added to your index. - If a record with the specified object ID exists, the existing
    * record is replaced. - If a record with the specified object ID doesn't exist, a new record is added to your index.
    * \- If you add a record to an index that doesn't exist yet, a new index is created. To update _some_ attributes of
    * a record, use the [`partial` operation](#tag/Records/operation/partialUpdateObject). To add, update, or replace
    * multiple records, use the [`batch` operation](#tag/Records/operation/batch).
    *
    * Required API Key ACLs:
    *   - addObject
    *
    * @param indexName
    *   Name of the index on which to perform the operation.
    * @param body
    *   The record, a schemaless object with attributes that are useful in the context of search and discovery.
    */
  def saveObject(indexName: String, body: Any, requestOptions: Option[RequestOptions] = None)(implicit
      ec: ExecutionContext
  ): Future[SaveObjectResponse] = Future {
    requireNotNull(indexName, "Parameter `indexName` is required when calling `saveObject`.")
    requireNotNull(body, "Parameter `body` is required when calling `saveObject`.")

    val request = HttpRequest
      .builder()
      .withMethod("POST")
      .withPath(s"/1/indexes/${escape(indexName)}")
      .withBody(body)
      .build()
    execute[SaveObjectResponse](request, requestOptions)
  }

  /** If a rule with the specified object ID doesn't exist, it's created. Otherwise, the existing rule is replaced. To
    * create or update more than one rule, use the [`batch` operation](#tag/Rules/operation/saveRules).
    *
    * Required API Key ACLs:
    *   - editSettings
    *
    * @param indexName
    *   Name of the index on which to perform the operation.
    * @param objectID
    *   Unique identifier of a rule object.
    * @param forwardToReplicas
    *   Whether changes are applied to replica indices.
    */
  def saveRule(
      indexName: String,
      objectID: String,
      rule: Rule,
      forwardToReplicas: Option[Boolean] = None,
      requestOptions: Option[RequestOptions] = None
  )(implicit ec: ExecutionContext): Future[UpdatedRuleResponse] = Future {
    requireNotNull(indexName, "Parameter `indexName` is required when calling `saveRule`.")
    requireNotNull(objectID, "Parameter `objectID` is required when calling `saveRule`.")
    requireNotNull(rule, "Parameter `rule` is required when calling `saveRule`.")

    val request = HttpRequest
      .builder()
      .withMethod("PUT")
      .withPath(s"/1/indexes/${escape(indexName)}/rules/${escape(objectID)}")
      .withBody(rule)
      .withQueryParameter("forwardToReplicas", forwardToReplicas)
      .build()
    execute[UpdatedRuleResponse](request, requestOptions)
  }

  /** Create or update multiple rules. If a rule with the specified object ID doesn't exist, Algolia creates a new one.
    * Otherwise, existing rules are replaced.
    *
    * Required API Key ACLs:
    *   - editSettings
    *
    * @param indexName
    *   Name of the index on which to perform the operation.
    * @param forwardToReplicas
    *   Whether changes are applied to replica indices.
    * @param clearExistingRules
    *   Whether existing rules should be deleted before adding this batch.
    */
  def saveRules(
      indexName: String,
      rules: Seq[Rule],
      forwardToReplicas: Option[Boolean] = None,
      clearExistingRules: Option[Boolean] = None,
      requestOptions: Option[RequestOptions] = None
  )(implicit ec: ExecutionContext): Future[UpdatedAtResponse] = Future {
    requireNotNull(indexName, "Parameter `indexName` is required when calling `saveRules`.")
    requireNotNull(rules, "Parameter `rules` is required when calling `saveRules`.")

    val request = HttpRequest
      .builder()
      .withMethod("POST")
      .withPath(s"/1/indexes/${escape(indexName)}/rules/batch")
      .withBody(rules)
      .withQueryParameter("forwardToReplicas", forwardToReplicas)
      .withQueryParameter("clearExistingRules", clearExistingRules)
      .build()
    execute[UpdatedAtResponse](request, requestOptions)
  }

  /** If a synonym with the specified object ID doesn't exist, Algolia adds a new one. Otherwise, the existing synonym
    * is replaced. To add multiple synonyms in a single API request, use the [`batch`
    * operation](#tag/Synonyms/operation/saveSynonyms).
    *
    * Required API Key ACLs:
    *   - editSettings
    *
    * @param indexName
    *   Name of the index on which to perform the operation.
    * @param objectID
    *   Unique identifier of a synonym object.
    * @param forwardToReplicas
    *   Whether changes are applied to replica indices.
    */
  def saveSynonym(
      indexName: String,
      objectID: String,
      synonymHit: SynonymHit,
      forwardToReplicas: Option[Boolean] = None,
      requestOptions: Option[RequestOptions] = None
  )(implicit ec: ExecutionContext): Future[SaveSynonymResponse] = Future {
    requireNotNull(indexName, "Parameter `indexName` is required when calling `saveSynonym`.")
    requireNotNull(objectID, "Parameter `objectID` is required when calling `saveSynonym`.")
    requireNotNull(synonymHit, "Parameter `synonymHit` is required when calling `saveSynonym`.")

    val request = HttpRequest
      .builder()
      .withMethod("PUT")
      .withPath(s"/1/indexes/${escape(indexName)}/synonyms/${escape(objectID)}")
      .withBody(synonymHit)
      .withQueryParameter("forwardToReplicas", forwardToReplicas)
      .build()
    execute[SaveSynonymResponse](request, requestOptions)
  }

  /** If a synonym with the `objectID` doesn't exist, Algolia adds a new one. Otherwise, existing synonyms are replaced.
    *
    * Required API Key ACLs:
    *   - editSettings
    *
    * @param indexName
    *   Name of the index on which to perform the operation.
    * @param forwardToReplicas
    *   Whether changes are applied to replica indices.
    * @param replaceExistingSynonyms
    *   Whether to replace all synonyms in the index with the ones sent with this request.
    */
  def saveSynonyms(
      indexName: String,
      synonymHit: Seq[SynonymHit],
      forwardToReplicas: Option[Boolean] = None,
      replaceExistingSynonyms: Option[Boolean] = None,
      requestOptions: Option[RequestOptions] = None
  )(implicit ec: ExecutionContext): Future[UpdatedAtResponse] = Future {
    requireNotNull(indexName, "Parameter `indexName` is required when calling `saveSynonyms`.")
    requireNotNull(synonymHit, "Parameter `synonymHit` is required when calling `saveSynonyms`.")

    val request = HttpRequest
      .builder()
      .withMethod("POST")
      .withPath(s"/1/indexes/${escape(indexName)}/synonyms/batch")
      .withBody(synonymHit)
      .withQueryParameter("forwardToReplicas", forwardToReplicas)
      .withQueryParameter("replaceExistingSynonyms", replaceExistingSynonyms)
      .build()
    execute[UpdatedAtResponse](request, requestOptions)
  }

  /** Sends multiple search request to one or more indices. This can be useful in these cases: - Different indices for
    * different purposes, such as, one index for products, another one for marketing content. - Multiple searches to the
    * same index—for example, with different filters.
    *
    * Required API Key ACLs:
    *   - search
    *
    * @param searchMethodParams
    *   Muli-search request body. Results are returned in the same order as the requests.
    */
  def search(searchMethodParams: SearchMethodParams, requestOptions: Option[RequestOptions] = None)(implicit
      ec: ExecutionContext
  ): Future[SearchResponses] = Future {
    requireNotNull(searchMethodParams, "Parameter `searchMethodParams` is required when calling `search`.")

    val request = HttpRequest
      .builder()
      .withMethod("POST")
      .withPath(s"/1/indexes/*/queries")
      .withBody(searchMethodParams)
      .withRead(true)
      .build()
    execute[SearchResponses](request, requestOptions)
  }

  /** Searches for standard and custom dictionary entries.
    *
    * Required API Key ACLs:
    *   - settings
    *
    * @param dictionaryName
    *   Dictionary type in which to search.
    */
  def searchDictionaryEntries(
      dictionaryName: DictionaryType,
      searchDictionaryEntriesParams: SearchDictionaryEntriesParams,
      requestOptions: Option[RequestOptions] = None
  )(implicit ec: ExecutionContext): Future[SearchDictionaryEntriesResponse] = Future {
    requireNotNull(dictionaryName, "Parameter `dictionaryName` is required when calling `searchDictionaryEntries`.")
    requireNotNull(
      searchDictionaryEntriesParams,
      "Parameter `searchDictionaryEntriesParams` is required when calling `searchDictionaryEntries`."
    )

    val request = HttpRequest
      .builder()
      .withMethod("POST")
      .withPath(s"/1/dictionaries/${escape(dictionaryName)}/search")
      .withBody(searchDictionaryEntriesParams)
      .withRead(true)
      .build()
    execute[SearchDictionaryEntriesResponse](request, requestOptions)
  }

  /** Searches for values of a specified facet attribute. - By default, facet values are sorted by decreasing count. You
    * can adjust this with the `sortFacetValueBy` parameter. - Searching for facet values doesn't work if you have
    * **more than 65 searchable facets and searchable attributes combined**.
    *
    * Required API Key ACLs:
    *   - search
    *
    * @param indexName
    *   Name of the index on which to perform the operation.
    * @param facetName
    *   Facet attribute in which to search for values. This attribute must be included in the `attributesForFaceting`
    *   index setting with the `searchable()` modifier.
    */
  def searchForFacetValues(
      indexName: String,
      facetName: String,
      searchForFacetValuesRequest: Option[SearchForFacetValuesRequest] = None,
      requestOptions: Option[RequestOptions] = None
  )(implicit ec: ExecutionContext): Future[SearchForFacetValuesResponse] = Future {
    requireNotNull(indexName, "Parameter `indexName` is required when calling `searchForFacetValues`.")
    requireNotNull(facetName, "Parameter `facetName` is required when calling `searchForFacetValues`.")

    val request = HttpRequest
      .builder()
      .withMethod("POST")
      .withPath(s"/1/indexes/${escape(indexName)}/facets/${escape(facetName)}/query")
      .withBody(searchForFacetValuesRequest)
      .withRead(true)
      .build()
    execute[SearchForFacetValuesResponse](request, requestOptions)
  }

  /** Searches for rules in your index.
    *
    * Required API Key ACLs:
    *   - settings
    *
    * @param indexName
    *   Name of the index on which to perform the operation.
    */
  def searchRules(
      indexName: String,
      searchRulesParams: Option[SearchRulesParams] = None,
      requestOptions: Option[RequestOptions] = None
  )(implicit ec: ExecutionContext): Future[SearchRulesResponse] = Future {
    requireNotNull(indexName, "Parameter `indexName` is required when calling `searchRules`.")

    val request = HttpRequest
      .builder()
      .withMethod("POST")
      .withPath(s"/1/indexes/${escape(indexName)}/rules/search")
      .withBody(searchRulesParams)
      .withRead(true)
      .build()
    execute[SearchRulesResponse](request, requestOptions)
  }

  /** Searches a single index and return matching search results (_hits_). This method lets you retrieve up to 1,000
    * hits. If you need more, use the [`browse` operation](#tag/Search/operation/browse) or increase the
    * `paginatedLimitedTo` index setting.
    *
    * Required API Key ACLs:
    *   - search
    *
    * @param indexName
    *   Name of the index on which to perform the operation.
    */
  def searchSingleIndex(
      indexName: String,
      searchParams: Option[SearchParams] = None,
      requestOptions: Option[RequestOptions] = None
  )(implicit ec: ExecutionContext): Future[SearchResponse] = Future {
    requireNotNull(indexName, "Parameter `indexName` is required when calling `searchSingleIndex`.")

    val request = HttpRequest
      .builder()
      .withMethod("POST")
      .withPath(s"/1/indexes/${escape(indexName)}/query")
      .withBody(searchParams)
      .withRead(true)
      .build()
    execute[SearchResponse](request, requestOptions)
  }

  /** Searches for synonyms in your index.
    *
    * Required API Key ACLs:
    *   - settings
    *
    * @param indexName
    *   Name of the index on which to perform the operation.
    * @param searchSynonymsParams
    *   Body of the `searchSynonyms` operation.
    */
  def searchSynonyms(
      indexName: String,
      searchSynonymsParams: Option[SearchSynonymsParams] = None,
      requestOptions: Option[RequestOptions] = None
  )(implicit ec: ExecutionContext): Future[SearchSynonymsResponse] = Future {
    requireNotNull(indexName, "Parameter `indexName` is required when calling `searchSynonyms`.")

    val request = HttpRequest
      .builder()
      .withMethod("POST")
      .withPath(s"/1/indexes/${escape(indexName)}/synonyms/search")
      .withBody(searchSynonymsParams)
      .withRead(true)
      .build()
    execute[SearchSynonymsResponse](request, requestOptions)
  }

  /** Since it can take a few seconds to get the data from the different clusters, the response isn't real-time. To
    * ensure rapid updates, the user IDs index isn't built at the same time as the mapping. Instead, it's built every 12
    * hours, at the same time as the update of user ID usage. For example, if you add or move a user ID, the search will
    * show an old value until the next time the mapping is rebuilt (every 12 hours).
    *
    * Required API Key ACLs:
    *   - admin
    */
  def searchUserIds(searchUserIdsParams: SearchUserIdsParams, requestOptions: Option[RequestOptions] = None)(implicit
      ec: ExecutionContext
  ): Future[SearchUserIdsResponse] = Future {
    requireNotNull(searchUserIdsParams, "Parameter `searchUserIdsParams` is required when calling `searchUserIds`.")

    val request = HttpRequest
      .builder()
      .withMethod("POST")
      .withPath(s"/1/clusters/mapping/search")
      .withBody(searchUserIdsParams)
      .withRead(true)
      .build()
    execute[SearchUserIdsResponse](request, requestOptions)
  }

  /** Turns standard stop word dictionary entries on or off for a given language.
    *
    * Required API Key ACLs:
    *   - editSettings
    */
  def setDictionarySettings(
      dictionarySettingsParams: DictionarySettingsParams,
      requestOptions: Option[RequestOptions] = None
  )(implicit ec: ExecutionContext): Future[UpdatedAtResponse] = Future {
    requireNotNull(
      dictionarySettingsParams,
      "Parameter `dictionarySettingsParams` is required when calling `setDictionarySettings`."
    )

    val request = HttpRequest
      .builder()
      .withMethod("PUT")
      .withPath(s"/1/dictionaries/*/settings")
      .withBody(dictionarySettingsParams)
      .build()
    execute[UpdatedAtResponse](request, requestOptions)
  }

  /** Update the specified index settings. Index settings that you don't specify are left unchanged. Specify `null` to
    * reset a setting to its default value. For best performance, update the index settings before you add new records
    * to your index.
    *
    * Required API Key ACLs:
    *   - editSettings
    *
    * @param indexName
    *   Name of the index on which to perform the operation.
    * @param forwardToReplicas
    *   Whether changes are applied to replica indices.
    */
  def setSettings(
      indexName: String,
      indexSettings: IndexSettings,
      forwardToReplicas: Option[Boolean] = None,
      requestOptions: Option[RequestOptions] = None
  )(implicit ec: ExecutionContext): Future[UpdatedAtResponse] = Future {
    requireNotNull(indexName, "Parameter `indexName` is required when calling `setSettings`.")
    requireNotNull(indexSettings, "Parameter `indexSettings` is required when calling `setSettings`.")

    val request = HttpRequest
      .builder()
      .withMethod("PUT")
      .withPath(s"/1/indexes/${escape(indexName)}/settings")
      .withBody(indexSettings)
      .withQueryParameter("forwardToReplicas", forwardToReplicas)
      .build()
    execute[UpdatedAtResponse](request, requestOptions)
  }

  /** Replaces the permissions of an existing API key. Any unspecified attribute resets that attribute to its default
    * value.
    *
    * Required API Key ACLs:
    *   - admin
    *
    * @param key
    *   API key.
    */
  def updateApiKey(key: String, apiKey: ApiKey, requestOptions: Option[RequestOptions] = None)(implicit
      ec: ExecutionContext
  ): Future[UpdateApiKeyResponse] = Future {
    requireNotNull(key, "Parameter `key` is required when calling `updateApiKey`.")
    requireNotNull(apiKey, "Parameter `apiKey` is required when calling `updateApiKey`.")

    val request = HttpRequest
      .builder()
      .withMethod("PUT")
      .withPath(s"/1/keys/${escape(key)}")
      .withBody(apiKey)
      .build()
    execute[UpdateApiKeyResponse](request, requestOptions)
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy