Skip to content
sdk

TypeScript

ESM-first. Zero runtime dependencies. Native fetch. Typed .d.ts. AbortSignal supported on every method.

Install

npm install git+ssh://git@git.argand.org/nicweyand/argand.git#main:sdk/typescript

Source-only install from Forgejo. pnpm add and yarn add work the same way. npm registry publish deferred to launch (mid-2026).

Hello world (anonymous)

hello.ts typescript
import { ArgandClient } from "argand";

const client = new ArgandClient();
const response = await client.search("rust async runtime", { limit: 10 });
for (const hit of response.results) {
  console.log(`${hit.rank}. ${hit.title} -> ${hit.url}`);
}

Method surface

  • client.search(query, { page?, limit?, signal? })Promise<SearchResponse>
  • client.lucky(query, { signal? })Promise<string> (Location URL)
  • client.fetch(...) / client.cite(...) — reject with NotImplementedAPIError until v2.

Auth

import { ArgandClient } from "argand";

const client = new ArgandClient({ apiKey: "your-argand-api-key" });
const response = await client.search("tokio");
console.log(response.results[0].url);

Cancellation (AbortSignal)

import { ArgandClient } from "argand";

const client = new ArgandClient();
const ac = new AbortController();
setTimeout(() => ac.abort(), 2000);

try {
  const response = await client.search("slow query", { signal: ac.signal });
  console.log(response.total_results);
} catch (err) {
  if (err instanceof Error && err.name === "AbortError") {
    console.log("cancelled");
  }
}

Self-hosted + custom config

const client = new ArgandClient({
  baseUrl: "https://argand.example.org",
  apiKey: "your-argand-api-key",
  timeoutMs: 15_000,
  retry: { maxAttempts: 5, baseDelayMs: 100, maxDelayMs: 4000 },
});

Retry semantics

Default: 3 attempts, 250ms → 8s exponential backoff. 429 and 5xx retry. Retry-After (seconds form) is honored. 401 / 403 reject immediately with AuthError.

Error types

All errors descend from ArgandError:

  • AuthError — 401/403, never retried.
  • RateLimitError — 429 after retries; carries retryAfterMs.
  • TimeoutError — transport timeout / aborted signal.
  • TransportError — DNS / TLS / connection.
  • ServerError — 5xx after retries.
  • ProtocolError — body doesn't match the contract.
  • NotImplementedAPIError — v2-reserved methods.
import {
  ArgandClient,
  AuthError,
  RateLimitError,
  ServerError,
  NotImplementedAPIError,
} from "argand";

const client = new ArgandClient();
try {
  await client.search("rust async runtime");
} catch (err) {
  if (err instanceof RateLimitError) {
    console.log(`Retry after ${err.retryAfterMs}ms`);
  } else if (err instanceof AuthError) {
    console.log("Bad API key");
  } else if (err instanceof ServerError) {
    console.log("Argand had a bad day");
  } else if (err instanceof NotImplementedAPIError) {
    console.log("Reserved for v2");
  } else {
    throw err;
  }
}