From 5c026e839f5b55a1b1670f32f974a96705ebe69f Mon Sep 17 00:00:00 2001 From: Tushar Sonawane <tusharlsonawane@gmail.com> Date: Fri, 21 Feb 2025 14:53:50 +0530 Subject: [PATCH] feat(vectorstore): adds firestore vector store support (#1600) --- .changeset/lemon-pumas-end.md | 5 + examples/firestore/.env.template | 4 + examples/firestore/README.md | 35 +++ examples/firestore/delete.ts | 32 ++ examples/firestore/load.ts | 44 +++ examples/firestore/query.ts | 58 ++++ examples/package.json | 1 + .../providers/storage/firestore/CHANGELOG.md | 0 .../providers/storage/firestore/package.json | 48 +++ .../firestore/src/FirestoreVectorStore.ts | 273 ++++++++++++++++++ .../providers/storage/firestore/src/index.ts | 1 + .../providers/storage/firestore/tsconfig.json | 19 ++ pnpm-lock.yaml | 170 ++++++++++- tsconfig.json | 3 + 14 files changed, 691 insertions(+), 2 deletions(-) create mode 100644 .changeset/lemon-pumas-end.md create mode 100644 examples/firestore/.env.template create mode 100644 examples/firestore/README.md create mode 100644 examples/firestore/delete.ts create mode 100644 examples/firestore/load.ts create mode 100644 examples/firestore/query.ts create mode 100644 packages/providers/storage/firestore/CHANGELOG.md create mode 100644 packages/providers/storage/firestore/package.json create mode 100644 packages/providers/storage/firestore/src/FirestoreVectorStore.ts create mode 100644 packages/providers/storage/firestore/src/index.ts create mode 100644 packages/providers/storage/firestore/tsconfig.json diff --git a/.changeset/lemon-pumas-end.md b/.changeset/lemon-pumas-end.md new file mode 100644 index 000000000..b4318ae9f --- /dev/null +++ b/.changeset/lemon-pumas-end.md @@ -0,0 +1,5 @@ +--- +"@llamaindex/firestore": major +--- + +Firestore vector store support for LlamaIndex diff --git a/examples/firestore/.env.template b/examples/firestore/.env.template new file mode 100644 index 000000000..03bdb03de --- /dev/null +++ b/examples/firestore/.env.template @@ -0,0 +1,4 @@ +GCP_PROJECT_ID= +GCP_CREDENTIALS= +FIRESTORE_DB= +OPENAI_API_KEY= \ No newline at end of file diff --git a/examples/firestore/README.md b/examples/firestore/README.md new file mode 100644 index 000000000..22764c2c3 --- /dev/null +++ b/examples/firestore/README.md @@ -0,0 +1,35 @@ +# Firestore Vector Store + +Here are some sample scripts which work with loading and querying data from a Firestore Vector Store. + +## Prerequisites + +- A Firestore Database + - Hosted https://console.firebase.google.com/ +- An OpenAI API Key + +## Setup + +1. Set your env variables: + +- `FIRESTORE_DB`: Name of your Firestore database +- `GCP_PROJECT_ID`: Your GCP project ID +- `GCP_CREDENTIALS`: Your GCP credentials JSON +- `OPENAI_API_KEY`: Your OpenAI key + +2. `cd` Into the `examples` directory +3. run `npm i` + +## Load the data + +This sample loads the same dataset of movie reviews as sample dataset + +run `npx tsx firestore/load.ts` + +## Use RAG to Query the data + +run `npx tsx firestore/query.ts` + +## Delete the data + +run `npx tsx firestore/delete.ts` diff --git a/examples/firestore/delete.ts b/examples/firestore/delete.ts new file mode 100644 index 000000000..6a6e1b07e --- /dev/null +++ b/examples/firestore/delete.ts @@ -0,0 +1,32 @@ +import { CollectionReference } from "@google-cloud/firestore"; +import "dotenv/config"; + +import { FirestoreVectorStore } from "@llamaindex/firestore"; +import { OpenAIEmbedding, Settings } from "llamaindex"; + +const indexName = "MovieReviews"; + +Settings.embedModel = new OpenAIEmbedding(); + +async function main() { + try { + const vectorStore = new FirestoreVectorStore({ + clientOptions: { + credentials: JSON.parse(process.env.GCP_CREDENTIALS!), + projectId: process.env.GCP_PROJECT_ID!, + databaseId: process.env.FIRESTORE_DB!, + ignoreUndefinedProperties: true, + }, + collectionName: indexName, + customCollectionReference: (rootCollection: CollectionReference) => { + return rootCollection.doc("accountId-123").collection("vectors"); + }, + }); + + vectorStore.delete("movie_reviews.csv"); + } catch (e) { + console.error(e); + } +} + +void main(); diff --git a/examples/firestore/load.ts b/examples/firestore/load.ts new file mode 100644 index 000000000..9a04fc5c9 --- /dev/null +++ b/examples/firestore/load.ts @@ -0,0 +1,44 @@ +import { CollectionReference } from "@google-cloud/firestore"; +import { CSVReader } from "@llamaindex/readers/csv"; +import "dotenv/config"; + +import { + OpenAIEmbedding, + Settings, + storageContextFromDefaults, + VectorStoreIndex, +} from "llamaindex"; + +import { FirestoreVectorStore } from "@llamaindex/firestore"; + +const indexName = "MovieReviews"; + +Settings.embedModel = new OpenAIEmbedding(); + +async function main() { + try { + const reader = new CSVReader(false); + const docs = await reader.loadData("./data/movie_reviews.csv"); + + const vectorStore = new FirestoreVectorStore({ + clientOptions: { + credentials: JSON.parse(process.env.GCP_CREDENTIALS!), + projectId: process.env.GCP_PROJECT_ID!, + databaseId: process.env.FIRESTORE_DB!, + ignoreUndefinedProperties: true, + }, + collectionName: indexName, + customCollectionReference: (rootCollection: CollectionReference) => { + return rootCollection.doc("accountId-123").collection("vectors"); + }, + }); + + const storageContext = await storageContextFromDefaults({ vectorStore }); + + await VectorStoreIndex.fromDocuments(docs, { storageContext }); + } catch (e) { + console.error(e); + } +} + +void main(); diff --git a/examples/firestore/query.ts b/examples/firestore/query.ts new file mode 100644 index 000000000..30a6d53ce --- /dev/null +++ b/examples/firestore/query.ts @@ -0,0 +1,58 @@ +import "dotenv/config"; + +import { OpenAIEmbedding, Settings, VectorStoreIndex } from "llamaindex"; + +import { CollectionReference } from "@google-cloud/firestore"; +import { FirestoreVectorStore } from "@llamaindex/firestore"; + +const indexName = "MovieReviews"; + +Settings.embedModel = new OpenAIEmbedding(); + +async function main() { + try { + const vectorStore = new FirestoreVectorStore({ + clientOptions: { + credentials: JSON.parse(process.env.GCP_CREDENTIALS!), + projectId: process.env.GCP_PROJECT_ID!, + databaseId: process.env.FIRESTORE_DB!, + ignoreUndefinedProperties: true, + }, + collectionName: indexName, + customCollectionReference: (rootCollection: CollectionReference) => { + return rootCollection.doc("accountId-123").collection("vectors"); + }, + }); + const index = await VectorStoreIndex.fromVectorStore(vectorStore); + const retriever = index.asRetriever({ similarityTopK: 20 }); + + const queryEngine = index.asQueryEngine({ retriever }); + const query = "Get all movie titles."; + const results = await queryEngine.query({ query }); + console.log(`Query from ${results.sourceNodes?.length} nodes`); + console.log(results.response); + + console.log("\n=====\nQuerying the index with filters"); + const queryEngineWithFilters = index.asQueryEngine({ + retriever, + preFilters: { + filters: [ + { + key: "file_name", + value: "movie_reviews.csv", + operator: "==", + }, + ], + }, + }); + const resultAfterFilter = await queryEngineWithFilters.query({ + query: "Get all movie titles.", + }); + console.log(`Query from ${resultAfterFilter.sourceNodes?.length} nodes`); + console.log(resultAfterFilter.response); + } catch (e) { + console.error(e); + } +} + +void main(); diff --git a/examples/package.json b/examples/package.json index 97db00b43..3ddfbcc85 100644 --- a/examples/package.json +++ b/examples/package.json @@ -21,6 +21,7 @@ "@llamaindex/core": "^0.5.1", "@llamaindex/deepinfra": "^0.0.37", "@llamaindex/env": "^0.1.28", + "@llamaindex/firestore": "^0.0.1", "@llamaindex/google": "^0.0.8", "@llamaindex/groq": "^0.0.52", "@llamaindex/huggingface": "^0.0.37", diff --git a/packages/providers/storage/firestore/CHANGELOG.md b/packages/providers/storage/firestore/CHANGELOG.md new file mode 100644 index 000000000..e69de29bb diff --git a/packages/providers/storage/firestore/package.json b/packages/providers/storage/firestore/package.json new file mode 100644 index 000000000..ea7e8d850 --- /dev/null +++ b/packages/providers/storage/firestore/package.json @@ -0,0 +1,48 @@ +{ + "name": "@llamaindex/firestore", + "description": "Firestore Storage for LlamaIndex", + "version": "0.0.1", + "type": "module", + "main": "./dist/index.cjs", + "module": "./dist/index.js", + "exports": { + ".": { + "edge-light": { + "types": "./dist/index.edge-light.d.ts", + "default": "./dist/index.edge-light.js" + }, + "workerd": { + "types": "./dist/index.edge-light.d.ts", + "default": "./dist/index.edge-light.js" + }, + "require": { + "types": "./dist/index.d.cts", + "default": "./dist/index.cjs" + }, + "import": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + } + } + }, + "files": [ + "dist" + ], + "repository": { + "type": "git", + "url": "git+https://github.com/run-llama/LlamaIndexTS.git", + "directory": "packages/providers/storage/firestore" + }, + "scripts": { + "build": "bunchee", + "dev": "bunchee --watch" + }, + "devDependencies": { + "bunchee": "6.3.4" + }, + "dependencies": { + "@llamaindex/core": "workspace:*", + "@llamaindex/env": "workspace:*", + "@google-cloud/firestore": "^7.11.0" + } +} diff --git a/packages/providers/storage/firestore/src/FirestoreVectorStore.ts b/packages/providers/storage/firestore/src/FirestoreVectorStore.ts new file mode 100644 index 000000000..31a357616 --- /dev/null +++ b/packages/providers/storage/firestore/src/FirestoreVectorStore.ts @@ -0,0 +1,273 @@ +import { + CollectionReference, + FieldValue, + Filter, + Firestore, + type Settings, + type VectorQuery, + type WhereFilterOp, +} from "@google-cloud/firestore"; +import type { BaseNode, Metadata } from "@llamaindex/core/schema"; +import { + BaseVectorStore, + FilterOperator, + metadataDictToNode, + nodeToMetadata, + type MetadataFilter, + type MetadataFilters, + type VectorStoreBaseParams, + type VectorStoreQuery, + type VectorStoreQueryResult, +} from "@llamaindex/core/vector-store"; + +enum DistanceMeasure { + COSINE = "COSINE", + EUCLIDEAN = "EUCLIDEAN", + DOT_PRODUCT = "DOT_PRODUCT", +} + +type FirestoreParams = { + collectionName: string; + client?: Firestore; + clientOptions?: { + credentials: Settings["credentials"]; + projectId: string; + databaseId: string; + ignoreUndefinedProperties: boolean; + }; + batchSize?: number; + embeddingKey?: string; + textKey?: string; + metadataKey?: string; + distanceMeasure?: DistanceMeasure; + customCollectionReference?: ( + rootCollection: CollectionReference, + ) => CollectionReference; +} & VectorStoreBaseParams; + +const DEFAULT_BATCH_SIZE = 500; + +function toFirestoreOperator(operator: FilterOperator): WhereFilterOp { + const operatorMap: Record<FilterOperator, WhereFilterOp> = { + [FilterOperator.EQ]: "==", + [FilterOperator.NE]: "!=", + [FilterOperator.GT]: ">", + [FilterOperator.GTE]: ">=", + [FilterOperator.LT]: "<", + [FilterOperator.LTE]: "<=", + [FilterOperator.IN]: "in", + [FilterOperator.NIN]: "not-in", + [FilterOperator.CONTAINS]: "array-contains", + [FilterOperator.TEXT_MATCH]: "==", + [FilterOperator.ANY]: "array-contains-any", + [FilterOperator.ALL]: "array-contains", + [FilterOperator.IS_EMPTY]: "==", + }; + + const firestoreOp = operatorMap[operator]; + if (!firestoreOp) { + throw new Error(`Operator ${operator} not supported in Firestore.`); + } + return firestoreOp; +} + +function toFirestoreFilter(filters: MetadataFilters): Filter | undefined { + if (!filters?.filters?.length) return undefined; + + const firestoreFilters = filters.filters.map((filter: MetadataFilter) => { + const path = `${filter.key}`; + const operator = toFirestoreOperator(filter.operator as FilterOperator); + return Filter.where(path, operator, filter.value); + }); + + if (firestoreFilters.length === 1) { + return firestoreFilters[0]; + } + + return filters.condition === "or" + ? Filter.or(...firestoreFilters) + : Filter.and(...firestoreFilters); +} + +export class FirestoreVectorStore extends BaseVectorStore<Firestore> { + storesText: boolean = true; + isEmbeddingQuery?: boolean = false; + flatMetadata: boolean = true; + + private firestoreClient: Firestore; + private collectionName: string; + private batchSize: number; + private embeddingKey: string = "embedding"; + private metadataKey: string = "metadata"; + private distanceMeasure: DistanceMeasure = DistanceMeasure.COSINE; + private customCollectionReference: ( + rootCollection: CollectionReference, + ) => CollectionReference; + + constructor({ + collectionName = "vector_store", + client, + clientOptions, + batchSize = DEFAULT_BATCH_SIZE, + distanceMeasure = DistanceMeasure.COSINE, + customCollectionReference, + ...init + }: FirestoreParams) { + super(init); + this.collectionName = collectionName; + this.batchSize = batchSize; + this.distanceMeasure = distanceMeasure; + this.customCollectionReference = + customCollectionReference ?? ((rootCollection) => rootCollection); + + if (client) { + this.firestoreClient = client; + } else { + if (!clientOptions) { + throw new Error("clientOptions are required"); + } + if (!clientOptions.credentials) { + throw new Error("clientOptions.credentials are required"); + } + if (!clientOptions.projectId) { + throw new Error("clientOptions.projectId is required"); + } + this.firestoreClient = new Firestore({ + credentials: clientOptions.credentials, + projectId: clientOptions.projectId, + databaseId: clientOptions?.databaseId, + ignoreUndefinedProperties: + clientOptions.ignoreUndefinedProperties ?? false, + }); + } + } + + public client() { + return this.firestoreClient; + } + + /** + * Adds nodes to the vector store + * @param {BaseNode<Metadata>[]} nodes - Array of nodes to add to the vector store + * @returns {Promise<string[]>} Array of node IDs that were added + */ + async add(nodes: BaseNode<Metadata>[]): Promise<string[]> { + const batch = this.firestoreClient.batch(); + const collection = this.customCollectionReference( + this.firestoreClient.collection(this.collectionName), + ); + + const ids: string[] = []; + + for (const node of nodes) { + const docRef = collection.doc(node.id_); + const metadata = nodeToMetadata( + node, + !this.storesText, + "text", + this.flatMetadata, + ); + const entry = { + [this.embeddingKey]: FieldValue.vector(node.getEmbedding()), + [this.metadataKey]: metadata, + }; + + batch.set(docRef, entry, { merge: true }); + + ids.push(node.id_); + + // Commit batch when it reaches the size limit + if (ids.length % this.batchSize === 0) { + await batch.commit(); + } + } + + // Commit any remaining documents + if (nodes.length % this.batchSize !== 0) { + await batch.commit(); + } + + return ids; + } + + /** + * Deletes all nodes from the vector store that match the given filename + * @param {string} fileName - Name of the file whose nodes should be deleted + * @returns {Promise<void>} + */ + async delete(fileName: string): Promise<void> { + const collection = this.customCollectionReference( + this.firestoreClient.collection(this.collectionName), + ); + const snapshot = await collection + .where(`${this.metadataKey}.file_name`, "==", fileName) + .get(); + + const batch = this.firestoreClient.batch(); + snapshot.docs.forEach((doc) => { + batch.delete(doc.ref); + }); + await batch.commit(); + } + + /** + * Queries the vector store for similar nodes + * @param {VectorStoreQuery} query - Query parameters including queryStr or queryEmbedding, filters, and similarityTopK + * @param {object} [_options] - Optional parameters for the query + * @returns {Promise<VectorStoreQueryResult>} Query results containing matching nodes, their similarities, and IDs + * @throws {Error} When neither queryEmbedding nor queryStr is provided + */ + async query( + query: VectorStoreQuery, + _options?: object, + ): Promise<VectorStoreQueryResult> { + if (!query.queryEmbedding) { + throw new Error("No query embedding provided"); + } + + // Get documents with filters if any + let baseQuery = this.firestoreClient.collection(this.collectionName); + baseQuery = this.customCollectionReference(baseQuery); + if (query.filters) { + const filter = toFirestoreFilter(query.filters); + if (filter) { + baseQuery = baseQuery.where(filter) as CollectionReference; + } + } + + // Use Firestore's native vector search + const vectorQuery = baseQuery.findNearest({ + vectorField: this.embeddingKey, + queryVector: query.queryEmbedding, + limit: query.similarityTopK, + distanceMeasure: this.distanceMeasure, + distanceResultField: "vector_distance", + }) as VectorQuery; + + const snapshot = await vectorQuery.get(); + + // Convert results to VectorStoreQueryResult format + const topKIds: string[] = []; + const topKNodes: BaseNode[] = []; + const topKSimilarities: number[] = []; + + snapshot.forEach((doc) => { + const distance = doc.get("vector_distance") as number; + // Convert distance to similarity score (1 - normalized distance) + const similarity = + this.distanceMeasure === DistanceMeasure.DOT_PRODUCT + ? distance // For dot product, higher is more similar + : 1 / (1 + distance); // For EUCLIDEAN and COSINE, lower distance means more similar + + topKIds.push(doc.id); + topKNodes.push(metadataDictToNode(doc.get(this.metadataKey))); + topKSimilarities.push(similarity); + }); + + return { + nodes: topKNodes, + similarities: topKSimilarities, + ids: topKIds, + }; + } +} diff --git a/packages/providers/storage/firestore/src/index.ts b/packages/providers/storage/firestore/src/index.ts new file mode 100644 index 000000000..efb0a7a09 --- /dev/null +++ b/packages/providers/storage/firestore/src/index.ts @@ -0,0 +1 @@ +export * from "./FirestoreVectorStore"; diff --git a/packages/providers/storage/firestore/tsconfig.json b/packages/providers/storage/firestore/tsconfig.json new file mode 100644 index 000000000..4607e1860 --- /dev/null +++ b/packages/providers/storage/firestore/tsconfig.json @@ -0,0 +1,19 @@ +{ + "extends": "../../../../tsconfig.json", + "compilerOptions": { + "target": "ESNext", + "module": "ESNext", + "moduleResolution": "bundler", + "outDir": "./lib", + "tsBuildInfoFile": "./lib/.tsbuildinfo" + }, + "include": ["./src"], + "references": [ + { + "path": "../../../core/tsconfig.json" + }, + { + "path": "../../../env/tsconfig.json" + } + ] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c76c1225f..e8f40eb6e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -625,6 +625,9 @@ importers: '@llamaindex/env': specifier: ^0.1.28 version: link:../packages/env + '@llamaindex/firestore': + specifier: ^0.0.1 + version: link:../packages/providers/storage/firestore '@llamaindex/google': specifier: ^0.0.8 version: link:../packages/providers/google @@ -1449,6 +1452,22 @@ importers: specifier: 6.3.4 version: 6.3.4(patch_hash=pavboztthlgni7m5gzw7643oru)(typescript@5.7.3) + packages/providers/storage/firestore: + dependencies: + '@google-cloud/firestore': + specifier: ^7.11.0 + version: 7.11.0 + '@llamaindex/core': + specifier: workspace:* + version: link:../../../core + '@llamaindex/env': + specifier: workspace:* + version: link:../../../env + devDependencies: + bunchee: + specifier: 6.3.4 + version: 6.3.4(patch_hash=pavboztthlgni7m5gzw7643oru)(typescript@5.7.3) + packages/providers/storage/milvus: dependencies: '@grpc/grpc-js': @@ -3057,6 +3076,10 @@ packages: '@gerrit0/mini-shiki@1.27.2': resolution: {integrity: sha512-GeWyHz8ao2gBiUW4OJnQDxXQnFgZQwwQk05t/CVVgNBN7/rK8XZ7xY6YhLVv9tH3VppWWmr9DCl3MwemB/i+Og==} + '@google-cloud/firestore@7.11.0': + resolution: {integrity: sha512-88uZ+jLsp1aVMj7gh3EKYH1aulTAMFAp8sH/v5a9w8q8iqSG27RiWLoxSAFr/XocZ9hGiWH1kEnBw+zl3xAgNA==} + engines: {node: '>=14.0.0'} + '@google-cloud/vertexai@1.9.0': resolution: {integrity: sha512-8brlcJwFXI4fPuBtsDNQqCdWZmz8gV9jeEKOU0vc5H2SjehCQpXK/NwuSEr916zbhlBHtg/sU37qQQdgvh5BRA==} engines: {node: '>=18.0.0'} @@ -4961,6 +4984,10 @@ packages: '@tokenizer/token@0.3.0': resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} + '@tootallnate/once@2.0.0': + resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==} + engines: {node: '>= 10'} + '@tootallnate/quickjs-emscripten@0.23.0': resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==} @@ -4998,6 +5025,9 @@ packages: '@types/babel__traverse@7.20.6': resolution: {integrity: sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==} + '@types/caseless@0.12.5': + resolution: {integrity: sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg==} + '@types/cookie@0.6.0': resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} @@ -5103,6 +5133,9 @@ packages: '@types/readable-stream@4.0.18': resolution: {integrity: sha512-21jK/1j+Wg+7jVw1xnSwy/2Q1VgVjWuFssbYGTREPUBeZ+rqVFl2udq0IkxzPC0ZhOzVceUbyIACFZKLqKEBlA==} + '@types/request@2.48.12': + resolution: {integrity: sha512-G3sY+NpsA9jnwm0ixhAFQSJ3Q9JkpLZpJbI3GMv0mIAT0y3mRabYeINzal5WOChIiaTEGQYlHOKgkaM9EisWHw==} + '@types/resolve@1.20.2': resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} @@ -6537,6 +6570,9 @@ packages: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} + duplexify@4.1.3: + resolution: {integrity: sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==} + eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} @@ -7075,6 +7111,10 @@ packages: resolution: {integrity: sha512-KQVhvhK8ZkWzxKxOr56CPulAhH3dobtuQ4+hNQ+HekH/Wp5gSOafqRAeTphQUJAIk0GBvHZgJ2ZGRWd5kphMuw==} engines: {node: '>= 18'} + form-data@2.5.2: + resolution: {integrity: sha512-GgwY0PS7DbXqajuGf4OYlsrIu3zgxD6Vvql43IBhm6MahqA5SK/7mwhtNj2AdH2z35YR34ujJ7BN+3fFC3jP5Q==} + engines: {node: '>= 0.12'} + form-data@4.0.0: resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} engines: {node: '>= 6'} @@ -7257,6 +7297,9 @@ packages: resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==} engines: {node: '>= 0.4'} + functional-red-black-tree@1.0.1: + resolution: {integrity: sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==} + functions-have-names@1.2.3: resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} @@ -7409,6 +7452,10 @@ packages: resolution: {integrity: sha512-Jb6Z0+nvECVz+2lzSMt9u98UsoakXxA2HGHMCxh+so3n90XgYWkq5dur19JAJV7ONiJY22yBTyJB1TSkvPq9Ng==} engines: {node: '>=14'} + google-gax@4.4.1: + resolution: {integrity: sha512-Phyp9fMfA00J3sZbJxbbB4jC55b7DBjE3F6poyL3wKMEBVKA79q6BGuHcTiM28yOzVql0NDbRL8MLLh8Iwk9Dg==} + engines: {node: '>=14'} + google-logging-utils@0.0.2: resolution: {integrity: sha512-NEgUnEcBiP5HrPzufUkBzJOD/Sxsco3rLNo1F1TNf7ieU8ryUzBhqba8r756CjLX7rn3fHl6iLEwPYuqpoKgQQ==} engines: {node: '>=14'} @@ -7624,6 +7671,10 @@ packages: http-cache-semantics@4.1.1: resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} + http-proxy-agent@5.0.0: + resolution: {integrity: sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==} + engines: {node: '>= 6'} + http-proxy-agent@7.0.2: resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} engines: {node: '>= 14'} @@ -9738,6 +9789,10 @@ packages: property-information@6.5.0: resolution: {integrity: sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==} + proto3-json-serializer@2.0.2: + resolution: {integrity: sha512-SAzp/O4Yh02jGdRc+uIrGoe87dkN/XtwxfZ4ZyafJHymd79ozp5VG5nyZ7ygqPM5+cpLDjjGnYFUkngonyDPOQ==} + engines: {node: '>=14.0.0'} + protobufjs@6.11.4: resolution: {integrity: sha512-5kQWPaJHi1WoCpjTGszzQ32PG2F4+wRY6BmAT4Vfw56Q2FZ4YZzK20xUYQH4YkfehY1e6QSICrJquM6xXZNcrw==} hasBin: true @@ -10182,6 +10237,10 @@ packages: resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} engines: {node: '>=18'} + retry-request@7.0.2: + resolution: {integrity: sha512-dUOvLMJ0/JJYEn8NrpOaGNE7X3vpI5XlZS/u0ANjqtcZVKnIxP7IgCFwrKTxENw29emmwug53awKtaMm4i9g5w==} + engines: {node: '>=14'} + reusify@1.0.4: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} @@ -10585,6 +10644,12 @@ packages: resolution: {integrity: sha512-I6GPS/E0zyieHehMRPQcqkiBMJKGgLta+1hREixhoLPqEA0AlVFiC43dl8uPpmkkeRdDMzYRWFWk5/l9x7nmNg==} engines: {node: '>=0.10.0'} + stream-events@1.0.5: + resolution: {integrity: sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==} + + stream-shift@1.0.3: + resolution: {integrity: sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==} + stream-to-array@2.3.0: resolution: {integrity: sha512-UsZtOYEn4tWU2RGLOXr/o/xjRBftZRlG3dEWoaHr8j4GuypJ3isitGbVyjQKAuMu+xbiop8q224TjiZWc4XTZA==} @@ -10712,6 +10777,9 @@ packages: resolution: {integrity: sha512-FhwotcEqjr241ZbjFzjlIYg6c5/L/s4yBGWSMvJ9UoExiSqL+FnFA/CaeZx17WGaZMS/4SOZp8wH18jSS4R4lw==} engines: {node: '>=16'} + stubs@3.0.0: + resolution: {integrity: sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw==} + style-mod@4.1.2: resolution: {integrity: sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==} @@ -10821,6 +10889,10 @@ packages: resolution: {integrity: sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==} engines: {node: '>=18'} + teeny-request@9.0.0: + resolution: {integrity: sha512-resvxdc6Mgb7YEThw6G6bExlXKkv6+YbuzGg9xuXxSgxJF7Ozs+o8Y9+2R3sArdWdW8nOokoQb1yrpFB0pQK2g==} + engines: {node: '>=14'} + term-size@2.2.1: resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} engines: {node: '>=8'} @@ -13447,6 +13519,17 @@ snapshots: '@shikijs/types': 1.29.2 '@shikijs/vscode-textmate': 10.0.1 + '@google-cloud/firestore@7.11.0': + dependencies: + '@opentelemetry/api': 1.9.0 + fast-deep-equal: 3.1.3 + functional-red-black-tree: 1.0.1 + google-gax: 4.4.1 + protobufjs: 7.4.0 + transitivePeerDependencies: + - encoding + - supports-color + '@google-cloud/vertexai@1.9.0': dependencies: google-auth-library: 9.15.1 @@ -15661,6 +15744,8 @@ snapshots: '@tokenizer/token@0.3.0': {} + '@tootallnate/once@2.0.0': {} + '@tootallnate/quickjs-emscripten@0.23.0': {} '@ts-graphviz/adapter@2.0.6': @@ -15709,6 +15794,8 @@ snapshots: dependencies: '@babel/types': 7.26.8 + '@types/caseless@0.12.5': {} + '@types/cookie@0.6.0': {} '@types/debug@4.1.12': @@ -15826,6 +15913,13 @@ snapshots: '@types/node': 22.9.0 safe-buffer: 5.1.2 + '@types/request@2.48.12': + dependencies: + '@types/caseless': 0.12.5 + '@types/node': 22.9.0 + '@types/tough-cookie': 4.0.5 + form-data: 2.5.2 + '@types/resolve@1.20.2': {} '@types/statuses@2.0.5': {} @@ -16351,7 +16445,6 @@ snapshots: debug: 4.4.0 transitivePeerDependencies: - supports-color - optional: true agent-base@7.1.3: {} @@ -17439,6 +17532,13 @@ snapshots: es-errors: 1.3.0 gopd: 1.2.0 + duplexify@4.1.3: + dependencies: + end-of-stream: 1.4.4 + inherits: 2.0.4 + readable-stream: 3.6.2 + stream-shift: 1.0.3 + eastasianwidth@0.2.0: {} ecdsa-sig-formatter@1.0.11: @@ -18233,6 +18333,13 @@ snapshots: form-data-encoder@4.0.2: {} + form-data@2.5.2: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + safe-buffer: 5.2.1 + form-data@4.0.0: dependencies: asynckit: 0.4.0 @@ -18511,6 +18618,8 @@ snapshots: hasown: 2.0.2 is-callable: 1.2.7 + functional-red-black-tree@1.0.1: {} + functions-have-names@1.2.3: {} fuse.js@6.6.2: {} @@ -18709,6 +18818,24 @@ snapshots: - encoding - supports-color + google-gax@4.4.1: + dependencies: + '@grpc/grpc-js': 1.12.6 + '@grpc/proto-loader': 0.7.13 + '@types/long': 4.0.2 + abort-controller: 3.0.0 + duplexify: 4.1.3 + google-auth-library: 9.15.1 + node-fetch: 2.7.0 + object-hash: 3.0.0 + proto3-json-serializer: 2.0.2 + protobufjs: 7.4.0 + retry-request: 7.0.2 + uuid: 9.0.1 + transitivePeerDependencies: + - encoding + - supports-color + google-logging-utils@0.0.2: {} gopd@1.2.0: {} @@ -19061,6 +19188,14 @@ snapshots: http-cache-semantics@4.1.1: {} + http-proxy-agent@5.0.0: + dependencies: + '@tootallnate/once': 2.0.0 + agent-base: 6.0.2 + debug: 4.4.0 + transitivePeerDependencies: + - supports-color + http-proxy-agent@7.0.2: dependencies: agent-base: 7.1.3 @@ -19106,7 +19241,6 @@ snapshots: debug: 4.4.0 transitivePeerDependencies: - supports-color - optional: true https-proxy-agent@7.0.6: dependencies: @@ -21733,6 +21867,10 @@ snapshots: property-information@6.5.0: {} + proto3-json-serializer@2.0.2: + dependencies: + protobufjs: 7.4.0 + protobufjs@6.11.4: dependencies: '@protobufjs/aspromise': 1.1.2 @@ -22412,6 +22550,15 @@ snapshots: onetime: 7.0.0 signal-exit: 4.1.0 + retry-request@7.0.2: + dependencies: + '@types/request': 2.48.12 + extend: 3.0.2 + teeny-request: 9.0.0 + transitivePeerDependencies: + - encoding + - supports-color + reusify@1.0.4: {} rfdc@1.4.1: {} @@ -22887,6 +23034,12 @@ snapshots: stopwords-iso@1.1.0: {} + stream-events@1.0.5: + dependencies: + stubs: 3.0.0 + + stream-shift@1.0.3: {} + stream-to-array@2.3.0: dependencies: any-promise: 1.3.0 @@ -23046,6 +23199,8 @@ snapshots: '@tokenizer/token': 0.3.0 peek-readable: 5.4.2 + stubs@3.0.0: {} + style-mod@4.1.2: {} style-to-object@0.4.4: @@ -23223,6 +23378,17 @@ snapshots: mkdirp: 3.0.1 yallist: 5.0.0 + teeny-request@9.0.0: + dependencies: + http-proxy-agent: 5.0.0 + https-proxy-agent: 5.0.1 + node-fetch: 2.7.0 + stream-events: 1.0.5 + uuid: 9.0.1 + transitivePeerDependencies: + - encoding + - supports-color + term-size@2.2.1: {} terser-webpack-plugin@5.3.11(@swc/core@1.10.15(@swc/helpers@0.5.15))(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))): diff --git a/tsconfig.json b/tsconfig.json index ea6733a72..a675b7b4b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -158,6 +158,9 @@ { "path": "./packages/providers/storage/weaviate/tsconfig.json" }, + { + "path": "./packages/providers/storage/firestore/tsconfig.json" + }, { "path": "./packages/providers/google/tsconfig.json" }, -- GitLab