Skip to content

Commit f2abb91

Browse files
authored
Updates for v1.3 (#58)
* fixed test broken due to $vector projection change * minor collection.distinct optimzation * minor error msg fix * getSortVector (no documentation) * added some documentation regarding sortVector * updated vectorize test suite * minor fix to vectorize tests when no params * further refactoring of vectorize tests * example vectorize_credentials.json file * removed api-extractor from package.json * added find-missing-licensing script for convenience * tiny vectorize test + devguide updats * dse db admin + fixed some tests (no docs) * fixed typo in package.json script name * minor update to list-embedding-providers script * few internal refactors * more minor refactors * documentation for environments and such * some new unit tests * create namespace options * fixed some documention + code issues * made modelName not fully optional, just allowably nullish * added doc for vectorize service * updated cursor.getSortVector() to return null if includeSortVector !== true * fixed a couple tests * minor internal refactors/fixes * added dse tests * db admin tests * vectorize whitelist * few test fixes + allowed null tokens in StaticTokenProvider * deleteAll() => deleteMany({}) * updated many examples using vector[ize] params * some documentation and such * couple tiny internal fixes * example for non-astra backends * a * fixed couple tiny internal things
1 parent b10da81 commit f2abb91

File tree

95 files changed

+2886
-1057
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

95 files changed

+2886
-1057
lines changed

.env.example

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,24 @@
33
################################################################################
44

55
# Astra API endpoint
6-
ASTRA_URI=https://<db_id>-<region>.apps.astra.datastax.com
6+
APPLICATION_URI=https://<db_id>-<region>.apps.astra.datastax.com
77

88
# Application token, used to authenticate with the Astra API
99
APPLICATION_TOKEN=AstraCS:<rest_of_token>
1010

11+
# Backend for the Data API (astra | dse | hcd | cassandra | other). Defaults to 'astra'.
12+
APPLICATION_ENVIRONMENT=astra
13+
1114
# Set this to some value to enable running tests that require a $vectorize enabled environment
1215
ASTRA_RUN_VECTORIZE_TESTS=1
1316

17+
# Regex whitelist for vectorize tests to run (test names formatted as providerName@modelName@authType@dimension)
18+
# - where dimension := 'specified' | 'default' | a specific number
19+
# - where authType := 'header' | 'providerKey' | 'none'
20+
# Only needs to match part of the test name to whitelist (use ^$ as necessary)
21+
# VECTORIZE_WHITELIST=^.*@(header|none)@default
22+
VECTORIZE_WHITELIST=.*
23+
1424
# Set this to some value to enable running long-running tests
1525
ASTRA_RUN_LONG_TESTS=1
1626

.eslintrc.cjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* eslint-env node */
22
module.exports = {
3-
ignorePatterns: ['dist/*', 'scripts/*'],
3+
ignorePatterns: ['dist/*', 'scripts/*', 'examples/*'],
44
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended'],
55
parser: '@typescript-eslint/parser',
66
plugins: ['@typescript-eslint'],

DEVGUIDE.md

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,23 @@ npm run test -- -f 'integration.'
2424
npm run test:types
2525
```
2626

27+
### Running the tests on local Stargate
28+
You can do `sh scripts/start-stargate-4-tests.sh` to spin up an ephemeral Data API on DSE instance which automatically
29+
creates the required keyspaces and destroys itself on exit.
30+
31+
Then, be sure to set the following vars in `.env` exactly, then run the tests as usual.
32+
```dotenv
33+
APPLICATION_URI=http://localhost:8181
34+
APPLICATION_TOKEN=Cassandra:Y2Fzc2FuZHJh:Y2Fzc2FuZHJh
35+
APPLICATION_ENVIRONMENT=dse
36+
```
37+
2738
### Running tagged tests
2839
Tests can be given certain tags to allow for more granular control over which tests are run. These tags currently include:
2940
- `[long]`/`'LONG'`: Longer running tests that take more than a few seconds to run
3041
- `[admin]`/`'ADMIN'`: Tests that require admin permissions to run
3142
- `[dev]`/`'DEV'`: Tests that require the dev environment to run
32-
- `[prod]`/`'PROD'`: Tests that require the dev environment to run
43+
- `[not-dev]`/`'NOT-DEV'`: Tests that require the dev environment to run
3344
- `[vectorize]`/`'VECTORIZE'`: Tests that require a specific vectorize-enabled kube to run
3445

3546
To enable these some of these tags, you can set the corresponding environment variables to some values. The env
@@ -77,28 +88,36 @@ To run vectorize tests, you need to have a vectorize-enabled kube running, with
7788
You must create a file, `vectorize_tests.json`, in the root folder, with the following format:
7889

7990
```ts
80-
interface Config {
91+
interface VectorizeTestSpec {
8192
[providerName: string]: {
8293
apiKey?: string,
8394
providerKey?: string,
95+
dimension?: {
96+
[modelNameRegex: string]: number,
97+
},
8498
parameters?: {
85-
[modelName: string]: Record<string, string>
99+
[modelNameRegex: string]: Record<string, string>
86100
},
87101
}
88102
}
89103
```
90104

91105
where:
92-
- `providerName` is the name of the provider (e.g. `nvidia`, `openai`, etc.) as found in `findEmbeddingProviders`
93-
- `apiKey` is the API key for the provider (which will be passed in through the header)
94-
- optional if no header auth test wanted
95-
- `providerKey` is the provider key for the provider (which will be passed in @ collection creation)
96-
- optional if no KMS auth test wanted
97-
- `parameters` is a mapping of model names to their corresponding parameters
106+
- `providerName` is the name of the provider (e.g. `nvidia`, `openai`, etc.) as found in `findEmbeddingProviders`.
107+
- `apiKey` is the API key for the provider (which will be passed in through the header) .
108+
- optional if no header auth test wanted.
109+
- `providerKey` is the provider key for the provider (which will be passed in @ collection creation) .
110+
- optional if no KMS auth test wanted.
111+
- `parameters` is a mapping of model names to their corresponding parameters. The model name can be some regex that partially matches the full model name.
112+
- `"text-embedding-3-small"`, `"3-small"`, and `".*"` will all match `"text-embedding-3-small"`.
98113
- optional if not required. `azureOpenAI`, for example, will need this.
114+
- `dimension` is a also a mapping of model name regex to their corresponding dimensions, like the `parameters` field.
115+
- optional if not required. `huggingfaceDedicated`, for example, will need this.
99116

100117
This file is gitignored by default and will not be checked into VCS.
101118

119+
See `vectorize_credentials.example.json` for—guess what—an example.
120+
102121
### Coverage testing
103122

104123
To run coverage testing, run the following command:

README.md

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
- [Working with Dates](#working-with-dates)
1212
- [Working with ObjectIds and UUIDs](#working-with-objectids-and-uuids)
1313
- [Monitoring/logging](#monitoringlogging)
14+
- [Non-astra support](#non-astra-support)
1415
- [Non-standard environment support](#non-standard-environment-support)
1516
- [HTTP/2 with minification](#http2-with-minification)
1617
- [Browser support](#browser-support)
@@ -41,7 +42,7 @@ const db = client.db('*ENDPOINT*', { namespace: '*NAMESPACE*' });
4142
const collection = await db.createCollection<Idea>('vector_5_collection', {
4243
vector: {
4344
dimension: 5,
44-
metric: 'cosine'
45+
metric: 'cosine',
4546
},
4647
checkExists: false,
4748
});
@@ -334,6 +335,35 @@ client.on('commandFailed', (event) => {
334335
})();
335336
```
336337

338+
## Non-astra support
339+
340+
`astra-db-ts` officially supports Data API instances using non-Astra backends, such as Data API on DSE or HCD.
341+
342+
However, while support is native, detection is not; you will have to manually declare the environment at times.
343+
344+
```typescript
345+
import { DataAPIClient, UsernamePasswordTokenProvider, DataAPIDbAdmin } from '@datastax/astra-db-ts';
346+
347+
// You'll need to pass in environment to the DataAPIClient when not using Astra
348+
const tp = new UsernamePasswordTokenProvider('*USERNAME*', '*PASSWORD*');
349+
const client = new DataAPIClient(tp, { environment: 'dse' });
350+
const db = client.db('*ENDPOINT*');
351+
352+
// You'll also need to pass it to db.admin() when not using Astra for typing purposes
353+
// If the environment does not match, an error will be thrown as a reminder
354+
const dbAdmin: DataAPIDbAdmin = db.admin({ environment: 'dse' });
355+
dbAdmin.createNamespace(...);
356+
```
357+
358+
The `TokenProvider` class is an extensible concept to allow you to create or even refresh your tokens
359+
as necessary, depending on the Data API backend. Tokens may even be omitted if necessary.
360+
361+
`astra-db-ts` provides two `TokenProvider` instances by default:
362+
- `StaticTokenProvider` - This unit provider simply regurgitates whatever token was passed into its constructor
363+
- `UsernamePasswordTokenProvider` - Turns a user/pass pair into an appropriate token for DSE/HCD
364+
365+
(See `examples/non-astra-backends` for a full example of this in action.)
366+
337367
## Non-standard environment support
338368

339369
`astra-db-ts` is designed foremost to work in Node.js environments.

api-extractor.jsonc

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,12 @@
402402
// "addToApiReportFile": false
403403
},
404404

405-
"ae-internal-missing-underscore": {
405+
// "ae-internal-missing-underscore": {
406+
// "logLevel": "none",
407+
// "addToApiReportFile": false
408+
// }
409+
410+
"ae-unresolved-link": {
406411
"logLevel": "none",
407412
"addToApiReportFile": false
408413
}

etc/astra-db-ts.api.md

Lines changed: 56 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ export class AstraAdmin {
101101
// Warning: (ae-forgotten-export) The symbol "InternalRootClientOpts" needs to be exported by the entry point index.d.ts
102102
//
103103
// @internal
104-
constructor(options: InternalRootClientOpts);
104+
constructor(rootOpts: InternalRootClientOpts, adminOpts?: AdminSpawnOptions);
105105
createDatabase(config: DatabaseConfig, options?: CreateDatabaseOptions): Promise<AstraDbAdmin>;
106106
db(endpoint: string, options?: DbSpawnOptions): Db;
107107
db(id: string, region: string, options?: DbSpawnOptions): Db;
@@ -115,7 +115,7 @@ export class AstraAdmin {
115115
// @public
116116
export class AstraDbAdmin extends DbAdmin {
117117
// @internal
118-
constructor(_db: Db, options: InternalRootClientOpts);
118+
constructor(db: Db, rootOpts: InternalRootClientOpts, adminOpts?: AdminSpawnOptions);
119119
createNamespace(namespace: string, options?: AdminBlockingOptions): Promise<void>;
120120
db(): Db;
121121
drop(options?: AdminBlockingOptions): Promise<void>;
@@ -177,6 +177,7 @@ export class Collection<Schema extends SomeDoc = SomeDoc> {
177177
bulkWrite(operations: AnyBulkWriteOperation<Schema>[], options?: BulkWriteOptions): Promise<BulkWriteResult<Schema>>;
178178
readonly collectionName: string;
179179
countDocuments(filter: Filter<Schema>, upperBound: number, options?: WithTimeout): Promise<number>;
180+
// @deprecated
180181
deleteAll(options?: WithTimeout): Promise<void>;
181182
deleteMany(filter?: Filter<Schema>, options?: WithTimeout): Promise<DeleteManyResult>;
182183
deleteOne(filter?: Filter<Schema>, options?: DeleteOneOptions): Promise<DeleteOneResult>;
@@ -298,6 +299,11 @@ export type CreateDatabaseOptions = AdminBlockingOptions & {
298299
dbOptions?: DbSpawnOptions;
299300
};
300301

302+
// @public
303+
export type CreateNamespaceOptions = AdminBlockingOptions & {
304+
replication?: NamespaceReplicationOptions;
305+
};
306+
301307
// @public
302308
export abstract class CumulativeDataAPIError extends DataAPIResponseError {
303309
readonly partialResult: unknown;
@@ -348,6 +354,7 @@ export interface DataAPIClientOptions {
348354
adminOptions?: AdminSpawnOptions;
349355
caller?: Caller | Caller[];
350356
dbOptions?: DbSpawnOptions;
357+
environment?: DataAPIEnvironment;
351358
httpOptions?: DataAPIHttpOptions;
352359
// @deprecated
353360
preferHttp2?: boolean;
@@ -360,13 +367,29 @@ export type DataAPICommandEvents = {
360367
commandFailed: (event: CommandFailedEvent) => void;
361368
};
362369

370+
// @public
371+
export class DataAPIDbAdmin extends DbAdmin {
372+
// @internal
373+
constructor(db: Db, httpClient: DataAPIHttpClient, adminOpts?: AdminSpawnOptions);
374+
createNamespace(namespace: string, options?: CreateNamespaceOptions): Promise<void>;
375+
db(): Db;
376+
dropNamespace(namespace: string, options?: AdminBlockingOptions): Promise<void>;
377+
listNamespaces(options?: WithTimeout): Promise<string[]>;
378+
}
379+
363380
// @public
364381
export interface DataAPIDetailedErrorDescriptor {
365382
readonly command: Record<string, any>;
366383
readonly errorDescriptors: DataAPIErrorDescriptor[];
367384
readonly rawResponse: RawDataAPIResponse;
368385
}
369386

387+
// @public
388+
export type DataAPIEnvironment = typeof DataAPIEnvironments[number];
389+
390+
// @public
391+
export const DataAPIEnvironments: readonly ["astra", "dse", "hcd", "cassandra", "other"];
392+
370393
// @public
371394
export abstract class DataAPIError extends Error {
372395
}
@@ -483,8 +506,13 @@ export type DateUpdate<Schema> = {
483506
// @public
484507
export class Db {
485508
// @internal
486-
constructor(endpoint: string, options: InternalRootClientOpts);
487-
admin(options?: AdminSpawnOptions): AstraDbAdmin;
509+
constructor(endpoint: string, rootOpts: InternalRootClientOpts, dbOpts: DbSpawnOptions | nullish);
510+
admin(options?: AdminSpawnOptions & {
511+
environment?: 'astra';
512+
}): AstraDbAdmin;
513+
admin(options: AdminSpawnOptions & {
514+
environment: Exclude<DataAPIEnvironment, 'astra'>;
515+
}): DataAPIDbAdmin;
488516
collection<Schema extends SomeDoc = SomeDoc>(name: string, options?: CollectionSpawnOptions): Collection<Schema>;
489517
collections(options?: WithNamespace & WithTimeout): Promise<Collection[]>;
490518
command(command: Record<string, any>, options?: RunCommandOptions): Promise<RawDataAPIResponse>;
@@ -613,12 +641,6 @@ export class DevOpsUnexpectedStateError extends DevOpsAPIError {
613641
export interface DropCollectionOptions extends WithTimeout, WithNamespace {
614642
}
615643

616-
// @public
617-
export class DSEUsernamePasswordTokenProvider extends TokenProvider {
618-
constructor(username: string, password: string);
619-
getTokenAsString(): Promise<string>;
620-
}
621-
622644
// @public
623645
export class FailedToLoadDefaultClientError extends Error {
624646
// @internal
@@ -699,8 +721,10 @@ export class FindCursor<T, TRaw extends SomeDoc = SomeDoc> {
699721
filter(filter: Filter<TRaw>): this;
700722
// @deprecated
701723
forEach(consumer: ((doc: T) => boolean) | ((doc: T) => void)): Promise<void>;
724+
getSortVector(): Promise<number[] | null>;
702725
hasNext(): Promise<boolean>;
703726
includeSimilarity(includeSimilarity?: boolean): this;
727+
includeSortVector(includeSortVector?: boolean): this;
704728
limit(limit: number): this;
705729
map<R>(mapping: (doc: T) => R): FindCursor<R, TRaw>;
706730
get namespace(): string;
@@ -764,6 +788,7 @@ export interface FindOneOptions extends WithTimeout {
764788
// @public
765789
export interface FindOptions {
766790
includeSimilarity?: boolean;
791+
includeSortVector?: boolean;
767792
limit?: number;
768793
projection?: Projection;
769794
skip?: number;
@@ -921,6 +946,15 @@ export interface ModifyResult<Schema extends SomeDoc> {
921946
value: WithId<Schema> | null;
922947
}
923948

949+
// @public
950+
export type NamespaceReplicationOptions = {
951+
class: 'SimpleStrategy';
952+
replicationFactor: number;
953+
} | {
954+
class: 'NetworkTopologyStrategy';
955+
[datacenter: string]: number | 'NetworkTopologyStrategy';
956+
};
957+
924958
// @public
925959
export interface NoBlockingOptions extends WithTimeout {
926960
blocking: false;
@@ -1041,8 +1075,8 @@ export type SortDirection = 1 | -1 | 'asc' | 'desc' | 'ascending' | 'descending'
10411075

10421076
// @public
10431077
export class StaticTokenProvider extends TokenProvider {
1044-
constructor(token: string);
1045-
getTokenAsString(): Promise<string>;
1078+
constructor(token: string | nullish);
1079+
getToken(): Promise<string | nullish>;
10461080
}
10471081

10481082
// @public
@@ -1134,9 +1168,9 @@ export type ToDotNotation<Schema extends SomeDoc> = Merge<_ToDotNotation<Schema,
11341168

11351169
// @public
11361170
export abstract class TokenProvider {
1137-
abstract getTokenAsString(): Promise<string>;
1171+
abstract getToken(): Promise<string | nullish>;
11381172
// @internal
1139-
static parseToken(token: unknown): TokenProvider | nullish;
1173+
static parseToken(token: unknown): TokenProvider;
11401174
}
11411175

11421176
// @public
@@ -1219,6 +1253,12 @@ export interface UpsertedUpdateOptions<Schema extends SomeDoc> {
12191253
upsertedId: IdOf<Schema>;
12201254
}
12211255

1256+
// @public
1257+
export class UsernamePasswordTokenProvider extends TokenProvider {
1258+
constructor(username: string, password: string);
1259+
getToken(): Promise<string>;
1260+
}
1261+
12221262
// @public
12231263
export class UUID {
12241264
constructor(uuid: string, validate?: boolean);
@@ -1244,10 +1284,10 @@ export interface VectorizeDoc {
12441284
$vectorize: string;
12451285
}
12461286

1247-
// @alpha
1287+
// @public
12481288
export interface VectorizeServiceOptions {
12491289
authentication?: Record<string, string | undefined>;
1250-
modelName: string;
1290+
modelName: string | nullish;
12511291
parameters?: Record<string, unknown>;
12521292
provider: string;
12531293
}

0 commit comments

Comments
 (0)