Skip to content

Commit 69dc794

Browse files
authored
[BLD] Add test for JS client to check for drift in generated openapi spec (#4298)
## Description of changes This PR prettifies the JS client and adds a test in integration tests to ensure that the openapi spec generated code has not differed from the committed version. ## Test plan *How are these changes tested?* - [ ] Tests pass locally with `pytest` for python, `yarn test` for js, `cargo test` for rust ## Documentation Changes *Are all docstrings for user-facing APIs updated if required? Do we need to make documentation changes in the [docs repository](https://github.com/chroma-core/docs)?*
1 parent 122dfed commit 69dc794

38 files changed

+5998
-3316
lines changed

bin/ts-integration-test.sh

+12-4
Original file line numberDiff line numberDiff line change
@@ -45,17 +45,25 @@ wait_for_server
4545

4646
# Install dependencies
4747
cd clients/js
48-
echo "Installing dependencies..."
49-
pnpm i -g openapi-generator-plus @openapi-generator-plus/typescript-fetch-client-generator
5048

5149
# Generate the JS client
5250
echo "Generating JS client..."
53-
chmod +x genapi.sh
54-
./genapi.sh
51+
pnpm genapi
5552

5653
# Cleanup: kill the server process
5754
kill $SERVER_PID
5855

56+
pnpm prettier
57+
58+
# run git diff and check if packages/chromadb-core/src/generated/ has changed
59+
echo "Checking for changes in generated client..."
60+
if ! git diff --quiet --exit-code packages/chromadb-core/src/generated/; then
61+
echo "Error: Generated JS client has changed. Please commit the changes."
62+
git diff packages/chromadb-core/src/generated/ | cat
63+
exit 1
64+
fi
65+
echo "No changes detected in generated client."
66+
5967
# Install dependencies and run tests
6068
echo "Running tests..."
6169
pnpm -r test --verbose

clients/js/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ This package gives you a JS/TS interface to talk to a backend Chroma DB over RES
1616
There are two packages available for using ChromaDB in your JavaScript/TypeScript projects:
1717

1818
1. **chromadb**: Includes all embedding libraries as bundled dependencies.
19+
1920
- Use this if you want a simple installation without worrying about dependency management.
2021
- Install with: `npm install chromadb` or `pnpm add chromadb`
2122

clients/js/examples/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,4 @@ pnpm dev:client
4646
- The **bundled package** (`chromadb`) includes all embedding libraries as dependencies, making it easier to get started.
4747
- The **client package** (`chromadb-client`) uses peer dependencies, giving you more control over which versions of embedding libraries you use. It also keeps your dependency tree leaner if you only need specific embedding libraries.
4848

49-
Both packages offer identical functionality and API.
49+
Both packages offer identical functionality and API.

clients/js/examples/node/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ This is an example of how to use ChromaDB with Node.js.
1717
This example demonstrates both ChromaDB package options:
1818

1919
1. **chromadb** (Bundled Package): Includes all embedding libraries as dependencies.
20+
2021
- Good for simple projects or when you want everything included.
2122
- Import with: `const chroma = require("chromadb");`
2223

clients/js/examples/node/app-bundled.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -55,5 +55,7 @@ app.get("/", async (req, res) => {
5555
res.send(query);
5656
});
5757
app.listen(3000, function () {
58-
console.log("Example app using bundled chromadb package listening on port 3000!");
59-
});
58+
console.log(
59+
"Example app using bundled chromadb package listening on port 3000!",
60+
);
61+
});

clients/js/examples/node/app-client.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -56,5 +56,7 @@ app.get("/", async (req, res) => {
5656
res.send(query);
5757
});
5858
app.listen(3001, function () {
59-
console.log("Example app using chromadb-client package listening on port 3001!");
60-
});
59+
console.log(
60+
"Example app using chromadb-client package listening on port 3001!",
61+
);
62+
});

clients/js/examples/node/app.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ var chroma = require("chromadb");
88
console.log("Using standard app.js with the bundled chromadb package");
99
console.log("To try the different variants, run:");
1010
console.log(" - pnpm dev:bundled - Uses the bundled chromadb package");
11-
console.log(" - pnpm dev:client - Uses the chromadb-client package with peer dependencies");
11+
console.log(
12+
" - pnpm dev:client - Uses the chromadb-client package with peer dependencies",
13+
);
1214

1315
var app = express();
1416
app.get("/", async (req, res) => {

clients/js/packages/chromadb-client/README.md

+7-4
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,10 @@ const collection = await chroma.createCollection({ name: "my-collection" });
5353
// Add documents to the collection
5454
await collection.add({
5555
ids: ["id1", "id2"],
56-
embeddings: [[1.1, 2.3, 3.2], [4.5, 6.9, 4.4]],
56+
embeddings: [
57+
[1.1, 2.3, 3.2],
58+
[4.5, 6.9, 4.4],
59+
],
5760
metadatas: [{ source: "doc1" }, { source: "doc2" }],
5861
documents: ["Document 1 content", "Document 2 content"],
5962
});
@@ -75,13 +78,13 @@ import { ChromaClient, OpenAIEmbeddingFunction } from "chromadb-client";
7578

7679
const embedder = new OpenAIEmbeddingFunction({
7780
openai_api_key: "your-api-key",
78-
model_name: "text-embedding-ada-002"
81+
model_name: "text-embedding-ada-002",
7982
});
8083

8184
const chroma = new ChromaClient({ path: "http://localhost:8000" });
8285
const collection = await chroma.createCollection({
8386
name: "my-collection",
84-
embeddingFunction: embedder
87+
embeddingFunction: embedder,
8588
});
8689

8790
// Now you can add documents without providing embeddings
@@ -125,4 +128,4 @@ This package supports multiple embedding providers as peer dependencies:
125128

126129
## License
127130

128-
Apache 2.0
131+
Apache 2.0

clients/js/packages/chromadb-client/jest.config.ts

+9-6
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,19 @@ export default {
55
collectCoverage: false,
66
testTimeout: 15000,
77
transform: {
8-
"^.+\\.(ts|tsx)$": ["ts-jest", {
9-
tsconfig: "tsconfig.json"
10-
}]
8+
"^.+\\.(ts|tsx)$": [
9+
"ts-jest",
10+
{
11+
tsconfig: "tsconfig.json",
12+
},
13+
],
1114
},
1215
collectCoverageFrom: [
1316
"./src/**/*.{js,ts}",
1417
"!**/node_modules/**",
1518
"!**/vendor/**",
1619
],
1720
moduleNameMapper: {
18-
"@internal/chromadb-core": "<rootDir>/../chromadb-core/src"
19-
}
20-
};
21+
"@internal/chromadb-core": "<rootDir>/../chromadb-core/src",
22+
},
23+
};

clients/js/packages/chromadb-client/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -76,4 +76,4 @@
7676
"engines": {
7777
"node": ">=14.17.0"
7878
}
79-
}
79+
}
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
2-
import * as punycode from 'punycode';
1+
import * as punycode from "punycode";
32
globalThis.punycode = punycode;
4-
export * from './index';
3+
export * from "./index";
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
/**
22
* Re-exports all functionality from the core package
33
*/
4-
export * from '@internal/chromadb-core';
4+
export * from "@internal/chromadb-core";
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// This shim provides punycode functionality to prevent dynamic require errors
2-
import punycode from 'punycode';
2+
import punycode from "punycode";
33

44
// Add to globalThis to make it available for dynamic requires
55
globalThis.punycode = punycode;
66

77
// Export punycode directly
8-
export default punycode;
8+
export default punycode;

clients/js/packages/chromadb-client/test/basic.test.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { describe, it, expect } from "@jest/globals";
22
import { ChromaClient } from "../src";
33

4-
54
describe("ChromaDB Client Integration", () => {
65
it("should properly import and instantiate ChromaClient", () => {
76
const client = new ChromaClient();
@@ -15,4 +14,4 @@ describe("ChromaDB Client Integration", () => {
1514
// We're just verifying the client initializes correctly with options
1615
expect(client).toBeDefined();
1716
});
18-
});
17+
});

clients/js/packages/chromadb-client/tsup.config.ts

+13-10
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,16 @@ export default defineConfig((options: Options) => {
1010
dts: true,
1111
target: "es2020",
1212
// Only bundle the core, keep embedding packages as external
13-
noExternal: ['@internal/chromadb-core', 'isomorphic-fetch', 'cliui'],
13+
noExternal: ["@internal/chromadb-core", "isomorphic-fetch", "cliui"],
1414
// Ensure all embedding packages remain external
1515
external: [
16-
'@google/generative-ai',
17-
'@xenova/transformers',
18-
'chromadb-default-embed',
19-
'cohere-ai',
20-
'openai',
21-
'voyageai',
22-
'ollama'
16+
"@google/generative-ai",
17+
"@xenova/transformers",
18+
"chromadb-default-embed",
19+
"cohere-ai",
20+
"openai",
21+
"voyageai",
22+
"ollama",
2323
],
2424
...options,
2525
};
@@ -32,7 +32,10 @@ export default defineConfig((options: Options) => {
3232
clean: true,
3333
async onSuccess() {
3434
// Support Webpack 4 by pointing `"module"` to a file with a `.js` extension
35-
fs.copyFileSync("dist/chromadb-client.mjs", "dist/chromadb-client.legacy-esm.js");
35+
fs.copyFileSync(
36+
"dist/chromadb-client.mjs",
37+
"dist/chromadb-client.legacy-esm.js",
38+
);
3639
},
3740
},
3841
{
@@ -42,4 +45,4 @@ export default defineConfig((options: Options) => {
4245
outExtension: () => ({ js: ".cjs" }),
4346
},
4447
];
45-
});
48+
});

clients/js/packages/chromadb-core/jest.config.ts

+9-8
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,12 @@ export default {
1010
coverageDirectory: "./test/coverage",
1111
coverageReporters: ["json", "html", "lcov"],
1212
transform: {
13-
"^.+\\.(ts|tsx)$": ["ts-jest", {
14-
tsconfig: "tsconfig.json"
15-
}]
13+
"^.+\\.(ts|tsx)$": [
14+
"ts-jest",
15+
{
16+
tsconfig: "tsconfig.json",
17+
},
18+
],
1619
},
1720
collectCoverageFrom: [
1821
"./src/**/*.{js,ts}",
@@ -21,9 +24,7 @@ export default {
2124
],
2225
// Make tests find the src modules
2326
moduleNameMapper: {
24-
"^@src/(.*)$": "<rootDir>/src/$1"
27+
"^@src/(.*)$": "<rootDir>/src/$1",
2528
},
26-
testPathIgnorePatterns: [
27-
"node_modules/"
28-
]
29-
};
29+
testPathIgnorePatterns: ["node_modules/"],
30+
};

clients/js/packages/chromadb-core/src/ChromaFetch.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ import { FetchAPI } from "./generated";
1515
function isOfflineError(error: any): boolean {
1616
return Boolean(
1717
(error?.name === "TypeError" || error?.name === "FetchError") &&
18-
(error.message?.includes("fetch failed") ||
19-
error.message?.includes("Failed to fetch") ||
20-
error.message?.includes("ENOTFOUND")),
18+
(error.message?.includes("fetch failed") ||
19+
error.message?.includes("Failed to fetch") ||
20+
error.message?.includes("ENOTFOUND")),
2121
);
2222
}
2323

clients/js/packages/chromadb-core/src/generated/README.md

+12-8
Original file line numberDiff line numberDiff line change
@@ -3,31 +3,35 @@
33
This generator creates TypeScript/JavaScript client that utilizes [Fetch API](https://fetch.spec.whatwg.org/). The generated Node module can be used in the following environments:
44

55
Environment
6-
* Node.js
7-
* Webpack
8-
* Browserify
6+
7+
- Node.js
8+
- Webpack
9+
- Browserify
910

1011
Language level
11-
* ES5 - you must have a Promises/A+ library installed
12-
* ES6
12+
13+
- ES5 - you must have a Promises/A+ library installed
14+
- ES6
1315

1416
Module system
15-
* CommonJS
16-
* ES6 module system
17+
18+
- CommonJS
19+
- ES6 module system
1720

1821
It can be used in both TypeScript and JavaScript. In TypeScript, the definition should be automatically resolved via `package.json`. ([Reference](http://www.typescriptlang.org/docs/handbook/typings-for-npm-packages.html))
1922

2023
### Building
2124

2225
To build an compile the typescript sources to javascript use:
26+
2327
```
2428
npm install
2529
npm run build
2630
```
2731

2832
### Publishing
2933

30-
First build the package then run ```npm publish```
34+
First build the package then run `npm publish`
3135

3236
### Consuming
3337

clients/js/packages/chromadb-core/src/schemas/schemaUtils.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,9 @@ export function getSchemaVersion(schemaName: keyof typeof schemaMap): string {
126126
* @returns A list of schema names (without .json extension)
127127
*/
128128
export function getAvailableSchemas(): (keyof typeof schemaMap)[] {
129-
return Object.keys(schemaMap).filter((name) => name !== "base_schema") as (keyof typeof schemaMap)[];
129+
return Object.keys(schemaMap).filter(
130+
(name) => name !== "base_schema",
131+
) as (keyof typeof schemaMap)[];
130132
}
131133

132134
/**

clients/js/packages/chromadb-core/src/types.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ type WhereOperator = "$gt" | "$gte" | "$lt" | "$lte" | "$ne" | "$eq";
3232

3333
type OperatorExpression = {
3434
[key in WhereOperator | InclusionOperator | LogicalOperator]?:
35-
| LiteralValue
36-
| ListLiteralValue;
35+
| LiteralValue
36+
| ListLiteralValue;
3737
};
3838

3939
type BaseWhere = {
@@ -50,9 +50,9 @@ type WhereDocumentOperator = "$contains" | "$not_contains" | LogicalOperator;
5050

5151
export type WhereDocument = {
5252
[key in WhereDocumentOperator]?:
53-
| LiteralValue
54-
| LiteralNumber
55-
| WhereDocument[];
53+
| LiteralValue
54+
| LiteralNumber
55+
| WhereDocument[];
5656
};
5757

5858
export type MultiGetResponse = {

clients/js/packages/chromadb-core/src/utils.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export function toArray<T>(obj: T | T[]): Array<T> {
2323

2424
// a function to convert an array to array of arrays
2525
export function toArrayOfArrays<T>(
26-
obj: Array<Array<T>> | Array<T>
26+
obj: Array<Array<T>> | Array<T>,
2727
): Array<Array<T>> {
2828
if (obj.length === 0) {
2929
return [];
@@ -33,8 +33,8 @@ export function toArrayOfArrays<T>(
3333
return obj as Array<Array<T>>;
3434
}
3535

36-
if (obj[0] && typeof (obj[0] as any)[Symbol.iterator] === 'function') {
37-
return (obj as unknown as Array<Iterable<T>>).map(el => Array.from(el));
36+
if (obj[0] && typeof (obj[0] as any)[Symbol.iterator] === "function") {
37+
return (obj as unknown as Array<Iterable<T>>).map((el) => Array.from(el));
3838
}
3939

4040
return [obj] as Array<Array<T>>;

clients/js/packages/chromadb-core/test/delete.collection.test.ts

+1-6
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,4 @@
1-
import {
2-
beforeEach,
3-
describe,
4-
expect,
5-
test,
6-
} from "@jest/globals";
1+
import { beforeEach, describe, expect, test } from "@jest/globals";
72
import { EMBEDDINGS, IDS, METADATAS } from "./data";
83
import { ChromaClient } from "../src/ChromaClient";
94
import { ChromaNotFoundError } from "../src/Errors";

0 commit comments

Comments
 (0)