@molecule/api-web-search-brave

Provider bond · web-search · API (Node) · v1.1.1 · Apache-2.0

Brave Search web search provider for molecule.dev — independent index, free monthly credits, per-1k pricing beyond them

npm install @molecule/api-web-search-brave

npm · Source on GitHub · Implements @molecule/api-web-search

How it works

@molecule/api-web-search-brave is a provider bond on the API (Node) side: it implements the web-search core interface (@molecule/api-web-search) with a concrete vendor or library behind it.

Your code calls the core; you wire this provider once at startup. Swapping vendors later is one line in that wiring, not a rewrite.

Works with: @molecule/api-secrets, @molecule/api-web-search

Secrets: BRAVE_SEARCH_API_KEY

Reference

Brave Search web search provider for molecule.dev — independent index, free monthly credits, per-1k pricing beyond them

Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit src/index.ts JSDoc, not this file.

Type

provider

Installation

npm install @molecule/api-web-search-brave @molecule/api-web-search @molecule/api-secrets

API

Interfaces

BraveWebSearchConfig

Options for createProvider. Every field falls back to an env var or Brave's documented default.

interface BraveWebSearchConfig {
  /**
   * The Brave Search API subscription token. Defaults to
   * `BRAVE_SEARCH_API_KEY`. Create one at https://brave.com/search/api/ —
   * the Search plan includes free monthly credits.
   */
  apiKey?: string
  /** API base URL. Defaults to `https://api.search.brave.com`. */
  baseUrl?: string
  /** Per-request timeout in milliseconds. Default 15000. */
  timeoutMs?: number
  /** Default result count when a call passes none. Default 5. */
  count?: number
  /** Default country code, e.g. `us`. */
  country?: string
  /** Default search language, e.g. `en`. */
  searchLang?: string
}

ProcessEnv

Environment variables this provider reads.

interface ProcessEnv {
  BRAVE_SEARCH_API_KEY?: string
}

Classes

BraveWebSearchError

Error thrown when the search endpoint refuses or fails.

class BraveWebSearchError extends Error {
  /** HTTP status from Brave (0 when the request never completed). */
  readonly status: number

  /**
   * Create the error.
   *
   * @param message - Human-readable message.
   * @param status - HTTP status.
   */
  constructor(message: string, status: number) {
    super(message)
    this.name = 'BraveWebSearchError'
    this.status = status
  }
}

BraveWebSearchProvider

Web search provider backed by the Brave Search API.

class BraveWebSearchProvider implements WebSearchProvider {
  readonly name = 'brave'

  private readonly apiKey: string
  private readonly baseUrl: string
  private readonly timeoutMs: number
  private readonly defaults: { count?: number; country?: string; searchLang?: string }

  /**
   * Create the provider.
   *
   * @param config - Options; each falls back to an env var or default.
   */
  constructor(config: BraveWebSearchConfig = {}) {
    this.apiKey = config.apiKey ?? process.env.BRAVE_SEARCH_API_KEY ?? ''
    this.baseUrl = (config.baseUrl ?? 'https://api.search.brave.com').replace(/\/+$/, '')
    this.timeoutMs = config.timeoutMs ?? 15_000
    this.defaults = { count: config.count, country: config.country, searchLang: config.searchLang }
  }

  /**
   * Search the web.
   *
   * @param query - The search query (at most 400 characters).
   * @param options - Count (1–20) and localization hints.
   * @returns Results in Brave's relevance order.
   */
  async search(query: string, options?: WebSearchOptions): Promise<WebSearchResult> {
    if (typeof query !== 'string' || query.trim().length === 0) {
      throw new BraveWebSearchError('"query" must be non-empty text.', 0)
    }
    if (query.length > MAX_QUERY_CHARS) {
      throw new BraveWebSearchError(
        `The query is ${query.length} characters; the limit is ${MAX_QUERY_CHARS}.`,
        0,
      )
    }
    const count = Math.max(1, Math.min(MAX_COUNT, options?.count ?? this.defaults.count ?? 5))
    const params = new URLSearchParams({ q: query, count: String(count) })
    const country = options?.country ?? this.defaults.country
    const searchLang = options?.searchLang ?? this.defaults.searchLang
    if (country) params.set('country', country)
    if (searchLang) params.set('search_lang', searchLang)

    if (!this.apiKey) {
      throw new BraveWebSearchError(
        'BRAVE_SEARCH_API_KEY is not set. Create a subscription at https://brave.com/search/api/ and put the key in the API .env.',
        0,
      )
    }
    const response = await fetch(`${this.baseUrl}/res/v1/web/search?${params}`, {
      headers: { Accept: 'application/json', 'X-Subscription-Token': this.apiKey },
      signal: AbortSignal.timeout(this.timeoutMs),
    })
    const text = await response.text()
    if (!response.ok) {
      throw new BraveWebSearchError(
        `Brave web search failed (${response.status}): ${text.slice(0, 200)}`,
        response.status,
      )
    }
    let data: {
      query?: { original?: string }
      web?: { results?: Array<{ title?: string; url?: string; description?: string }> }
    }
    try {
      data = JSON.parse(text)
    } catch (_error) {
      // A proxy/gateway error page, not JSON: report the status, not the body.
      throw new BraveWebSearchError(
        `Brave returned ${response.status} with a non-JSON body.`,
        response.status,
      )
    }
    const results = (data.web?.results ?? []).map((r) => ({
      title: r.title ?? '',
      url: r.url ?? '',
      ...(r.description ? { description: r.description } : {}),
    }))
    return { query: data.query?.original ?? query, results }
  }
}

Functions

createProvider(config)

Create a Brave web search provider.

function createProvider(config?: BraveWebSearchConfig): WebSearchProvider
  • config — Options; each falls back to an env var or default.

Returns: A WebSearchProvider backed by the Brave Search API.

Constants

provider

The provider implementation (wire with setProvider).

const provider: WebSearchProvider

braveWebSearchSecretDefinitions

Secret definitions required by the Brave web search bond.

const braveWebSearchSecretDefinitions: SecretDefinition[]

Core Interface

Implements @molecule/api-web-search interface.

Bond Wiring

Setup function to register this provider with the core interface:

import { setProvider } from '@molecule/api-web-search'
import { provider } from '@molecule/api-web-search-brave'

export function setupWebSearchBrave(): void {
  setProvider(provider)
}

Injection Notes

Requirements

Peer dependencies:

  • @molecule/api-web-search >=1.0.0
  • @molecule/api-secrets ^1.0.1

Environment Variables

Runtime Dependencies

  • @molecule/api-web-search
  • @molecule/api-secrets