# JavaScript and TypeScript

Source: https://mostlyright.md/docs/guides/javascript/

Search a public table from your server and return its rows to your application. Start with one table. You need Node.js 20 or newer, a public table with search ready, and an `mr_use_` key from [Settings → Access](/dashboard/settings/access/).

Open the dataset's **Use → Search API** panel to copy its public table ID. A dataset slug, a Studio table ID and a public table ID are different identifiers. Keep the key on your server; browser and mobile clients call your own authenticated backend.

## Make your first request with fetch

This example needs no package installation. Save it as `search.mjs`. Set `MOSTLYRIGHT_API_KEY` and `MOSTLYRIGHT_TABLE_ID` in your server environment, then run `node search.mjs`.

```js title="search.mjs"
const apiKey = process.env.MOSTLYRIGHT_API_KEY;
const tableId = process.env.MOSTLYRIGHT_TABLE_ID;
if (!apiKey || !tableId) {
  throw new Error("Set MOSTLYRIGHT_API_KEY and MOSTLYRIGHT_TABLE_ID");
}

const response = await fetch("https://mostlyright.md/api/v2/public/search", {
  method: "POST",
  redirect: "error",
  headers: {
    "x-api-key": apiKey,
    "content-type": "application/json",
  },
  body: JSON.stringify({ query: "", tables: [tableId], limit: 20 }),
  signal: AbortSignal.timeout(30_000),
});
if (!response.ok) {
  // Keep credentials and response bodies out of application logs.
  throw new Error(`Search failed: HTTP ${response.status}`);
}
const result = await response.json();
if (result.partial) {
  console.warn("Some tables were unavailable; inspect result.tables.");
}
console.log(result.rows);
```

An empty `query` browses the table. Replace it with the words you want to search. Each result includes `table_id`, `table_version_id`, `row_id` and `fields`. Zero rows is a valid result. A failed request is not an empty result: preserve that distinction in your UI.

## Use the JavaScript SDK

`@mostlyright/search` supplies a typed server client, validates responses and exposes structured errors. **It is not yet published on npm.** If you have access to the Cloud source workspace, build and pack its `search-sdk` package:

```sh
pnpm --filter @mostlyright/search build
pnpm --filter @mostlyright/search pack
```

Install the resulting `.tgz` file in your application with `npm install /path/to/package.tgz`. If you do not have source access, use the fetch example above. The retired weather SDK under `/legacy/sdk/` is a different package.

```ts
import { createSearchClient, SearchError } from "@mostlyright/search";

const apiKey = process.env.MOSTLYRIGHT_API_KEY;
const tableId = process.env.MOSTLYRIGHT_TABLE_ID;
if (!apiKey || !tableId) throw new Error("Set the server environment variables");

const search = createSearchClient({ apiKey, tables: [tableId] });
try {
  const result = await search.search({
    query: "",
    limit: 20,
    signal: AbortSignal.timeout(30_000),
  });
  console.log(result.rows);
} catch (error) {
  if (!(error instanceof SearchError)) throw error;
  console.error(error.code, error.status, error.requestId, error.retryAfterMs);
}
```

Create the client once with a fixed allowlist of public table IDs. A call accepts `query`, optional `limit`, and optional `signal`. The SDK always requests settled results. It does not expose model selection, cursors or a browser search component. It refuses browser execution and does not retry automatically.

## Connect a search box

Your browser sends query text to your own backend. Authenticate and rate-limit that route before calling Mostly Right. Validate the query and limit, take table IDs from server configuration, and return only the result your application needs. Never accept an API origin or arbitrary table list from the browser.

```js
const response = await fetch("/api/search", {
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({ query: searchText }),
  signal: controller.signal,
});
if (!response.ok) throw new Error("Search could not be completed");
const result = await response.json();
```

Cancel the previous request when a new query replaces it. Cancellation does not undo work or usage already recorded. Keep the last successful rows separate from the loading and failure states.

## Limits and failures

Queries accept up to 512 Unicode characters. `limit` is 1–100, default 20. Configure 1–5 distinct public tables. Multi-table search is experimental: tables plan independently, each incurs usage, and their rows are interleaved by rank without a shared relevance score.

`partial: true` means some configured tables were unavailable. Inspect `tables` before displaying a combined result. Authentication, permission, allowance and rate-limit failures fail the request even if another table answered. If every table is unavailable, the endpoint returns 503. Honor a supplied retry delay; avoid automatic retries that may repeat billable work.

For response fields and HTTP failures, read the [Search API reference](/docs/reference/search/). For downloading or filtering rows, use the [Public Dataset API](/docs/reference/public-dataset-api/). For a private table, use authenticated [CLI search](/docs/reference/cli/search/); this SDK only searches public tables.
