All files / src/utils state.ts

84% Statements 21/25
59.37% Branches 19/32
85.71% Functions 6/7
84% Lines 21/25

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125    5x 5x                                                           5x                     61x         38x 1x     37x                               241x                       178x   178x 38x 38x 140x 140x                   98x 98x   98x                     3x 3x   3x     61x              
import { AutocompleteConfig } from "../config"
import { History } from "./history"
import { Cancellable, makeCancellable } from "./promise"
import { search } from "../search"
import { SearchAutocompleteOptions } from "../autocomplete"
import type { InputSearchQuery, SearchResult } from "@nosto/nosto-js/client"
 
/**
 * @group Autocomplete
 * @category Core
 */
export interface DefaultState {
  /**
   * The current search query object.
   */
  query?: InputSearchQuery
  /**
   * The current search response.
   */
  response?: SearchResult
  /**
   * The history items.
   */
  history?: { item: string }[]
}
 
export type StateActions<State> = {
  updateState(inputValue?: string): PromiseLike<State>
  addHistoryItem(item: string): PromiseLike<State>
  removeHistoryItem(item: string): PromiseLike<State>
  clearHistory(): PromiseLike<State>
}
 
export function getStateActions<State>({
  config,
  history,
  input,
}: {
  config: Required<AutocompleteConfig<State>>
  history?: History
  input: HTMLInputElement
}): StateActions<State> {
  let cancellable: Cancellable<State> | undefined
 
  const fetchState = (
    value: string,
    config: AutocompleteConfig<State>,
    options?: SearchAutocompleteOptions
  ): PromiseLike<State> => {
    if (typeof config.fetch === "function") {
      return config.fetch(value)
    } else {
      // @ts-expect-error type mismatch
      return search(
        {
          query: value,
          ...config.fetch,
        },
        {
          track: config.nostoAnalytics ? "autocomplete" : undefined,
          redirect: false,
          hitDecorators: config.hitDecorators,
          ...options,
        })
    }
  }
 
  function getHistoryState(query: string): PromiseLike<State> {
    // @ts-expect-error type mismatch
    return Promise.resolve({
      query: {
        query,
      },
      history: history?.getItems(),
    })
  }
 
  function updateState(
    inputValue?: string,
    options?: SearchAutocompleteOptions
  ): PromiseLike<State> {
    cancellable?.cancel()
 
    if (inputValue && inputValue.length >= config.minQueryLength) {
      cancellable = makeCancellable(fetchState(inputValue, config, options))
      return cancellable.promise
    } else if (history) {
      return getHistoryState(inputValue ?? "")
    }
 
    return (
      // @ts-expect-error type mismatch
      cancellable?.promise ?? Promise.resolve<State>({})
    )
  }
 
  function addHistoryItem(item: string): PromiseLike<State> {
    if (history) {
      history.add(item)
    }
    return getHistoryState(input.value)
  }
 
  function removeHistoryItem(item: string): PromiseLike<State> {
    Iif (history) {
      history.remove(item)
    }
    return getHistoryState(input.value)
  }
 
  function clearHistory(): PromiseLike<State> {
    if (history) {
      history.clear()
    }
    return getHistoryState(input.value)
  }
 
  return {
    updateState,
    addHistoryItem,
    removeHistoryItem,
    clearHistory,
  }
}