> Fetch the index of every Tonbo docs page as Markdown at https://tonbo.dev/llms.txt

# resolveDatabase()

Last updated 29 October 2026

`resolveDatabase` turns a database name into the URL and the `token` option another opener takes, without opening the database.

## resolveDatabase()

From `@tonbo/sqlite-ursula/tonbo`, since 0.11.1.

```text
function resolveDatabase(
  nameOrUrl: string | URL,
  options?: TonboResolveOptions,
): Promise<ResolvedDatabase>

interface TonboResolveOptions {
  apiKey?: string;
  apiOrigin?: string;
  authOrigin?: string;
  token?: string | TokenProvider;
  signal?: AbortSignal;
}

interface ResolvedDatabase {
  url: string;
  token: string | TokenProvider | undefined;
}
```

```js
import { openUrsulaPiStorage } from "@tonbo/sqlite-ursula/pi";
import { resolveDatabase } from "@tonbo/sqlite-ursula/tonbo";

// token is undefined while the key's own tokens serve: pass it on as it is.
const { url, token } = await resolveDatabase("notes");
const storage = await openUrsulaPiStorage(url, { token, closeTimeoutMs: 10_000 });
```

It finds the key and looks the name up as the `/tonbo` [open()](https://tonbo.dev/docs/reference/nodejs/open.md#tonbo-open) does, and opens nothing. Unless a `token` or `URSULA_VFS_TOKEN_FILE` serves the stream, the key then becomes the process’s source of Streams tokens, which the extension exchanges and refreshes in the background, and the resolve returns once it holds the first one, so you run no refresher of your own. From then on the key’s tokens serve every Streams request of the process, in place of a token an earlier open set. Concurrent calls with the same arguments on one JavaScript thread share one resolve. This is so since 0.11.2: 0.11.1 exchanged nothing here, and handed out a token provider that the open called.

## Options

`TonboResolveOptions`:

| Option | Default | What it does |
| --- | --- | --- |
| `apiKey` | `TONBO_API_KEY`, else the login `tonbo login` saved | As [open()](https://tonbo.dev/docs/reference/nodejs/open.md#option-api-key)’s. |
| `apiOrigin` | `https://api.tonbo.dev` | As [open()](https://tonbo.dev/docs/reference/nodejs/open.md#option-api-origin)’s, or `TONBO_API_ORIGIN`. |
| `authOrigin` | `https://tonbo.dev` | As [open()](https://tonbo.dev/docs/reference/nodejs/open.md#option-auth-origin)’s, or `TONBO_AUTH_ORIGIN`. |
| `token` | None | A token or provider for the stream, handed back as it is, so the key’s tokens do not serve it. Then a URL needs no key, and the resolve sends nothing. |
| `signal` | 30 seconds | Bounds the resolve: the lookup, and since 0.11.2 the wait for the first token. |

## Result

`ResolvedDatabase`:

| Field | What it holds |
| --- | --- |
| `url` | The database's stream URL: the name's, or the URL given. |
| `token` | The `token` option to open it with: the `token` you passed, or `undefined` when the key’s Streams tokens, which the extension holds and refreshes, or `URSULA_VFS_TOKEN_FILE` serve the stream. Pass it on as it is. Before 0.11.2 it was a [TokenProvider](https://tonbo.dev/docs/reference/nodejs/tokens.md#token-provider) for the key, and code that called `token(...)` now passes `token` through. |

## Errors

It rejects as the `/tonbo` `open` does before it opens the stream: [TonboError](https://tonbo.dev/docs/reference/nodejs/errors.md#tonbo-error) for a key or a database to fix, `UrsulaUnavailableError` when the signal fired while the Tonbo API did not answer, and `UrsulaSetupError` `invalid_name`, `invalid_argument`, `invalid_url` or `local_setup`. A key the token endpoint refuses a Streams token fails the resolve itself with `invalid_api_key`, and a second key fails with `invalid_argument` while the first key’s tokens serve (see [One token per process](https://tonbo.dev/docs/reference/nodejs/tokens.md#one-token)), both since 0.11.2. For Pi, see [Pi Durable storage](https://tonbo.dev/docs/reference/nodejs/pi.md).
