Skip to content

useSearchApi Composable ​

File Information ​

  • Path: app/composables/api/useSearchApi.ts
  • Purpose: Search operations API (recent searches, asset search, search data)
  • Category: Search API Composable

Overview ​

The useSearchApi composable provides functionality for search operations including fetching recent searches, performing asset searches via Typesense, and getting search configuration data.

Functions ​

getRecentSearch ​

Fetches recent search history for a workspace.

Signature:

typescript
getRecentSearch(workspaceId: string): Promise<SearchHistory[]>

Parameters:

  • workspaceId: string - Workspace ID

Returns:

  • Promise<SearchHistory[]> - Array of recent searches

API Endpoint: GET /digital/recent-search?url_workspace_id={workspaceId}

Usage:

typescript
const { getRecentSearch } = useSearchApi()

const recentSearches = await getRecentSearch(workspaceId)
// recentSearches contains array of SearchHistory objects

searchAssets ​

Performs asset search via Typesense server API.

Signature:

typescript
searchAssets(body: any): Promise<SearchApiResponse>

Parameters:

  • body: any - Search request body (collections, query, filters, etc.)

Returns:

  • Promise<SearchApiResponse> - Search results

API Endpoint: POST /api/typesense/search (useApiBase: false - internal route)

Relevance band: before posting, searchAssets passes the body through withRelevanceTier. For each collection in request.collections it takes the collection's sort (request.sort_by string, else request.sort_by[collection], else commonSearchParams.sort_by) and prepends the _eval band from withEvalTier(collection, q, sort), where q is '*' or the query lowercased. The result is sent as a plain string when there is one collection and as a per-collection map when there are several, because the server only accepts those two shapes. With q = '*' no band is added. Band contents and server checks: Search Fields.

Request Body Structure:

typescript
{
  request: {
    q?: string
    collections: string[]
    sort_by?: string
    include_fields?: { [collection: string]: string[] }
    group_by?: string
    group_limit?: number
  }
  commonSearchParams: {
    query_by: string
    per_page: number
    page: number
    sort_by?: string
  }
  workspace_id_filter: string
  filterQuery?: { [collection: string]: string }
}

Usage:

typescript
const { searchAssets } = useSearchApi()

const results = await searchAssets({
  request: {
    q: 'logo',
    collections: ['assets', 'folders'],
    sort_by: 'created_at:desc'
  },
  commonSearchParams: {
    query_by: 'name,description',
    per_page: 20,
    page: 1
  },
  workspace_id_filter: workspaceId,
  filterQuery: {
    assets: 'file_type:image'
  }
})

getSearchData ​

Fetches search configuration data (tags, file types, custom fields) for a workspace. Identical requests made within 5 seconds share one in-flight request; each caller gets a structuredClone of the response so it can mutate its copy safely.

Signature:

typescript
getSearchData(workspaceId: string, instanceId?: string | number, fresh = false): Promise<any>

Parameters:

  • workspaceId: string - Workspace ID
  • instanceId?: string | number - Optional instance ID, sent as instance_id when provided
  • fresh?: boolean - When true, skips the reuse window and always issues a new request (default false)

Returns:

  • Promise<any> - Search data response (cloned)

API Endpoint: GET /digital/get-search-data?workspace_id={workspaceId}&instance_id={instanceId}

Caching: Requests are keyed by their query string in a module-level Map (searchDataRequests) and reused for SEARCH_DATA_REUSE_MS (5000 ms). A failed request is removed from the map so the next call retries.

Usage:

typescript
const { getSearchData } = useSearchApi()

const searchData = await getSearchData(workspaceId, authStore.user?.instance_id)
// Force a fresh request, e.g. after tags change
const latest = await getSearchData(workspaceId, authStore.user?.instance_id, true)

Error Handling ​

All functions include error handling:

typescript
catch (error) {
  console.error('Failed to {operation}:', error)
  throw error
}

Type Definitions ​

typescript
import type { SearchHistory, SearchApiResponse } from '~/types'

Integration with API Client ​

The composable uses the global $api client:

typescript
const { $api } = useNuxtApp()

Note: searchAssets uses useApiBase: false to route to internal server API (/api/typesense/search).

Use Cases ​

Recent Searches ​

typescript
const { getRecentSearch } = useSearchApi()

const loadRecentSearches = async () => {
  try {
    const searches = await getRecentSearch(workspaceId)
    // Display recent searches dropdown...
  } catch (error) {
    console.error('Failed to load recent searches:', error)
  }
}
typescript
const { searchAssets } = useSearchApi()

const performSearch = async (query: string, filters: any) => {
  try {
    const results = await searchAssets({
      request: {
        q: query,
        collections: ['assets'],
        sort_by: 'created_at:desc'
      },
      commonSearchParams: {
        query_by: 'name,description',
        per_page: 20,
        page: 1
      },
      workspace_id_filter: workspaceId,
      filterQuery: filters
    })
    
    // Display results...
  } catch (error) {
    console.error('Search failed:', error)
  }
}

Load Search Configuration ​

typescript
const { getSearchData } = useSearchApi()

const loadSearchConfig = async () => {
  try {
    const searchData = await getSearchData(workspaceId)
    // Use searchData for filters, tags, etc.
  } catch (error) {
    console.error('Failed to load search data:', error)
  }
}