@datastax/astra-db-ts
astra-db-ts is a TypeScript client for interacting with DataStax Astra DB.
This README targets v2.0.0+, which expands on the previous 1.x API. Click here for the pre-existing client readme.
Table of contents
Quickstart
Use your preferred package manager to install @datastax/astra-db-ts.
npm i @datastax/astra-db-ts
If you're using TypeScript, you must use at least version 5.0.0 to use astra-db-ts 2.0, as it uses modern TypeScript features such as const type parameters.
npm i typescript@^5.0.0
Get the API endpoint and your application token for your Astra DB instance @ astra.datastax.com.
Collections
import { DataAPIClient, ObjectId, vector, VectorDoc, oid } from '@datastax/astra-db-ts';
const client = new DataAPIClient({ logging: 'all' });
const db = client.db(process.env.CLIENT_DB_URL!, { token: process.env.CLIENT_DB_TOKEN! });
interface Dream extends VectorDoc {
_id: ObjectId,
summary: string,
tags?: string[],
}
(async () => {
const collection = await db.createCollection<Dream>('dreams', {
defaultId: { type: 'objectId' },
});
await collection.insertMany([{
summary: 'A dinner on the Moon',
$vector: vector([0.2, -0.3, -0.5]),
}, {
summary: 'Riding the waves',
$vector: vector([0, 0.2, 1]),
tags: ['sport'],
}, {
_id: oid('674f0f5c1c162131319fa09e'),
summary: 'Meeting Beethoven at the dentist',
$vector: vector([0.2, 0.6, 0]),
}]);
await collection.updateOne({ _id: oid('674f0f5c1c162131319fa09e') }, {
$set: { summary: 'Surfers\' paradise' }
});
const cursor = collection.find({})
.sort({ vector: vector([0, 0.2, 0.4]) })
.includeSimilarity(true)
.limit(2);
for await (const result of cursor) {
console.log(`${result.summary}: ${result.$similarity}`);
}
await collection.drop();
})();
Tables
import { DataAPIClient, InferTableSchema, Table, vector } from '@datastax/astra-db-ts';
const client = new DataAPIClient({ logging: 'all' });
const db = client.db(process.env.CLIENT_DB_URL!, { token: process.env.CLIENT_DB_TOKEN! });
const DreamsTableSchema = Table.schema({
columns: {
id: 'int',
summary: 'text',
tags: { type: 'set', valueType: 'text' },
vector: { type: 'vector', dimension: 3 },
},
primaryKey: 'id',
});
type Dream = InferTableSchema<typeof DreamsTableSchema>;
(async () => {
const table = await db.createTable('dreams', {
definition: DreamsTableSchema,
ifNotExists: true,
});
await table.createVectorIndex('dreams_vector_idx', 'vector', {
options: { metric: 'cosine' },
ifNotExists: true,
});
const rows: Dream[] = [{
id: 102,
summary: 'A dinner on the Moon',
vector: vector([0.2, -0.3, -0.5]),
}, {
id: 103,
summary: 'Riding the waves',
vector: vector([0, 0.2, 1]),
tags: new Set(['sport']),
}, {
id: 37,
summary: 'Meeting Beethoven at the dentist',
vector: vector([0.2, 0.6, 0]),
}];
await table.insertMany(rows);
await table.updateOne({ id: 103 }, {
$set: { summary: 'Surfers\' paradise' }
});
const cursor = table.find({})
.sort({ vector: vector([0, 0.2, 0.4]) })
.includeSimilarity(true)
.limit(2);
for await (const result of cursor) {
console.log(`${result.summary}: ${result.$similarity}`);
}
await table.drop();
})();
Next steps
High-level architecture
astra-db-ts's abstractions for working at the data and admin layers are structured as depicted by this diagram:
flowchart TD
DataAPIClient -->|".db(endpoint)"| Db
DataAPIClient -->|".admin()"| AstraAdmin
Db --->|".collection(name)
.createCollection(name)"| Collection
Db --->|".table(name)
.createTable(name)"| Table
AstraAdmin -->|".dbAdmin(endpoint)
.dbAdmin(id, region)"| DbAdmin
Db -->|".admin()"| DbAdmin
DbAdmin -->|".db()"| Db
Here's a small admin-oriented example:
import { DataAPIClient } from '@datastax/astra-db-ts';
const client = new DataAPIClient('*TOKEN*');
const admin = client.admin();
(async () => {
const databases = await admin.listDatabases();
const dbInfo = databases[0];
console.log(dbInfo.name, dbInfo.id, dbInfo.regions);
const dbAdmin = admin.dbAdmin(dbInfo.id, dbInfo.regions[0].name);
console.log(await dbAdmin.listKeyspaces());
})();
Options hierarchy
Like the client hierarchy, the options for each class also exist in a hierarchy.
The general options for parent classes are deeply merged with the options for child classes.
graph TD
DataAPIClientOptions --> AdminOptions
DataAPIClientOptions --> DbOptions
DbOptions --> CollectionOptions
DbOptions --> TableOptions
Datatypes
See DATATYPES.md for a full list of supported datatypes and their TypeScript equivalents.
Non-astra support
astra-db-ts officially supports Data API instances using non-Astra backends, such as Data API on DSE or HCD.
However, while support is native, detection is not; you will have to manually declare the environment at times.
import { DataAPIClient, UsernamePasswordTokenProvider, DataAPIDbAdmin } from '@datastax/astra-db-ts';
const tp = new UsernamePasswordTokenProvider('*USERNAME*', '*PASSWORD*');
const client = new DataAPIClient(tp, { environment: 'dse' });
const db = client.db('*ENDPOINT*');
const dbAdmin = db.admin({ environment: 'dse' });
dbAdmin.createKeyspace('...', { updateDbKeyspace: true });
The TokenProvider class is an extensible concept to allow you to create or even refresh your tokens
as necessary, depending on the Data API backend. Tokens may even be omitted if necessary.
astra-db-ts provides two TokenProvider instances by default:
StaticTokenProvider - This unit provider simply regurgitates whatever token was passed into its constructor
UsernamePasswordTokenProvider - Turns a user/pass pair into an appropriate token for DSE/HCD
(See examples/non-astra-backends for a full example of this in action.)
Browser support
astra-db-ts is designed to work in server-side environments, but it can technically work in the browser as well.
However, if, for some reason, you really want to use this in a browser, you may need to install the events polyfill,
and possibly set up a CORS proxy (such as CORS Anywhere) to forward requests to the Data API.
But keep in mind that this may be very insecure, especially if you're hardcoding sensitive data into your client-side
code, as it's trivial for anyone to inspect the code and extract the token (through XSS attacks or otherwise).
See examples/browser for a full example of browser usage in action, and steps on how to use astra-db-ts in your own browser application.
Using HTTP/2
astra-db-ts uses the native fetch API by default, but it can also work with HTTP/2 using the fetch-h2 module.
However, due to compatability reasons, fetch-h2 is no longer dynamically imported by default, and must be provided to the client manually.
Luckily, it is only a couple of easy steps to get HTTP/2 working in your project:
- Install
fetch-h2 by running npm i fetch-h2.
- Provide
fetch-h2 to the client.
import * as fetchH2 from 'fetch-h2';
const client = new DataAPIClient({
httpOptions: {
client: 'fetch-h2',
fetchH2: fetchH2,
},
});
See the using HTTP/2 example for a full example of this in action, and more information on how to use astra-db-ts with HTTP/2.
Examples
Check out the examples directory for more examples on how to use astra-db-ts in your own projects.