# invariantdb

Official Node/TypeScript client for [InvariantDB](https://invariantdb.com), a
bitemporal, tamper-evident graph database.

## Install

```bash
# From the AWS-hosted tarball (used by StaticOwl + other internal consumers):
npm install https://sdk.invariantdb.com/node/invariantdb-latest.tgz

# Or pin to a version:
npm install https://sdk.invariantdb.com/node/invariantdb-0.5.0.tgz
```

> Note: package renamed `@invariantdb/client` → `invariantdb` in v0.5.0.
> Existing imports of `@invariantdb/client` must be updated to `invariantdb`.

## Quickstart

```ts
import { Client } from "invariantdb";

const c = new Client({ url: "https://invariantdb.com", apiKey: "gq_..." });

// Cypher
const result = await c.cypher("my_graph", "MATCH (n:Person) RETURN n.name LIMIT 10");
for (const row of result.asDicts()) {
  console.log(row["n.name"]);
}

// Atomic writes — properties auto-wrap to the engine's tagged Value format.
await c.write("my_graph", [
  { createNode: { strId: "n1", labels: ["Person"], properties: { name: "Ada" } } },
  { createEdge: { strId: "e1", type: "KNOWS", source: "n1", target: "n2" } },
]);

// Graphs
await c.graphs.list();
await c.graphs.create("new_graph");
await c.graphs.clone({ source: "prod", destination: "prod_snapshot" });

// Schema (versioned)
const v = await c.schema.put("my_graph", { labels: ["Person"] });
const history = await c.schema.history("my_graph");

// Search
const hits = await c.search.fulltext("my_graph", {
  label: "Document",
  property: "body",
  query: "invoice",
});

// Audit chain
const status = await c.audit.verify("my_graph");
console.assert(status.isClean);

// Compliance bundle
await c.compliance.export("my_graph", { output: "/var/lib/exports/bundle.tar.gz" });

// Async imports
const job = await c.jobs.wait("job_id");
console.assert(job.isSucceeded);
```

## Authentication

Pass `apiKey: "gq_..."` to the constructor. The SDK sends it as
`Authorization: Bearer gq_...` on every request. Open-mode servers (no auth
configured) work without `apiKey`.

## Errors

All errors extend `InvariantDBError`. Catch the specific subclass when
you want to branch on the failure mode:

```ts
import { Client, NotFoundError, AuthError } from "invariantdb";

try {
  await c.graphs.info("does_not_exist");
} catch (err) {
  if (err instanceof NotFoundError) {
    // handle missing
  } else if (err instanceof AuthError) {
    // handle bad credentials
  } else {
    throw err;
  }
}
```

## TypeScript

This package is written in TypeScript and ships full type definitions.
All sub-clients (graphs, schema, indexes, audit, backup, jobs, search,
compliance, admin, ai, cluster) are strongly typed.

## License

© 2026 InvariantDB Inc. All rights reserved. Proprietary and confidential.
