├── .babelrc ├── .editorconfig ├── .eslintignore ├── .eslintrc.cjs ├── .github ├── CODEOWNERS └── workflows │ └── main.yaml ├── .gitignore ├── .husky └── pre-commit ├── .npmignore ├── .prettierignore ├── .prettierrc ├── CODE_OF_CONDUCT.md ├── CONTRIBUTE.md ├── LICENSE ├── README.md ├── ci ├── compose.sh ├── docker-compose-async.yml ├── docker-compose-azure-cc.yml ├── docker-compose-backup.yml ├── docker-compose-cluster.yml ├── docker-compose-okta-cc.yml ├── docker-compose-okta-users.yml ├── docker-compose-openai.yml ├── docker-compose-proxy.yml ├── docker-compose-rbac.yml ├── docker-compose-wcs.yml ├── docker-compose.yml ├── proxy │ ├── grpc.yaml │ └── http.yaml ├── run_dependencies.sh └── stop_dependencies.sh ├── examples ├── README.md ├── javascript │ ├── .gitignore │ ├── index.js │ └── package.json └── typescript │ ├── .gitignore │ ├── index.ts │ ├── package.json │ └── tsconfig.json ├── jest.config.ts ├── package-lock.json ├── package.json ├── public └── favicon.ico ├── src ├── backup │ ├── backupCreateStatusGetter.ts │ ├── backupCreator.ts │ ├── backupGetter.ts │ ├── backupRestoreStatusGetter.ts │ ├── backupRestorer.ts │ ├── index.ts │ ├── journey.test.ts │ └── validation.ts ├── batch │ ├── index.ts │ ├── journey.test.ts │ ├── objectsBatchDeleter.ts │ ├── objectsBatcher.ts │ ├── path.test.ts │ ├── path.ts │ ├── referencePayloadBuilder.ts │ └── referencesBatcher.ts ├── c11y │ ├── conceptsGetter.ts │ ├── extensionCreator.ts │ ├── index.ts │ └── journey.test.ts ├── classifications │ ├── contextual.journey.test.ts │ ├── getter.ts │ ├── index.ts │ ├── knn.journey.test.ts │ └── scheduler.ts ├── cluster │ ├── index.ts │ └── nodesStatusGetter.ts ├── collections │ ├── aggregate │ │ ├── index.ts │ │ └── integration.test.ts │ ├── backup │ │ ├── client.ts │ │ ├── collection.ts │ │ ├── index.ts │ │ ├── integration.test.ts │ │ ├── types.ts │ │ └── unit.test.ts │ ├── cluster │ │ ├── index.ts │ │ └── integration.test.ts │ ├── collection │ │ └── index.ts │ ├── config │ │ ├── classes.ts │ │ ├── index.ts │ │ ├── integration.test.ts │ │ ├── types │ │ │ ├── generative.ts │ │ │ ├── index.ts │ │ │ ├── reranker.ts │ │ │ ├── vectorIndex.ts │ │ │ └── vectorizer.ts │ │ ├── unit.test.ts │ │ └── utils.ts │ ├── configure │ │ ├── generative.ts │ │ ├── index.ts │ │ ├── parsing.ts │ │ ├── reranker.ts │ │ ├── types │ │ │ ├── base.ts │ │ │ ├── generative.ts │ │ │ ├── index.ts │ │ │ ├── vectorIndex.ts │ │ │ └── vectorizer.ts │ │ ├── unit.test.ts │ │ ├── vectorIndex.ts │ │ └── vectorizer.ts │ ├── data │ │ ├── index.ts │ │ └── integration.test.ts │ ├── deserialize │ │ └── index.ts │ ├── filters │ │ ├── classes.ts │ │ ├── index.ts │ │ ├── integration.test.ts │ │ ├── types.ts │ │ ├── unit.test.ts │ │ └── utils.ts │ ├── generate │ │ ├── config.ts │ │ ├── index.ts │ │ ├── integration.test.ts │ │ ├── mock.test.ts │ │ ├── types.ts │ │ └── unit.test.ts │ ├── index.ts │ ├── integration.test.ts │ ├── iterator │ │ ├── index.ts │ │ └── integration.test.ts │ ├── journey.test.ts │ ├── query │ │ ├── check.ts │ │ ├── index.ts │ │ ├── integration.test.ts │ │ ├── types.ts │ │ └── utils.ts │ ├── references │ │ ├── classes.ts │ │ ├── index.ts │ │ ├── types.ts │ │ └── utils.ts │ ├── serialize │ │ ├── index.ts │ │ └── unit.test.ts │ ├── sort │ │ ├── classes.ts │ │ ├── index.ts │ │ ├── integration.test.ts │ │ └── types.ts │ ├── tenants │ │ ├── index.ts │ │ ├── integration.test.ts │ │ ├── types.ts │ │ └── unit.test.ts │ ├── types │ │ ├── batch.ts │ │ ├── data.ts │ │ ├── generate.ts │ │ ├── index.ts │ │ ├── internal.ts │ │ └── query.ts │ └── vectors │ │ └── multiTargetVector.ts ├── connection │ ├── auth.ts │ ├── gql.ts │ ├── grpc.ts │ ├── helpers.test.ts │ ├── helpers.ts │ ├── http.ts │ ├── index.ts │ ├── integration.test.ts │ ├── journey.test.ts │ ├── proxy.test.ts │ └── unit.test.ts ├── data │ ├── checker.ts │ ├── creator.ts │ ├── deleter.ts │ ├── getter.ts │ ├── getterById.ts │ ├── index.ts │ ├── journey.test.ts │ ├── merger.ts │ ├── path.test.ts │ ├── path.ts │ ├── referenceCreator.ts │ ├── referenceDeleter.ts │ ├── referencePayloadBuilder.ts │ ├── referenceReplacer.ts │ ├── replication.ts │ ├── updater.ts │ └── validator.ts ├── errors.ts ├── graphql │ ├── aggregator.ts │ ├── ask.ts │ ├── bm25.ts │ ├── explorer.ts │ ├── generate.ts │ ├── getter.test.ts │ ├── getter.ts │ ├── group.ts │ ├── groupBy.ts │ ├── hybrid.ts │ ├── index.ts │ ├── journey.test.ts │ ├── nearImage.ts │ ├── nearMedia.ts │ ├── nearObject.ts │ ├── nearText.ts │ ├── nearVector.ts │ ├── raw.test.ts │ ├── raw.ts │ ├── sort.ts │ └── where.ts ├── grpc │ ├── aggregator.ts │ ├── base.ts │ ├── batcher.ts │ ├── retry.ts │ ├── searcher.ts │ └── tenantsManager.ts ├── index.ts ├── integration.test.ts ├── misc │ ├── index.ts │ ├── journey.test.ts │ ├── liveChecker.ts │ ├── metaGetter.ts │ ├── openidConfigurationGetter.ts │ └── readyChecker.ts ├── openapi │ ├── schema.ts │ └── types.ts ├── proto │ ├── google │ │ ├── health │ │ │ └── v1 │ │ │ │ └── health.ts │ │ └── protobuf │ │ │ └── struct.ts │ └── v1 │ │ ├── aggregate.ts │ │ ├── base.ts │ │ ├── base_search.ts │ │ ├── batch.ts │ │ ├── batch_delete.ts │ │ ├── generative.ts │ │ ├── properties.ts │ │ ├── search_get.ts │ │ ├── tenants.ts │ │ └── weaviate.ts ├── roles │ ├── index.ts │ ├── integration.test.ts │ ├── types.ts │ └── util.ts ├── schema │ ├── classCreator.ts │ ├── classDeleter.ts │ ├── classExists.ts │ ├── classGetter.ts │ ├── classUpdater.ts │ ├── deleteAll.ts │ ├── getter.ts │ ├── index.ts │ ├── journey.test.ts │ ├── propertyCreator.ts │ ├── shardUpdater.ts │ ├── shardsGetter.ts │ ├── shardsUpdater.ts │ ├── tenantsCreator.ts │ ├── tenantsDeleter.ts │ ├── tenantsExists.ts │ ├── tenantsGetter.ts │ ├── tenantsUpdater.ts │ └── vectorAdder.ts ├── users │ ├── index.ts │ ├── integration.test.ts │ └── types.ts ├── utils │ ├── base64.test.ts │ ├── base64.ts │ ├── beaconPath.ts │ ├── dbVersion.ts │ ├── journey.test.ts │ ├── testData.ts │ └── uuid.ts ├── v2 │ └── index.ts └── validation │ ├── commandBase.ts │ ├── number.ts │ ├── string.ts │ └── version.ts ├── test ├── dbVersionProvider.ts ├── server.ts └── version.ts ├── tools ├── health.proto ├── prepare_release.sh ├── refresh_protos.sh └── refresh_schema.sh ├── tsconfig-test.json ├── tsconfig.json └── tsup.config.ts /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-env"], 3 | "plugins": [ 4 | "@babel/plugin-proposal-class-properties", 5 | "@babel/plugin-transform-runtime" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | charset = utf-8 3 | indent_style = space 4 | indent_size = 2 5 | insert_final_newline = true 6 | trim_trailing_whitespace = true 7 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | types 4 | docs -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Ci related folders 2 | /.github/ @weaviate/core 3 | /ci/ @weaviate/core 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | coverage/ 3 | node_modules/ 4 | config.yaml 5 | lib.js 6 | weaviate-data/ 7 | .vscode/ 8 | .idea/ 9 | *.tgz 10 | .npmrc 11 | .eslintcache 12 | test.sh 13 | scratch/ 14 | docs/ 15 | dist/ -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npx lint-staged 5 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # This file is written to be a whitelist instead of a blacklist. Start by 2 | # ignoring everything, then add back the files we want to be included in the 3 | # final NPM package. 4 | * 5 | 6 | # And these are the files that are allowed. 7 | !/LICENSE 8 | !/README.md 9 | !/package.json 10 | !/dist/**/* 11 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | src/proto/**/*.ts 2 | src/dist/**/* 3 | src/docs/**/*.js -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": true, 3 | "arrowParens": "always", 4 | "trailingComma": "es5", 5 | "bracketSpacing": true, 6 | "singleQuote": true, 7 | "printWidth": 110, 8 | "tabWidth": 2 9 | } 10 | -------------------------------------------------------------------------------- /CONTRIBUTE.md: -------------------------------------------------------------------------------- 1 | ### Thanks for looking into contributing to Weaviate TypeScript client! 2 | Contributing works pretty easy. You can do a pull request or you can commit if you are part of a Weaviate team. 3 | 4 | ### Code of Conduct 5 | Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms. 6 | [![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-v2.0%20adopted-ff69b4.svg)](CODE_OF_CONDUCT.md) 7 | 8 | 9 | ### How we use Gitflow 10 | How we use [Gitflow](https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow) and how you can contribute following a few steps. 11 | 12 | - The main branch is what is released and developed currently. 13 | - You can create a feature-branch that is named: feature/YOUR-FEATURE-NAME. 14 | - Your feature branch always has the main branch as a starting point. 15 | - When you are done with your feature you should create a pull request into the main branch. 16 | - The main branch is protected. 17 | 18 | ### Tagging your commit 19 | 20 | Always add a reference to your issue to your git commit. 21 | 22 | For example: `gh-100: This is the commit message` 23 | 24 | AKA: smart commits 25 | 26 | ### Pull Request 27 | 28 | If you create a pull request without smart commits, the pull request will be [squashed into](https://blog.github.com/2016-04-01-squash-your-commits/) one git commit. 29 | 30 | ### Contributor License Agreement 31 | 32 | Contributions to Weaviate TypeScript client must be accompanied by a Contributor License Agreement. You (or your employer) retain the copyright to your contribution; this simply gives us permission to use and redistribute your contributions as part of Weaviate TypeScript client. Go to [this page](https://www.semi.technology/playbooks/misc/contributor-license-agreement.html) to read the current agreement. 33 | 34 | The process works as follows: 35 | 36 | - You contribute by opening a [pull request](#pull-request). 37 | - If your account has no CLA, a DocuSign link will be added as a comment to the pull request. 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020-2023, Weaviate B.V. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Weaviate JS/TS client Weaviate logo 2 | 3 | Official JS/TS client for easy interaction with a Weaviate instance. 4 | 5 | ## Documentation 6 | 7 | - [General Documentation](https://weaviate.io/developers/weaviate/client-libraries/typescript). 8 | - [Client-specific Documentation](https://weaviate.github.io/typescript-client/) 9 | 10 | ## Support 11 | 12 | - [Stackoverflow for questions](https://stackoverflow.com/questions/tagged/weaviate). 13 | - [Github for issues](https://github.com/weaviate/typescript-client/issues). 14 | 15 | ## Contributing 16 | 17 | - [How to Contribute](https://github.com/weaviate/typescript-client/blob/main/CONTRIBUTE.md). 18 | 19 | ## Build Status 20 | 21 | [![Build Status](https://github.com/weaviate/typescript-client/actions/workflows/.github/workflows/main.yaml/badge.svg?branch=main)](https://github.com/weaviate/typescript-client/actions/workflows/.github/workflows/main.yaml) 22 | -------------------------------------------------------------------------------- /ci/compose.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -eou pipefail 4 | 5 | function ls_compose { 6 | ls ci | grep 'docker-compose' 7 | } 8 | 9 | function exec_all { 10 | for file in $(ls_compose); do 11 | docker compose -f $(echo "ci/${file} ${1}") 12 | done 13 | } 14 | 15 | function compose_up_all { 16 | exec_all "up -d" 17 | } 18 | 19 | function compose_down_all { 20 | exec_all "down --remove-orphans" 21 | } 22 | 23 | function all_weaviate_ports { 24 | echo "8078 8080 8081 8082 8083 8085 8086 8087 8088 8089 8090 8091" 25 | } 26 | -------------------------------------------------------------------------------- /ci/docker-compose-async.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: '3.4' 3 | services: 4 | weaviate_async: 5 | command: 6 | - --host 7 | - 0.0.0.0 8 | - --port 9 | - '8090' 10 | - --scheme 11 | - http 12 | image: semitechnologies/weaviate:${WEAVIATE_VERSION} 13 | ports: 14 | - "8078:8090" 15 | - "50049:50051" 16 | restart: on-failure:0 17 | environment: 18 | QUERY_DEFAULTS_LIMIT: 25 19 | AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: 'true' 20 | PERSISTENCE_DATA_PATH: '/var/lib/weaviate' 21 | CLUSTER_HOSTNAME: 'node1' 22 | ASYNC_INDEXING: 'true' 23 | DISABLE_TELEMETRY: 'true' 24 | -------------------------------------------------------------------------------- /ci/docker-compose-azure-cc.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: '3.4' 3 | services: 4 | weaviate-auth-azure: 5 | command: 6 | - --host 7 | - 0.0.0.0 8 | - --port 9 | - '8081' 10 | - --scheme 11 | - http 12 | - --write-timeout=600s 13 | image: semitechnologies/weaviate:${WEAVIATE_VERSION} 14 | ports: 15 | - 8081:8081 16 | restart: on-failure:0 17 | environment: 18 | PERSISTENCE_DATA_PATH: '/var/lib/weaviate' 19 | AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: 'false' 20 | AUTHENTICATION_OIDC_ENABLED: 'true' 21 | AUTHENTICATION_OIDC_CLIENT_ID: '4706508f-30c2-469b-8b12-ad272b3de864' 22 | AUTHENTICATION_OIDC_ISSUER: 'https://login.microsoftonline.com/36c47fb4-f57c-4e1c-8760-d42293932cc2/v2.0' 23 | AUTHENTICATION_OIDC_USERNAME_CLAIM: 'oid' 24 | AUTHENTICATION_OIDC_GROUPS_CLAIM: 'groups' 25 | AUTHORIZATION_ADMINLIST_ENABLED: 'true' 26 | AUTHORIZATION_ADMINLIST_USERS: 'b6bf8e1d-d398-4e5d-8f1b-50fda9146a64' 27 | DISABLE_TELEMETRY: 'true' 28 | ... 29 | -------------------------------------------------------------------------------- /ci/docker-compose-backup.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: '3.4' 3 | services: 4 | weaviate-backup: 5 | image: semitechnologies/weaviate:${WEAVIATE_VERSION} 6 | restart: on-failure:0 7 | ports: 8 | - 8090:8080 9 | - 50061:50051 10 | environment: 11 | QUERY_DEFAULTS_LIMIT: 20 12 | AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: 'true' 13 | PERSISTENCE_DATA_PATH: "./weaviate-data" 14 | BACKUP_FILESYSTEM_PATH: "/tmp/backups" 15 | ENABLE_MODULES: backup-filesystem 16 | CLUSTER_GOSSIP_BIND_PORT: "7100" 17 | CLUSTER_DATA_BIND_PORT: "7101" 18 | DISABLE_TELEMETRY: 'true' 19 | ... 20 | -------------------------------------------------------------------------------- /ci/docker-compose-cluster.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: '3.4' 3 | services: 4 | weaviate-node-1: 5 | image: semitechnologies/weaviate:${WEAVIATE_VERSION} 6 | restart: on-failure:0 7 | ports: 8 | - "8087:8080" 9 | - "50058:50051" 10 | environment: 11 | QUERY_DEFAULTS_LIMIT: 20 12 | AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: 'true' 13 | PERSISTENCE_DATA_PATH: "./weaviate-node-1" 14 | CLUSTER_HOSTNAME: "node1" 15 | CLUSTER_GOSSIP_BIND_PORT: "7110" 16 | CLUSTER_DATA_BIND_PORT: "7111" 17 | RAFT_PORT: '8300' 18 | RAFT_INTERNAL_RPC_PORT: "8301" 19 | RAFT_JOIN: "node1:8300,node2:8300,node3:8300" 20 | RAFT_BOOTSTRAP_EXPECT: "3" 21 | DISABLE_TELEMETRY: 'true' 22 | CONTEXTIONARY_URL: contextionary:9999 23 | DEFAULT_VECTORIZER_MODULE: text2vec-contextionary 24 | ENABLE_MODULES: text2vec-contextionary 25 | 26 | weaviate-node-2: 27 | init: true 28 | command: 29 | - --host 30 | - 0.0.0.0 31 | - --port 32 | - '8080' 33 | - --scheme 34 | - http 35 | image: semitechnologies/weaviate:${WEAVIATE_VERSION} 36 | ports: 37 | - 8088:8080 38 | - "50059:50051" 39 | restart: on-failure:0 40 | environment: 41 | LOG_LEVEL: 'debug' 42 | QUERY_DEFAULTS_LIMIT: 20 43 | AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: 'true' 44 | PERSISTENCE_DATA_PATH: './weaviate-node-2' 45 | CLUSTER_HOSTNAME: 'node2' 46 | CLUSTER_GOSSIP_BIND_PORT: '7110' 47 | CLUSTER_DATA_BIND_PORT: '7111' 48 | CLUSTER_JOIN: 'weaviate-node-1:7110' 49 | RAFT_PORT: '8300' 50 | RAFT_INTERNAL_RPC_PORT: "8301" 51 | RAFT_JOIN: "node1:8300,node2:8300,node3:8300" 52 | RAFT_BOOTSTRAP_EXPECT: "3" 53 | DISABLE_TELEMETRY: 'true' 54 | CONTEXTIONARY_URL: contextionary:9999 55 | DEFAULT_VECTORIZER_MODULE: text2vec-contextionary 56 | ENABLE_MODULES: text2vec-contextionary 57 | 58 | weaviate-node-3: 59 | init: true 60 | command: 61 | - --host 62 | - 0.0.0.0 63 | - --port 64 | - '8080' 65 | - --scheme 66 | - http 67 | image: semitechnologies/weaviate:${WEAVIATE_VERSION} 68 | ports: 69 | - 8089:8080 70 | - "50060:50051" 71 | restart: on-failure:0 72 | environment: 73 | LOG_LEVEL: 'debug' 74 | QUERY_DEFAULTS_LIMIT: 20 75 | AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: 'true' 76 | PERSISTENCE_DATA_PATH: './weaviate-node-2' 77 | CLUSTER_HOSTNAME: 'node3' 78 | CLUSTER_GOSSIP_BIND_PORT: '7110' 79 | CLUSTER_DATA_BIND_PORT: '7111' 80 | CLUSTER_JOIN: 'weaviate-node-1:7110' 81 | RAFT_PORT: '8300' 82 | RAFT_INTERNAL_RPC_PORT: "8301" 83 | RAFT_JOIN: "node1:8300,node2:8300,node3:8300" 84 | RAFT_BOOTSTRAP_EXPECT: "3" 85 | DISABLE_TELEMETRY: 'true' 86 | CONTEXTIONARY_URL: contextionary:9999 87 | DEFAULT_VECTORIZER_MODULE: text2vec-contextionary 88 | ENABLE_MODULES: text2vec-contextionary 89 | ... 90 | -------------------------------------------------------------------------------- /ci/docker-compose-okta-cc.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: '3.4' 3 | services: 4 | weaviate-auth-okta-cc: 5 | command: 6 | - --host 7 | - 0.0.0.0 8 | - --port 9 | - '8082' 10 | - --scheme 11 | - http 12 | - --write-timeout=600s 13 | image: semitechnologies/weaviate:${WEAVIATE_VERSION} 14 | ports: 15 | - 8082:8082 16 | restart: on-failure:0 17 | environment: 18 | PERSISTENCE_DATA_PATH: '/var/lib/weaviate' 19 | AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: 'false' 20 | AUTHENTICATION_OIDC_ENABLED: 'true' 21 | AUTHENTICATION_OIDC_CLIENT_ID: '0oa7e9ipdkVZRUcxo5d7' 22 | AUTHENTICATION_OIDC_ISSUER: 'https://dev-32300990.okta.com/oauth2/aus7e9kxbwYQB0eht5d7' 23 | AUTHENTICATION_OIDC_USERNAME_CLAIM: 'cid' 24 | AUTHENTICATION_OIDC_GROUPS_CLAIM: 'groups' 25 | AUTHORIZATION_ADMINLIST_ENABLED: 'true' 26 | AUTHORIZATION_ADMINLIST_USERS: '0oa7e9ipdkVZRUcxo5d7' 27 | DISABLE_TELEMETRY: 'true' 28 | ... 29 | -------------------------------------------------------------------------------- /ci/docker-compose-okta-users.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: '3.4' 3 | services: 4 | weaviate-auth-okta-users: 5 | command: 6 | - --host 7 | - 0.0.0.0 8 | - --port 9 | - '8083' 10 | - --scheme 11 | - http 12 | - --write-timeout=600s 13 | image: semitechnologies/weaviate:${WEAVIATE_VERSION} 14 | ports: 15 | - 8083:8083 16 | restart: on-failure:0 17 | environment: 18 | PERSISTENCE_DATA_PATH: '/var/lib/weaviate' 19 | AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: 'false' 20 | AUTHENTICATION_OIDC_ENABLED: 'true' 21 | AUTHENTICATION_OIDC_CLIENT_ID: '0oa7iz2g41rNxv95B5d7' 22 | AUTHENTICATION_OIDC_ISSUER: 'https://dev-32300990.okta.com/oauth2/aus7iz3tna3kckRWS5d7' 23 | AUTHENTICATION_OIDC_USERNAME_CLAIM: 'sub' 24 | AUTHENTICATION_OIDC_GROUPS_CLAIM: 'groups' 25 | AUTHORIZATION_ADMINLIST_ENABLED: 'true' 26 | AUTHORIZATION_ADMINLIST_USERS: 'test@test.de' 27 | AUTHENTICATION_OIDC_SCOPES: 'openid,email' 28 | DISABLE_TELEMETRY: 'true' 29 | ... 30 | -------------------------------------------------------------------------------- /ci/docker-compose-openai.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: '3.4' 3 | services: 4 | weaviate_openai: 5 | command: 6 | - --host 7 | - 0.0.0.0 8 | - --port 9 | - '8086' 10 | - --scheme 11 | - http 12 | image: semitechnologies/weaviate:${WEAVIATE_VERSION} 13 | ports: 14 | - 8086:8086 15 | - 50057:50051 16 | restart: on-failure:0 17 | environment: 18 | QUERY_DEFAULTS_LIMIT: 25 19 | AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: 'true' 20 | PERSISTENCE_DATA_PATH: '/var/lib/weaviate' 21 | DEFAULT_VECTORIZER_MODULE: 'text2vec-openai' 22 | ENABLE_MODULES: 'text2vec-openai,generative-openai' 23 | CLUSTER_HOSTNAME: 'node1' 24 | DISABLE_TELEMETRY: 'true' 25 | ... 26 | -------------------------------------------------------------------------------- /ci/docker-compose-proxy.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: '3.4' 3 | services: 4 | weaviate-proxy: 5 | command: 6 | - --host 7 | - 0.0.0.0 8 | - --port 9 | - '8020' 10 | - --scheme 11 | - http 12 | - --write-timeout=600s 13 | image: semitechnologies/weaviate:${WEAVIATE_VERSION} 14 | restart: on-failure:0 15 | environment: 16 | CONTEXTIONARY_URL: contextionary:9999 17 | QUERY_DEFAULTS_LIMIT: 25 18 | AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: 'true' 19 | PERSISTENCE_DATA_PATH: '/var/lib/weaviate' 20 | DEFAULT_VECTORIZER_MODULE: 'text2vec-contextionary' 21 | ENABLE_MODULES: text2vec-contextionary 22 | BACKUP_FILESYSTEM_PATH: "/tmp/backups" 23 | CLUSTER_GOSSIP_BIND_PORT: "7100" 24 | CLUSTER_DATA_BIND_PORT: "7101" 25 | CLUSTER_HOSTNAME: "node1" 26 | AUTOSCHEMA_ENABLED: 'false' 27 | DISABLE_TELEMETRY: 'true' 28 | GRPC_PORT: 8021 29 | proxy-http: 30 | image: envoyproxy/envoy:v1.29-latest 31 | command: envoy --config-path /etc/envoy/http.yaml 32 | ports: 33 | - 10000:10000 34 | volumes: 35 | - ./proxy:/etc/envoy 36 | proxy-grpc: 37 | image: envoyproxy/envoy:v1.29-latest 38 | command: envoy --config-path /etc/envoy/grpc.yaml 39 | ports: 40 | - 10001:10000 41 | volumes: 42 | - ./proxy:/etc/envoy 43 | ... 44 | -------------------------------------------------------------------------------- /ci/docker-compose-rbac.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: '3.4' 3 | services: 4 | weaviate-rbac: 5 | command: 6 | - --host 7 | - 0.0.0.0 8 | - --port 9 | - '8085' 10 | - --scheme 11 | - http 12 | - --write-timeout=600s 13 | image: semitechnologies/weaviate:${WEAVIATE_VERSION} 14 | ports: 15 | - 8091:8085 16 | - 50062:50051 17 | restart: on-failure:0 18 | environment: 19 | ENABLE_MODULES: "generative-dummy,reranker-dummy" 20 | PERSISTENCE_DATA_PATH: "./data-weaviate-0" 21 | CLUSTER_IN_LOCALHOST: "true" 22 | CLUSTER_GOSSIP_BIND_PORT: "7100" 23 | CLUSTER_DATA_BIND_PORT: "7101" 24 | RAFT_BOOTSTRAP_EXPECT: "1" 25 | AUTHENTICATION_APIKEY_ENABLED: "true" 26 | AUTHENTICATION_APIKEY_ALLOWED_KEYS: 'viewer-key,editor-key,admin-key,custom-key' 27 | AUTHENTICATION_APIKEY_USERS: 'viewer-user,editor-user,admin-user,custom-user' 28 | AUTHORIZATION_RBAC_ENABLED: "true" 29 | AUTHORIZATION_ADMIN_USERS: "admin-user" 30 | AUTHORIZATION_VIEWER_USERS: "viewer-user" 31 | AUTHENTICATION_DB_USERS_ENABLED: "true" 32 | AUTHENTICATION_OIDC_ENABLED: "true" 33 | AUTHENTICATION_OIDC_CLIENT_ID: "wcs" 34 | AUTHENTICATION_OIDC_ISSUER: "https://auth.wcs.api.weaviate.io/auth/realms/SeMI" 35 | AUTHENTICATION_OIDC_USERNAME_CLAIM: "email" 36 | AUTHENTICATION_OIDC_GROUPS_CLAIM: "groups" 37 | ... 38 | -------------------------------------------------------------------------------- /ci/docker-compose-wcs.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: '3.4' 3 | services: 4 | weaviate-auth-wcs: 5 | command: 6 | - --host 7 | - 0.0.0.0 8 | - --port 9 | - '8085' 10 | - --scheme 11 | - http 12 | - --write-timeout=600s 13 | image: semitechnologies/weaviate:${WEAVIATE_VERSION} 14 | ports: 15 | - 8085:8085 16 | restart: on-failure:0 17 | environment: 18 | PERSISTENCE_DATA_PATH: '/var/lib/weaviate' 19 | AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: 'false' 20 | AUTHENTICATION_OIDC_ENABLED: 'true' 21 | AUTHENTICATION_OIDC_CLIENT_ID: 'wcs' 22 | AUTHENTICATION_OIDC_ISSUER: 'https://auth.wcs.api.weaviate.io/auth/realms/SeMI' 23 | AUTHENTICATION_OIDC_USERNAME_CLAIM: 'email' 24 | AUTHENTICATION_OIDC_GROUPS_CLAIM: 'groups' 25 | AUTHORIZATION_ADMINLIST_ENABLED: 'true' 26 | AUTHORIZATION_ADMINLIST_USERS: 'oidc-test-user@weaviate.io' 27 | AUTHENTICATION_OIDC_SCOPES: 'openid,email' 28 | AUTHENTICATION_APIKEY_ENABLED: 'true' 29 | AUTHENTICATION_APIKEY_ALLOWED_KEYS: 'my-secret-key' 30 | AUTHENTICATION_APIKEY_USERS: 'oidc-test-user@weaviate.io' 31 | DISABLE_TELEMETRY: 'true' 32 | ... 33 | -------------------------------------------------------------------------------- /ci/docker-compose.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: '3.4' 3 | services: 4 | weaviate: 5 | command: 6 | - --host 7 | - 0.0.0.0 8 | - --port 9 | - '8080' 10 | - --scheme 11 | - http 12 | - --write-timeout=600s 13 | image: semitechnologies/weaviate:${WEAVIATE_VERSION} 14 | ports: 15 | - "8080:8080" 16 | - "50051:50051" 17 | restart: on-failure:0 18 | environment: 19 | CONTEXTIONARY_URL: contextionary:9999 20 | QUERY_DEFAULTS_LIMIT: 25 21 | AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: 'true' 22 | PERSISTENCE_DATA_PATH: '/var/lib/weaviate' 23 | DEFAULT_VECTORIZER_MODULE: 'text2vec-contextionary' 24 | ENABLE_MODULES: text2vec-contextionary,backup-filesystem,generative-cohere,reranker-cohere 25 | BACKUP_FILESYSTEM_PATH: "/tmp/backups" 26 | CLUSTER_GOSSIP_BIND_PORT: "7100" 27 | CLUSTER_DATA_BIND_PORT: "7101" 28 | CLUSTER_HOSTNAME: "node1" 29 | AUTOSCHEMA_ENABLED: 'false' 30 | IMAGE_INFERENCE_API: "http://i2v-neural:8080" 31 | DISABLE_TELEMETRY: 'true' 32 | contextionary: 33 | environment: 34 | OCCURRENCE_WEIGHT_LINEAR_FACTOR: 0.75 35 | EXTENSIONS_STORAGE_MODE: weaviate 36 | EXTENSIONS_STORAGE_ORIGIN: http://weaviate:8080 37 | NEIGHBOR_OCCURRENCE_IGNORE_PERCENTILE: 5 38 | ENABLE_COMPOUND_SPLITTING: 'false' 39 | image: semitechnologies/contextionary:en0.16.0-v1.2.0 40 | ports: 41 | - 9999:9999 42 | ... 43 | -------------------------------------------------------------------------------- /ci/proxy/grpc.yaml: -------------------------------------------------------------------------------- 1 | # This proxy configuration is one that allows the use of a gRPC proxy between Weaviate and the client. 2 | # It is used in the CI/CD pipeline to test the gRPC proxy functionality of the client. 3 | # It follows the method as described here: https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/http/upgrades#connect-support 4 | # where special attention should be paid to the fact that we are using a terminating HTTP/2 connection, 5 | # as in this example: https://github.com/envoyproxy/envoy/blob/8e93d16d433d3364c2b000dc9067ffc400e8f0d6/configs/terminate_http2_connect.yaml, 6 | # because Weaviate itself is not capable of handling CONNECT requests. So Envoy instead upgrades these to POSTs and sends them on 7 | admin: 8 | address: 9 | socket_address: 10 | protocol: TCP 11 | address: 127.0.0.1 12 | port_value: 9902 13 | static_resources: 14 | listeners: 15 | - name: proxy 16 | address: 17 | socket_address: 18 | protocol: TCP 19 | address: 0.0.0.0 20 | port_value: 10000 21 | filter_chains: 22 | - filters: 23 | - name: envoy.filters.network.http_connection_manager 24 | typed_config: 25 | "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager 26 | stat_prefix: ingress_http 27 | route_config: 28 | name: local_route 29 | virtual_hosts: 30 | - name: local_service 31 | domains: 32 | - "*" 33 | routes: 34 | - match: 35 | connect_matcher: {} 36 | route: 37 | cluster: weaviate-grpc 38 | upgrade_configs: 39 | - upgrade_type: CONNECT 40 | connect_config: 41 | {} 42 | http_filters: 43 | - name: envoy.filters.http.router 44 | typed_config: 45 | "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router 46 | http2_protocol_options: 47 | allow_connect: true 48 | upgrade_configs: 49 | - upgrade_type: CONNECT 50 | clusters: 51 | - name: weaviate-grpc 52 | type: STRICT_DNS 53 | typed_extension_protocol_options: 54 | envoy.extensions.upstreams.http.v3.HttpProtocolOptions: 55 | "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions 56 | explicit_http_config: 57 | http2_protocol_options: {} 58 | load_assignment: 59 | cluster_name: weaviate-grpc 60 | endpoints: 61 | - lb_endpoints: 62 | - endpoint: 63 | address: 64 | socket_address: 65 | address: weaviate-proxy 66 | port_value: 8021 -------------------------------------------------------------------------------- /ci/proxy/http.yaml: -------------------------------------------------------------------------------- 1 | # This proxy configuration is one that allows the use of a gRPC proxy between Weaviate and the client. 2 | # It is used in the CI/CD pipeline to test the gRPC proxy functionality of the client. 3 | # It follows the method as described here: https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/http/upgrades#connect-support 4 | # where special attention should be paid to the fact that we are using a terminating HTTP/2 connection, 5 | # as in this example: https://github.com/envoyproxy/envoy/blob/8e93d16d433d3364c2b000dc9067ffc400e8f0d6/configs/terminate_http2_connect.yaml, 6 | # because Weaviate itself is not capable of handling CONNECT requests. So Envoy instead upgrades these to POSTs and sends them on 7 | admin: 8 | address: 9 | socket_address: 10 | protocol: TCP 11 | address: 127.0.0.1 12 | port_value: 9902 13 | static_resources: 14 | listeners: 15 | - name: proxy 16 | address: 17 | socket_address: 18 | protocol: TCP 19 | address: 0.0.0.0 20 | port_value: 10000 21 | filter_chains: 22 | - filters: 23 | - name: envoy.filters.network.http_connection_manager 24 | typed_config: 25 | "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager 26 | stat_prefix: ingress_http 27 | codec_type: HTTP1 28 | route_config: 29 | name: local_route 30 | virtual_hosts: 31 | - name: local_service 32 | domains: 33 | - "*" 34 | routes: 35 | - match: 36 | prefix: "/http" 37 | route: 38 | prefix_rewrite: "/" 39 | cluster: weaviate-http 40 | http_filters: 41 | - name: envoy.filters.http.router 42 | typed_config: 43 | "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router 44 | 45 | clusters: 46 | - name: weaviate-http 47 | type: STRICT_DNS 48 | connect_timeout: 5s 49 | lb_policy: ROUND_ROBIN 50 | load_assignment: 51 | cluster_name: weaviate-http 52 | endpoints: 53 | - lb_endpoints: 54 | - endpoint: 55 | address: 56 | socket_address: 57 | address: weaviate-proxy 58 | port_value: 8020 -------------------------------------------------------------------------------- /ci/run_dependencies.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -eou pipefail 4 | 5 | export WEAVIATE_VERSION=$1 6 | 7 | source ./ci/compose.sh 8 | 9 | echo "Stop existing session if running" 10 | compose_down_all 11 | rm -rf weaviate-data || true 12 | 13 | echo "Run Docker compose" 14 | compose_up_all 15 | 16 | echo "Wait until all containers are up" 17 | 18 | function wait(){ 19 | MAX_WAIT_SECONDS=60 20 | ALREADY_WAITING=0 21 | 22 | echo "Waiting for $1" 23 | while true; do 24 | # first check if weaviate already responds 25 | if ! curl -s $1 > /dev/null; then 26 | continue 27 | fi 28 | 29 | # endpoint available, check if it is ready 30 | HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" "$1/v1/.well-known/ready") 31 | 32 | if [ "$HTTP_STATUS" -eq 200 ]; then 33 | break 34 | else 35 | echo "Weaviate is not up yet. (waited for ${ALREADY_WAITING}s)" 36 | if [ $ALREADY_WAITING -gt $MAX_WAIT_SECONDS ]; then 37 | echo "Weaviate did not start up in $MAX_WAIT_SECONDS." 38 | exit 1 39 | else 40 | sleep 2 41 | let ALREADY_WAITING=$ALREADY_WAITING+2 42 | fi 43 | fi 44 | done 45 | 46 | echo "Weaviate is up and running!" 47 | } 48 | 49 | for port in $(all_weaviate_ports); do 50 | wait "http://localhost:$port" 51 | done 52 | 53 | echo "All containers running" 54 | -------------------------------------------------------------------------------- /ci/stop_dependencies.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -eou pipefail 4 | 5 | export WEAVIATE_VERSION=$1 6 | 7 | source ./ci/compose.sh 8 | 9 | compose_down_all 10 | rm -rf weaviate-data || true 11 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # Weaviate TypeScript Client Examples 2 | 3 | These examples reflect the most current state of the client and its features, so please make sure that you have the latest version of `weaviate-ts-client` installed 🙂 4 | 5 | ## JavaScript 6 | 7 | Usage within a CommonJS project. 8 | 9 | ## TypeScipt 10 | 11 | TypeScript & ESM JavaScript usage. 12 | -------------------------------------------------------------------------------- /examples/javascript/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | package-lock.json 3 | -------------------------------------------------------------------------------- /examples/javascript/index.js: -------------------------------------------------------------------------------- 1 | const { default: weaviate } = require('weaviate-ts-client'); 2 | 3 | const client = weaviate.client({ 4 | scheme: 'http', 5 | host: 'localhost:8080', 6 | }); 7 | 8 | console.log( 9 | JSON.stringify( 10 | new weaviate.AuthAccessTokenCredentials({ 11 | accessToken: 'token123', 12 | expiresIn: 123, 13 | }) 14 | ) 15 | ); 16 | 17 | console.log( 18 | JSON.stringify( 19 | new weaviate.AuthUserPasswordCredentials({ 20 | username: 'user123', 21 | password: 'password', 22 | }) 23 | ) 24 | ); 25 | 26 | console.log( 27 | JSON.stringify( 28 | new weaviate.AuthClientCredentials({ 29 | clientSecret: 'secret123', 30 | }) 31 | ) 32 | ); 33 | 34 | console.log(JSON.stringify(new weaviate.ApiKey('abcd1234'))); 35 | 36 | client.misc 37 | .metaGetter() 38 | .do() 39 | .then((res) => console.log(`res: ${JSON.stringify(res)}`)); 40 | -------------------------------------------------------------------------------- /examples/javascript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "weaviate-js-example", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "dependencies": { 7 | "weaviate-ts-client": "latest" 8 | }, 9 | "scripts": { 10 | "start": "node index.js" 11 | }, 12 | "author": "", 13 | "license": "ISC" 14 | } 15 | -------------------------------------------------------------------------------- /examples/typescript/.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | package-lock.json 4 | -------------------------------------------------------------------------------- /examples/typescript/index.ts: -------------------------------------------------------------------------------- 1 | import weaviate, { 2 | ApiKey, 3 | AuthAccessTokenCredentials, 4 | AuthClientCredentials, 5 | AuthUserPasswordCredentials, 6 | generateUuid5, 7 | } from 'weaviate-ts-client'; 8 | 9 | const client = weaviate.client({ 10 | scheme: 'http', 11 | host: 'localhost:8080', 12 | }); 13 | 14 | console.log( 15 | JSON.stringify( 16 | new AuthAccessTokenCredentials({ 17 | accessToken: 'token123', 18 | expiresIn: 123, 19 | }) 20 | ) 21 | ); 22 | 23 | console.log( 24 | JSON.stringify( 25 | new AuthUserPasswordCredentials({ 26 | username: 'user123', 27 | password: 'password', 28 | }) 29 | ) 30 | ); 31 | 32 | console.log( 33 | JSON.stringify( 34 | new AuthClientCredentials({ 35 | clientSecret: 'secret123', 36 | }) 37 | ) 38 | ); 39 | 40 | console.log(JSON.stringify(new ApiKey('abcd1234'))); 41 | console.log(generateUuid5('55dfccce-0142-4807-a1ff-60be9b38f5cc', 'the-best-namespace')); 42 | 43 | client.misc 44 | .metaGetter() 45 | .do() 46 | .then((res: any) => console.log(`res: ${JSON.stringify(res)}`)); 47 | -------------------------------------------------------------------------------- /examples/typescript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "weaviate-ts-example", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "dist/index.js", 6 | "types": "dist/index.d.ts", 7 | "type": "module", 8 | "dependencies": { 9 | "weaviate-ts-client": "latest" 10 | }, 11 | "scripts": { 12 | "start": "tsc && node dist/index.js" 13 | }, 14 | "author": "", 15 | "license": "ISC", 16 | "devDependencies": { 17 | "typescript": "^4.9.5" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /examples/typescript/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "strict": true, 5 | "preserveConstEnums": true, 6 | "noEmit": false, 7 | "sourceMap": false, 8 | "module":"ES2022", 9 | "moduleResolution":"node", 10 | "esModuleInterop": true, 11 | "skipLibCheck": true, 12 | "forceConsistentCasingInFileNames": true, 13 | "isolatedModules": true, 14 | "outDir": "./dist" 15 | }, 16 | "include": ["**/*"], 17 | "exclude": ["node_modules"] 18 | } 19 | -------------------------------------------------------------------------------- /jest.config.ts: -------------------------------------------------------------------------------- 1 | import { JestConfigWithTsJest } from 'ts-jest'; 2 | 3 | const config: JestConfigWithTsJest = { 4 | clearMocks: false, 5 | collectCoverage: false, 6 | coverageDirectory: 'coverage', 7 | coveragePathIgnorePatterns: ['/node_modules/', '/dist/', '/src/proto'], 8 | coverageProvider: 'v8', 9 | preset: 'ts-jest/presets/default-esm', // or other ESM presets 10 | moduleNameMapper: { 11 | '^(\\.{1,2}/.*)\\.js$': '$1', 12 | }, 13 | transform: { 14 | // '^.+\\.[tj]sx?$' to process js/ts with `ts-jest` 15 | // '^.+\\.m?[tj]sx?$' to process js/ts/mjs/mts with `ts-jest` 16 | '^.+\\.tsx?$': [ 17 | 'ts-jest', 18 | { 19 | useESM: true, 20 | }, 21 | ], 22 | }, 23 | testEnvironment: 'node', 24 | testMatch: ['**/*.test.ts'], 25 | testTimeout: 100000, 26 | }; 27 | 28 | export default config; 29 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weaviate/typescript-client/f7591d649b05929c5a45b601fecd468935447b9a/public/favicon.ico -------------------------------------------------------------------------------- /src/backup/backupCreateStatusGetter.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import { WeaviateInvalidInputError } from '../errors.js'; 3 | import { BackupCreateStatusResponse } from '../openapi/types.js'; 4 | import { CommandBase } from '../validation/commandBase.js'; 5 | import { Backend } from './index.js'; 6 | import { validateBackend, validateBackupId } from './validation.js'; 7 | 8 | export default class BackupCreateStatusGetter extends CommandBase { 9 | private backend?: Backend; 10 | private backupId?: string; 11 | 12 | constructor(client: Connection) { 13 | super(client); 14 | } 15 | 16 | withBackend(backend: Backend) { 17 | this.backend = backend; 18 | return this; 19 | } 20 | 21 | withBackupId(backupId: string) { 22 | this.backupId = backupId; 23 | return this; 24 | } 25 | 26 | validate = (): void => { 27 | this.addErrors([...validateBackend(this.backend), ...validateBackupId(this.backupId)]); 28 | }; 29 | 30 | do = (): Promise => { 31 | this.validate(); 32 | if (this.errors.length > 0) { 33 | return Promise.reject(new WeaviateInvalidInputError('invalid usage: ' + this.errors.join(', '))); 34 | } 35 | return this.client.get(this._path()) as Promise; 36 | }; 37 | 38 | private _path = (): string => { 39 | return `/backups/${this.backend}/${this.backupId}`; 40 | }; 41 | } 42 | -------------------------------------------------------------------------------- /src/backup/backupGetter.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import { WeaviateInvalidInputError } from '../errors.js'; 3 | import { BackupCreateResponse } from '../openapi/types.js'; 4 | import { CommandBase } from '../validation/commandBase.js'; 5 | import { Backend } from './index.js'; 6 | import { validateBackend } from './validation.js'; 7 | 8 | export default class BackupGetter extends CommandBase { 9 | private backend?: Backend; 10 | 11 | constructor(client: Connection) { 12 | super(client); 13 | } 14 | 15 | withBackend(backend: Backend) { 16 | this.backend = backend; 17 | return this; 18 | } 19 | 20 | validate = (): void => { 21 | this.addErrors(validateBackend(this.backend)); 22 | }; 23 | 24 | do = (): Promise => { 25 | this.validate(); 26 | if (this.errors.length > 0) { 27 | return Promise.reject(new WeaviateInvalidInputError('invalid usage: ' + this.errors.join(', '))); 28 | } 29 | 30 | return this.client.get(this._path()); 31 | }; 32 | 33 | private _path = (): string => { 34 | return `/backups/${this.backend}`; 35 | }; 36 | } 37 | -------------------------------------------------------------------------------- /src/backup/backupRestoreStatusGetter.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import { WeaviateInvalidInputError } from '../errors.js'; 3 | import { BackupRestoreStatusResponse } from '../openapi/types.js'; 4 | import { CommandBase } from '../validation/commandBase.js'; 5 | import { Backend } from './index.js'; 6 | import { validateBackend, validateBackupId } from './validation.js'; 7 | 8 | export default class BackupRestoreStatusGetter extends CommandBase { 9 | private backend?: Backend; 10 | private backupId?: string; 11 | 12 | constructor(client: Connection) { 13 | super(client); 14 | } 15 | 16 | withBackend(backend: Backend) { 17 | this.backend = backend; 18 | return this; 19 | } 20 | 21 | withBackupId(backupId: string) { 22 | this.backupId = backupId; 23 | return this; 24 | } 25 | 26 | validate = (): void => { 27 | this.addErrors([...validateBackend(this.backend), ...validateBackupId(this.backupId)]); 28 | }; 29 | 30 | do = (): Promise => { 31 | this.validate(); 32 | if (this.errors.length > 0) { 33 | return Promise.reject(new WeaviateInvalidInputError('invalid usage: ' + this.errors.join(', '))); 34 | } 35 | 36 | return this.client.get(this._path()); 37 | }; 38 | 39 | private _path = (): string => { 40 | return `/backups/${this.backend}/${this.backupId}/restore`; 41 | }; 42 | } 43 | -------------------------------------------------------------------------------- /src/backup/index.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import BackupCreateStatusGetter from './backupCreateStatusGetter.js'; 3 | import BackupCreator from './backupCreator.js'; 4 | import BackupRestoreStatusGetter from './backupRestoreStatusGetter.js'; 5 | import BackupRestorer from './backupRestorer.js'; 6 | 7 | export type Backend = 'filesystem' | 's3' | 'gcs' | 'azure'; 8 | export type BackupStatus = 'STARTED' | 'TRANSFERRING' | 'TRANSFERRED' | 'SUCCESS' | 'FAILED'; 9 | export type BackupCompressionLevel = 'DefaultCompression' | 'BestSpeed' | 'BestCompression'; 10 | 11 | export interface Backup { 12 | creator: () => BackupCreator; 13 | createStatusGetter: () => BackupCreateStatusGetter; 14 | restorer: () => BackupRestorer; 15 | restoreStatusGetter: () => BackupRestoreStatusGetter; 16 | } 17 | 18 | const backup = (client: Connection): Backup => { 19 | return { 20 | creator: () => new BackupCreator(client, new BackupCreateStatusGetter(client)), 21 | createStatusGetter: () => new BackupCreateStatusGetter(client), 22 | restorer: () => new BackupRestorer(client, new BackupRestoreStatusGetter(client)), 23 | restoreStatusGetter: () => new BackupRestoreStatusGetter(client), 24 | }; 25 | }; 26 | 27 | export default backup; 28 | export { default as BackupCreateStatusGetter } from './backupCreateStatusGetter.js'; 29 | export { default as BackupCreator } from './backupCreator.js'; 30 | export { default as BackupRestoreStatusGetter } from './backupRestoreStatusGetter.js'; 31 | export { default as BackupRestorer } from './backupRestorer.js'; 32 | -------------------------------------------------------------------------------- /src/backup/validation.ts: -------------------------------------------------------------------------------- 1 | import { isValidStringProperty } from '../validation/string.js'; 2 | 3 | export function validateIncludeClassNames(classNames?: string[]) { 4 | if (Array.isArray(classNames)) { 5 | const errors: any[] = []; 6 | classNames.forEach((className) => { 7 | if (!isValidStringProperty(className)) { 8 | errors.push('string className invalid - set with .withIncludeClassNames(...classNames)'); 9 | } 10 | }); 11 | return errors; 12 | } 13 | if (classNames !== null && classNames !== undefined) { 14 | return ['strings classNames invalid - set with .withIncludeClassNames(...classNames)']; 15 | } 16 | return []; 17 | } 18 | 19 | export function validateExcludeClassNames(classNames?: string[]) { 20 | if (Array.isArray(classNames)) { 21 | const errors: any[] = []; 22 | classNames.forEach((className) => { 23 | if (!isValidStringProperty(className)) { 24 | errors.push('string className invalid - set with .withExcludeClassNames(...classNames)'); 25 | } 26 | }); 27 | return errors; 28 | } 29 | if (classNames !== null && classNames !== undefined) { 30 | return ['strings classNames invalid - set with .withExcludeClassNames(...classNames)']; 31 | } 32 | return []; 33 | } 34 | 35 | export function validateBackend(backend?: string) { 36 | if (!isValidStringProperty(backend)) { 37 | return ['string backend must set - set with .withBackend(backend)']; 38 | } 39 | return []; 40 | } 41 | 42 | export function validateBackupId(backupId?: string) { 43 | if (!isValidStringProperty(backupId)) { 44 | return ['string backupId must be set - set with .withBackupId(backupId)']; 45 | } 46 | return []; 47 | } 48 | -------------------------------------------------------------------------------- /src/batch/index.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import { BeaconPath } from '../utils/beaconPath.js'; 3 | import { DbVersionSupport } from '../utils/dbVersion.js'; 4 | import ObjectsBatchDeleter from './objectsBatchDeleter.js'; 5 | import ObjectsBatcher from './objectsBatcher.js'; 6 | import ReferencePayloadBuilder from './referencePayloadBuilder.js'; 7 | import ReferencesBatcher from './referencesBatcher.js'; 8 | 9 | export type DeleteOutput = 'verbose' | 'minimal'; 10 | export type DeleteResultStatus = 'SUCCESS' | 'FAILED' | 'DRYRUN'; 11 | 12 | export interface Batch { 13 | objectsBatcher: () => ObjectsBatcher; 14 | objectsBatchDeleter: () => ObjectsBatchDeleter; 15 | referencesBatcher: () => ReferencesBatcher; 16 | referencePayloadBuilder: () => ReferencePayloadBuilder; 17 | } 18 | 19 | const batch = (client: Connection, dbVersionSupport: DbVersionSupport): Batch => { 20 | const beaconPath = new BeaconPath(dbVersionSupport); 21 | 22 | return { 23 | objectsBatcher: () => new ObjectsBatcher(client), 24 | objectsBatchDeleter: () => new ObjectsBatchDeleter(client), 25 | referencesBatcher: () => new ReferencesBatcher(client, beaconPath), 26 | referencePayloadBuilder: () => new ReferencePayloadBuilder(client), 27 | }; 28 | }; 29 | 30 | export default batch; 31 | export { default as ObjectsBatchDeleter } from './objectsBatchDeleter.js'; 32 | export { default as ObjectsBatcher } from './objectsBatcher.js'; 33 | export { default as ReferencesBatcher } from './referencesBatcher.js'; 34 | -------------------------------------------------------------------------------- /src/batch/objectsBatchDeleter.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import { ConsistencyLevel } from '../data/replication.js'; 3 | import { BatchDelete, BatchDeleteResponse, WhereFilter } from '../openapi/types.js'; 4 | import { CommandBase } from '../validation/commandBase.js'; 5 | import { isValidStringProperty } from '../validation/string.js'; 6 | import { DeleteOutput } from './index.js'; 7 | import { buildObjectsPath } from './path.js'; 8 | 9 | export default class ObjectsBatchDeleter extends CommandBase { 10 | private className?: string; 11 | private consistencyLevel?: ConsistencyLevel; 12 | private dryRun?: boolean; 13 | private output?: DeleteOutput; 14 | private whereFilter?: WhereFilter; 15 | private tenant?: string; 16 | 17 | constructor(client: Connection) { 18 | super(client); 19 | } 20 | 21 | withClassName(className: string) { 22 | this.className = className; 23 | return this; 24 | } 25 | 26 | withWhere(whereFilter: WhereFilter) { 27 | this.whereFilter = whereFilter; 28 | return this; 29 | } 30 | 31 | withOutput(output: DeleteOutput) { 32 | this.output = output; 33 | return this; 34 | } 35 | 36 | withDryRun(dryRun: boolean) { 37 | this.dryRun = dryRun; 38 | return this; 39 | } 40 | 41 | withConsistencyLevel = (cl: ConsistencyLevel) => { 42 | this.consistencyLevel = cl; 43 | return this; 44 | }; 45 | 46 | withTenant(tenant: string) { 47 | this.tenant = tenant; 48 | return this; 49 | } 50 | 51 | payload = (): BatchDelete => { 52 | return { 53 | match: { 54 | class: this.className, 55 | where: this.whereFilter, 56 | }, 57 | output: this.output, 58 | dryRun: this.dryRun, 59 | }; 60 | }; 61 | 62 | validateClassName = (): void => { 63 | if (!isValidStringProperty(this.className)) { 64 | this.addError('string className must be set - set with .withClassName(className)'); 65 | } 66 | }; 67 | 68 | validateWhereFilter = (): void => { 69 | if (typeof this.whereFilter != 'object') { 70 | this.addError('object where must be set - set with .withWhere(whereFilter)'); 71 | } 72 | }; 73 | 74 | validate = (): void => { 75 | this.validateClassName(); 76 | this.validateWhereFilter(); 77 | }; 78 | 79 | do = (): Promise => { 80 | this.validate(); 81 | if (this.errors.length > 0) { 82 | return Promise.reject(new Error('invalid usage: ' + this.errors.join(', '))); 83 | } 84 | const params = new URLSearchParams(); 85 | if (this.consistencyLevel) { 86 | params.set('consistency_level', this.consistencyLevel); 87 | } 88 | if (this.tenant) { 89 | params.set('tenant', this.tenant); 90 | } 91 | const path = buildObjectsPath(params); 92 | return this.client.delete(path, this.payload(), true); 93 | }; 94 | } 95 | -------------------------------------------------------------------------------- /src/batch/objectsBatcher.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import { ConsistencyLevel } from '../data/replication.js'; 3 | import { BatchRequest, WeaviateObject, WeaviateObjectsGet } from '../openapi/types.js'; 4 | import { CommandBase } from '../validation/commandBase.js'; 5 | import { buildObjectsPath } from './path.js'; 6 | 7 | export default class ObjectsBatcher extends CommandBase { 8 | private consistencyLevel?: ConsistencyLevel; 9 | public objects: WeaviateObject[]; 10 | 11 | constructor(client: Connection) { 12 | super(client); 13 | this.objects = []; 14 | } 15 | 16 | /** 17 | * can be called as: 18 | * - withObjects(...[obj1, obj2, obj3]) 19 | * - withObjects(obj1, obj2, obj3) 20 | * - withObjects(obj1) 21 | * @param {...WeaviateObject[]} objects 22 | */ 23 | withObjects(...objects: WeaviateObject[]) { 24 | let objs = objects; 25 | if (objects.length && Array.isArray(objects[0])) { 26 | objs = objects[0]; 27 | } 28 | this.objects = [...this.objects, ...objs]; 29 | return this; 30 | } 31 | 32 | withObject(object: WeaviateObject) { 33 | return this.withObjects(object); 34 | } 35 | 36 | withConsistencyLevel = (cl: ConsistencyLevel) => { 37 | this.consistencyLevel = cl; 38 | return this; 39 | }; 40 | 41 | payload = (): BatchRequest => ({ 42 | objects: this.objects, 43 | }); 44 | 45 | validateObjectCount = (): void => { 46 | if (this.objects.length == 0) { 47 | this.addError('need at least one object to send a request, add one with .withObject(obj)'); 48 | } 49 | }; 50 | 51 | validate = (): void => { 52 | this.validateObjectCount(); 53 | }; 54 | 55 | do = (): Promise => { 56 | this.validate(); 57 | if (this.errors.length > 0) { 58 | return Promise.reject(new Error('invalid usage: ' + this.errors.join(', '))); 59 | } 60 | const params = new URLSearchParams(); 61 | if (this.consistencyLevel) { 62 | params.set('consistency_level', this.consistencyLevel); 63 | } 64 | const path = buildObjectsPath(params); 65 | return this.client.postReturn(path, this.payload()); 66 | }; 67 | } 68 | -------------------------------------------------------------------------------- /src/batch/path.test.ts: -------------------------------------------------------------------------------- 1 | import { buildObjectsPath, buildRefsPath } from './path.js'; 2 | 3 | describe('paths', () => { 4 | it('builds batch objects without params', () => { 5 | const path = buildObjectsPath(new URLSearchParams()); 6 | expect(path).toEqual('/batch/objects'); 7 | }); 8 | 9 | it('builds batch objects with params', () => { 10 | const path = buildObjectsPath( 11 | new URLSearchParams({ 12 | consistency_level: 'ONE', 13 | }) 14 | ); 15 | expect(path).toEqual('/batch/objects?consistency_level=ONE'); 16 | }); 17 | 18 | it('builds batch references without params', () => { 19 | const path = buildRefsPath(new URLSearchParams()); 20 | expect(path).toEqual('/batch/references'); 21 | }); 22 | 23 | it('builds batch object with params', () => { 24 | const path = buildRefsPath( 25 | new URLSearchParams({ 26 | consistency_level: 'ONE', 27 | }) 28 | ); 29 | expect(path).toEqual('/batch/references?consistency_level=ONE'); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /src/batch/path.ts: -------------------------------------------------------------------------------- 1 | export function buildObjectsPath(queryParams: any): string { 2 | const path = '/batch/objects'; 3 | return buildPath(path, queryParams); 4 | } 5 | 6 | export function buildRefsPath(queryParams: any): string { 7 | const path = '/batch/references'; 8 | return buildPath(path, queryParams); 9 | } 10 | 11 | function buildPath(path: string, queryParams: any): string { 12 | if (queryParams && queryParams.toString() != '') { 13 | path = `${path}?${queryParams.toString()}`; 14 | } 15 | return path; 16 | } 17 | -------------------------------------------------------------------------------- /src/batch/referencePayloadBuilder.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import { BatchReference } from '../openapi/types.js'; 3 | import { CommandBase } from '../validation/commandBase.js'; 4 | import { isValidStringProperty } from '../validation/string.js'; 5 | 6 | export default class ReferencesBatcher extends CommandBase { 7 | private fromClassName?: string; 8 | private fromId?: string; 9 | private fromRefProp?: string; 10 | private toClassName?: string; 11 | private toId?: string; 12 | 13 | constructor(client: Connection) { 14 | super(client); 15 | } 16 | 17 | withFromId = (id: string) => { 18 | this.fromId = id; 19 | return this; 20 | }; 21 | 22 | withToId = (id: string) => { 23 | this.toId = id; 24 | return this; 25 | }; 26 | 27 | withFromClassName = (className: string) => { 28 | this.fromClassName = className; 29 | return this; 30 | }; 31 | 32 | withFromRefProp = (refProp: string) => { 33 | this.fromRefProp = refProp; 34 | return this; 35 | }; 36 | 37 | withToClassName(className: string) { 38 | this.toClassName = className; 39 | return this; 40 | } 41 | 42 | validateIsSet = (prop: string | undefined | null, name: string, setter: string): void => { 43 | if (prop == undefined || prop == null || prop.length == 0) { 44 | this.addError(`${name} must be set - set with ${setter}`); 45 | } 46 | }; 47 | 48 | validate = (): void => { 49 | this.validateIsSet(this.fromId, 'fromId', '.withFromId(id)'); 50 | this.validateIsSet(this.toId, 'toId', '.withToId(id)'); 51 | this.validateIsSet(this.fromClassName, 'fromClassName', '.withFromClassName(className)'); 52 | this.validateIsSet(this.fromRefProp, 'fromRefProp', '.withFromRefProp(refProp)'); 53 | }; 54 | 55 | payload = (): BatchReference => { 56 | this.validate(); 57 | if (this.errors.length > 0) { 58 | throw new Error(this.errors.join(', ')); 59 | } 60 | 61 | let beaconTo = `weaviate://localhost`; 62 | if (isValidStringProperty(this.toClassName)) { 63 | beaconTo = `${beaconTo}/${this.toClassName}`; 64 | } 65 | 66 | return { 67 | from: `weaviate://localhost/${this.fromClassName}/${this.fromId}/${this.fromRefProp}`, 68 | to: `${beaconTo}/${this.toId}`, 69 | }; 70 | }; 71 | 72 | do = (): Promise => { 73 | return Promise.reject(new Error('Should never be called')); 74 | }; 75 | } 76 | -------------------------------------------------------------------------------- /src/batch/referencesBatcher.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import { ConsistencyLevel } from '../data/replication.js'; 3 | import { BatchReference, BatchReferenceResponse } from '../openapi/types.js'; 4 | import { BeaconPath } from '../utils/beaconPath.js'; 5 | import { CommandBase } from '../validation/commandBase.js'; 6 | import { buildRefsPath } from './path.js'; 7 | 8 | export default class ReferencesBatcher extends CommandBase { 9 | private beaconPath: BeaconPath; 10 | private consistencyLevel?: ConsistencyLevel; 11 | public references: BatchReference[]; 12 | 13 | constructor(client: Connection, beaconPath: BeaconPath) { 14 | super(client); 15 | this.beaconPath = beaconPath; 16 | this.references = []; 17 | } 18 | 19 | /** 20 | * can be called as: 21 | * - withReferences(...[ref1, ref2, ref3]) 22 | * - withReferences(ref1, ref2, ref3) 23 | * - withReferences(ref1) 24 | * @param {...BatchReference[]} references 25 | */ 26 | withReferences(...references: BatchReference[]) { 27 | let refs = references; 28 | if (references.length && Array.isArray(references[0])) { 29 | refs = references[0]; 30 | } 31 | this.references = [...this.references, ...refs]; 32 | return this; 33 | } 34 | 35 | withReference(reference: BatchReference) { 36 | return this.withReferences(reference); 37 | } 38 | 39 | withConsistencyLevel = (cl: ConsistencyLevel) => { 40 | this.consistencyLevel = cl; 41 | return this; 42 | }; 43 | 44 | payload = (): BatchReference[] => this.references; 45 | 46 | validateReferenceCount = (): void => { 47 | if (this.references.length == 0) { 48 | this.addError('need at least one reference to send a request, add one with .withReference(obj)'); 49 | } 50 | }; 51 | 52 | validate = () => { 53 | this.validateReferenceCount(); 54 | }; 55 | 56 | do = (): Promise => { 57 | this.validate(); 58 | if (this.errors.length > 0) { 59 | return Promise.reject(new Error('invalid usage: ' + this.errors.join(', '))); 60 | } 61 | const params = new URLSearchParams(); 62 | if (this.consistencyLevel) { 63 | params.set('consistency_level', this.consistencyLevel); 64 | } 65 | const path = buildRefsPath(params); 66 | const payloadPromise = Promise.all(this.references.map((ref) => this.rebuildReferencePromise(ref))); 67 | 68 | return payloadPromise.then((payload) => this.client.postReturn(path, payload)); 69 | }; 70 | 71 | rebuildReferencePromise = (reference: BatchReference): Promise => { 72 | // eslint-disable-next-line @typescript-eslint/no-non-null-assertion 73 | return this.beaconPath.rebuild(reference.to!).then((beaconTo: any) => ({ 74 | from: reference.from, 75 | to: beaconTo, 76 | tenant: reference.tenant, 77 | })); 78 | }; 79 | } 80 | -------------------------------------------------------------------------------- /src/c11y/conceptsGetter.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import { C11yWordsResponse } from '../openapi/types.js'; 3 | import { CommandBase } from '../validation/commandBase.js'; 4 | 5 | export default class ConceptsGetter extends CommandBase { 6 | private concept?: string; 7 | 8 | constructor(client: Connection) { 9 | super(client); 10 | } 11 | 12 | validateIsSet = (prop: string | undefined | null, name: string, setter: string) => { 13 | if (prop == undefined || prop == null || prop.length == 0) { 14 | this.addError(`${name} must be set - set with ${setter}`); 15 | } 16 | }; 17 | 18 | withConcept = (concept: string) => { 19 | this.concept = concept; 20 | return this; 21 | }; 22 | 23 | validate = (): void => { 24 | this.validateIsSet(this.concept, 'concept', 'withConcept(concept)'); 25 | }; 26 | 27 | do = (): Promise => { 28 | this.validate(); 29 | if (this.errors.length > 0) { 30 | return Promise.reject(new Error('invalid usage: ' + this.errors.join(', '))); 31 | } 32 | 33 | const path = `/modules/text2vec-contextionary/concepts/${this.concept}`; 34 | return this.client.get(path); 35 | }; 36 | } 37 | -------------------------------------------------------------------------------- /src/c11y/extensionCreator.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import { C11yExtension } from '../openapi/types.js'; 3 | import { CommandBase } from '../validation/commandBase.js'; 4 | 5 | export default class ExtensionCreator extends CommandBase { 6 | private concept?: string; 7 | private definition?: string; 8 | private weight?: number; 9 | 10 | constructor(client: Connection) { 11 | super(client); 12 | } 13 | 14 | withConcept = (concept: string) => { 15 | this.concept = concept; 16 | return this; 17 | }; 18 | 19 | withDefinition = (definition: string) => { 20 | this.definition = definition; 21 | return this; 22 | }; 23 | 24 | withWeight = (weight: number) => { 25 | this.weight = weight; 26 | return this; 27 | }; 28 | 29 | validateIsSet = (prop: string | undefined | null, name: string, setter: string): void => { 30 | if (prop == undefined || prop == null || prop.length == 0) { 31 | this.addError(`${name} must be set - set with ${setter}`); 32 | } 33 | }; 34 | 35 | validate = (): void => { 36 | this.validateIsSet(this.concept, 'concept', 'withConcept(concept)'); 37 | this.validateIsSet(this.definition, 'definition', 'withDefinition(definition)'); 38 | this.validateIsSet(this.weight?.toString() || '', 'weight', 'withWeight(weight)'); 39 | }; 40 | 41 | payload = (): C11yExtension => ({ 42 | concept: this.concept, 43 | definition: this.definition, 44 | weight: this.weight, 45 | }); 46 | 47 | do = (): Promise => { 48 | this.validate(); 49 | if (this.errors.length > 0) { 50 | return Promise.reject(new Error('invalid usage: ' + this.errors.join(', '))); 51 | } 52 | 53 | const path = `/modules/text2vec-contextionary/extensions`; 54 | return this.client.postReturn(path, this.payload()); 55 | }; 56 | } 57 | -------------------------------------------------------------------------------- /src/c11y/index.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import ConceptsGetter from './conceptsGetter.js'; 3 | import ExtensionCreator from './extensionCreator.js'; 4 | 5 | export interface C11y { 6 | conceptsGetter: () => ConceptsGetter; 7 | extensionCreator: () => ExtensionCreator; 8 | } 9 | 10 | const c11y = (client: Connection): C11y => { 11 | return { 12 | conceptsGetter: () => new ConceptsGetter(client), 13 | extensionCreator: () => new ExtensionCreator(client), 14 | }; 15 | }; 16 | 17 | export default c11y; 18 | export { default as ConceptsGetter } from './conceptsGetter.js'; 19 | export { default as ExtensionCreator } from './extensionCreator.js'; 20 | -------------------------------------------------------------------------------- /src/c11y/journey.test.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-non-null-assertion */ 2 | import { C11yExtension, C11yWordsResponse } from '../openapi/types.js'; 3 | import weaviate from '../v2/index.js'; 4 | 5 | describe('c11y endpoints', () => { 6 | const client = weaviate.client({ 7 | scheme: 'http', 8 | host: 'localhost:8080', 9 | }); 10 | 11 | it('displays info about a concept', () => { 12 | return client.c11y 13 | .conceptsGetter() 14 | .withConcept('car') 15 | .do() 16 | .then((res: C11yWordsResponse) => { 17 | expect(res.individualWords![0].word!).toEqual('car'); 18 | }); 19 | }); 20 | 21 | it('extends the c11y with a custom concept', () => { 22 | return client.c11y 23 | .extensionCreator() 24 | .withConcept('clientalmostdonehappyness') 25 | .withDefinition( 26 | 'the happyness you feel when the Weaviate TypeScript client ' + 27 | 'is almost complete and ready to be released' 28 | ) 29 | .withWeight(1) 30 | .do() 31 | .then((res: C11yExtension) => { 32 | expect(res).toEqual({ 33 | concept: 'clientalmostdonehappyness', 34 | definition: 35 | 'the happyness you feel when the Weaviate TypeScript client ' + 36 | 'is almost complete and ready to be released', 37 | weight: 1, 38 | }); 39 | }); 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /src/classifications/getter.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import { Classification } from '../openapi/types.js'; 3 | import { CommandBase } from '../validation/commandBase.js'; 4 | 5 | export default class ClassificationsGetter extends CommandBase { 6 | private id?: string; 7 | 8 | constructor(client: Connection) { 9 | super(client); 10 | } 11 | 12 | withId = (id: string) => { 13 | this.id = id; 14 | return this; 15 | }; 16 | 17 | validateIsSet = (prop: string | undefined | null, name: string, setter: string): void => { 18 | if (prop == undefined || prop == null || prop.length == 0) { 19 | this.addError(`${name} must be set - set with ${setter}`); 20 | } 21 | }; 22 | 23 | validateId = (): void => { 24 | this.validateIsSet(this.id, 'id', '.withId(id)'); 25 | }; 26 | 27 | validate = (): void => { 28 | this.validateId(); 29 | }; 30 | 31 | do = (): Promise => { 32 | this.validate(); 33 | if (this.errors.length > 0) { 34 | return Promise.reject(new Error('invalid usage: ' + this.errors.join(', '))); 35 | } 36 | 37 | const path = `/classifications/${this.id}`; 38 | return this.client.get(path); 39 | }; 40 | } 41 | -------------------------------------------------------------------------------- /src/classifications/index.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import ClassificationsGetter from './getter.js'; 3 | import ClassificationsScheduler from './scheduler.js'; 4 | 5 | export interface Classifications { 6 | scheduler: () => ClassificationsScheduler; 7 | getter: () => ClassificationsGetter; 8 | } 9 | 10 | const data = (client: Connection): Classifications => { 11 | return { 12 | scheduler: () => new ClassificationsScheduler(client), 13 | getter: () => new ClassificationsGetter(client), 14 | }; 15 | }; 16 | 17 | export default data; 18 | export { default as ClassificationsGetter } from './getter.js'; 19 | export { default as ClassificationsScheduler } from './scheduler.js'; 20 | -------------------------------------------------------------------------------- /src/cluster/index.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import NodesStatusGetter from './nodesStatusGetter.js'; 3 | 4 | export type NodeStatus = 'HEALTHY' | 'UNHEALTHY' | 'UNAVAILABLE'; 5 | 6 | export interface Cluster { 7 | nodesStatusGetter: () => NodesStatusGetter; 8 | } 9 | 10 | const cluster = (client: Connection): Cluster => { 11 | return { 12 | nodesStatusGetter: () => new NodesStatusGetter(client), 13 | }; 14 | }; 15 | 16 | export default cluster; 17 | export { default as NodesStatusGetter } from './nodesStatusGetter.js'; 18 | -------------------------------------------------------------------------------- /src/cluster/nodesStatusGetter.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import { NodesStatusResponse } from '../openapi/types.js'; 3 | import { CommandBase } from '../validation/commandBase.js'; 4 | 5 | export default class NodesStatusGetter extends CommandBase { 6 | private className?: string; 7 | private output?: string; 8 | 9 | constructor(client: Connection) { 10 | super(client); 11 | } 12 | 13 | withClassName = (className: string) => { 14 | this.className = className; 15 | return this; 16 | }; 17 | 18 | withOutput = (output: 'minimal' | 'verbose') => { 19 | this.output = output; 20 | return this; 21 | }; 22 | 23 | validate() { 24 | // nothing to validate 25 | } 26 | 27 | do = (): Promise => { 28 | let path = '/nodes'; 29 | if (this.className) { 30 | path = `${path}/${this.className}`; 31 | } 32 | if (this.output) { 33 | path = `${path}?output=${this.output}`; 34 | } else { 35 | path = `${path}?output=verbose`; 36 | } 37 | return this.client.get(path); 38 | }; 39 | } 40 | -------------------------------------------------------------------------------- /src/collections/backup/collection.ts: -------------------------------------------------------------------------------- 1 | import { Backend } from '../../backup/index.js'; 2 | import Connection from '../../connection/index.js'; 3 | import { WeaviateInvalidInputError } from '../../errors.js'; 4 | import { backup } from './client.js'; 5 | import { BackupReturn, BackupStatusArgs, BackupStatusReturn } from './types.js'; 6 | 7 | /** The arguments required to create and restore backups. */ 8 | export type BackupCollectionArgs = { 9 | /** The ID of the backup. */ 10 | backupId: string; 11 | /** The backend to use for the backup. */ 12 | backend: Backend; 13 | /** The collections to include in the backup. */ 14 | waitForCompletion?: boolean; 15 | }; 16 | 17 | export const backupCollection = (connection: Connection, name: string) => { 18 | const handler = backup(connection); 19 | return { 20 | create: (args: BackupCollectionArgs) => 21 | handler.create({ 22 | ...args, 23 | includeCollections: [name], 24 | }), 25 | getCreateStatus: handler.getCreateStatus, 26 | getRestoreStatus: handler.getRestoreStatus, 27 | restore: (args: BackupCollectionArgs) => 28 | handler.restore({ 29 | ...args, 30 | includeCollections: [name], 31 | }), 32 | }; 33 | }; 34 | 35 | export interface BackupCollection { 36 | /** 37 | * Create a backup of this collection. 38 | * 39 | * @param {BackupArgs} args The arguments for the request. 40 | * @returns {Promise} The response from Weaviate. 41 | * @throws {WeaviateInvalidInputError} If the input is invalid. 42 | * @throws {WeaviateBackupFailed} If the backup creation fails. 43 | * @throws {WeaviateBackupCanceled} If the backup creation is canceled. 44 | */ 45 | create(args: BackupCollectionArgs): Promise; 46 | /** 47 | * Get the status of a backup. 48 | * 49 | * @param {BackupStatusArgs} args The arguments for the request. 50 | * @returns {Promise} The status of the backup. 51 | * @throws {WeaviateInvalidInputError} If the input is invalid. 52 | */ 53 | getCreateStatus(args: BackupStatusArgs): Promise; 54 | /** 55 | * Get the status of a restore. 56 | * 57 | * @param {BackupStatusArgs} args The arguments for the request. 58 | * @returns {Promise} The status of the restore. 59 | * @throws {WeaviateInvalidInputError} If the input is invalid. 60 | */ 61 | getRestoreStatus(args: BackupStatusArgs): Promise; 62 | /** 63 | * Restore a backup of this collection. 64 | * 65 | * @param {BackupArgs} args The arguments for the request. 66 | * @returns {Promise} The response from Weaviate. 67 | * @throws {WeaviateInvalidInputError} If the input is invalid. 68 | * @throws {WeaviateBackupFailed} If the backup restoration fails. 69 | * @throws {WeaviateBackupCanceled} If the backup restoration is canceled. 70 | */ 71 | restore(args: BackupCollectionArgs): Promise; 72 | } 73 | -------------------------------------------------------------------------------- /src/collections/backup/index.ts: -------------------------------------------------------------------------------- 1 | export type { Backup } from './client.js'; 2 | export type { BackupCollection, BackupCollectionArgs } from './collection.js'; 3 | export type { BackupArgs, BackupConfigCreate, BackupConfigRestore, BackupStatusArgs } from './types.js'; 4 | -------------------------------------------------------------------------------- /src/collections/backup/types.ts: -------------------------------------------------------------------------------- 1 | import { Backend, BackupCompressionLevel } from '../../index.js'; 2 | 3 | /** The status of a backup operation */ 4 | export type BackupStatus = 'STARTED' | 'TRANSFERRING' | 'TRANSFERRED' | 'SUCCESS' | 'FAILED' | 'CANCELED'; 5 | 6 | /** The status of a backup operation */ 7 | export type BackupStatusReturn = { 8 | /** The ID of the backup */ 9 | id: string; 10 | /** The error message if the backup failed */ 11 | error?: string; 12 | /** The path to the backup */ 13 | path: string; 14 | /** The status of the backup */ 15 | status: BackupStatus; 16 | }; 17 | 18 | /** The return type of a backup creation or restoration operation */ 19 | export type BackupReturn = BackupStatusReturn & { 20 | /** The backend to which the backup was created or restored */ 21 | backend: Backend; 22 | /** The collections that were included in the backup */ 23 | collections: string[]; 24 | }; 25 | 26 | /** Configuration options available when creating a backup */ 27 | export type BackupConfigCreate = { 28 | /** The size of the chunks to use for the backup. */ 29 | chunkSize?: number; 30 | /** The standard of compression to use for the backup. */ 31 | compressionLevel?: BackupCompressionLevel; 32 | /** The percentage of CPU to use for the backup creation job. */ 33 | cpuPercentage?: number; 34 | }; 35 | 36 | /** Configuration options available when restoring a backup */ 37 | export type BackupConfigRestore = { 38 | /** The percentage of CPU to use for the backuop restoration job. */ 39 | cpuPercentage?: number; 40 | }; 41 | 42 | /** The arguments required to create and restore backups. */ 43 | export type BackupArgs = { 44 | /** The ID of the backup. */ 45 | backupId: string; 46 | /** The backend to use for the backup. */ 47 | backend: Backend; 48 | /** The collections to include in the backup. */ 49 | includeCollections?: string[]; 50 | /** The collections to exclude from the backup. */ 51 | excludeCollections?: string[]; 52 | /** Whether to wait for the backup to complete. */ 53 | waitForCompletion?: boolean; 54 | /** The configuration options for the backup. */ 55 | config?: C; 56 | }; 57 | 58 | /** The arguments required to get the status of a backup. */ 59 | export type BackupStatusArgs = { 60 | /** The ID of the backup. */ 61 | backupId: string; 62 | /** The backend to use for the backup. */ 63 | backend: Backend; 64 | }; 65 | 66 | /** The arguments required to cancel a backup. */ 67 | export type BackupCancelArgs = { 68 | /** The ID of the backup. */ 69 | backupId: string; 70 | /** The backend to use for the backup. */ 71 | backend: Backend; 72 | }; 73 | -------------------------------------------------------------------------------- /src/collections/cluster/index.ts: -------------------------------------------------------------------------------- 1 | import { NodesStatusGetter } from '../../cluster/index.js'; 2 | import Connection from '../../connection/index.js'; 3 | import { BatchStats, NodeShardStatus, NodeStats } from '../../openapi/types.js'; 4 | 5 | export type Output = 'minimal' | 'verbose' | undefined; 6 | 7 | export type NodesOptions = { 8 | /** The name of the collection to get the status of. */ 9 | collection?: string; 10 | /** Set the desired output verbosity level. Can be `minimal | verbose | undefined` with `undefined` defaulting to `minimal`. */ 11 | output: O; 12 | }; 13 | 14 | export type Node = { 15 | name: string; 16 | status: 'HEALTHY' | 'UNHEALTHY' | 'UNAVAILABLE'; 17 | version: string; 18 | gitHash: string; 19 | stats: O extends 'minimal' | undefined ? undefined : Required; 20 | batchStats: Required; 21 | shards: O extends 'minimal' | undefined ? null : Required[]; 22 | }; 23 | 24 | const cluster = (connection: Connection) => { 25 | return { 26 | nodes: (opts?: NodesOptions): Promise[]> => { 27 | let builder = new NodesStatusGetter(connection).withOutput(opts?.output ? opts.output : 'minimal'); 28 | if (opts?.collection) { 29 | builder = builder.withClassName(opts.collection); 30 | } 31 | return builder.do().then((res) => res.nodes) as Promise[]>; 32 | }, 33 | }; 34 | }; 35 | 36 | export default cluster; 37 | 38 | export interface Cluster { 39 | /** 40 | * Get the status of all nodes in the cluster. 41 | * 42 | * @param {NodesOptions} [opts] The options for the request. 43 | * @returns {Promise[]>} The status of all nodes in the cluster. 44 | */ 45 | nodes: (opts?: NodesOptions) => Promise[]>; 46 | } 47 | -------------------------------------------------------------------------------- /src/collections/config/types/reranker.ts: -------------------------------------------------------------------------------- 1 | export type RerankerTransformersConfig = {}; 2 | 3 | export type RerankerCohereConfig = { 4 | model?: 'rerank-english-v2.0' | 'rerank-multilingual-v2.0' | string; 5 | }; 6 | 7 | export type RerankerVoyageAIConfig = { 8 | baseURL?: string; 9 | model?: 'rerank-lite-1' | string; 10 | }; 11 | 12 | export type RerankerJinaAIConfig = { 13 | model?: 14 | | 'jina-reranker-v2-base-multilingual' 15 | | 'jina-reranker-v1-base-en' 16 | | 'jina-reranker-v1-turbo-en' 17 | | 'jina-reranker-v1-tiny-en' 18 | | 'jina-colbert-v1-en' 19 | | string; 20 | }; 21 | 22 | export type RerankerNvidiaConfig = { 23 | baseURL?: string; 24 | model?: 'nvidia/rerank-qa-mistral-4b' | string; 25 | }; 26 | 27 | export type RerankerConfig = 28 | | RerankerCohereConfig 29 | | RerankerJinaAIConfig 30 | | RerankerNvidiaConfig 31 | | RerankerTransformersConfig 32 | | RerankerVoyageAIConfig 33 | | Record 34 | | undefined; 35 | 36 | export type Reranker = 37 | | 'reranker-cohere' 38 | | 'reranker-jinaai' 39 | | 'reranker-nvidia' 40 | | 'reranker-transformers' 41 | | 'reranker-voyageai' 42 | | 'none' 43 | | string; 44 | 45 | export type RerankerConfigType = R extends 'reranker-cohere' 46 | ? RerankerCohereConfig 47 | : R extends 'reranker-jinaai' 48 | ? RerankerJinaAIConfig 49 | : R extends 'reranker-nvidia' 50 | ? RerankerNvidiaConfig 51 | : R extends 'reranker-transformers' 52 | ? RerankerTransformersConfig 53 | : R extends 'reranker-voyageai' 54 | ? RerankerVoyageAIConfig 55 | : R extends 'none' 56 | ? undefined 57 | : Record | undefined; 58 | -------------------------------------------------------------------------------- /src/collections/config/types/vectorIndex.ts: -------------------------------------------------------------------------------- 1 | export type VectorIndexConfigHNSW = { 2 | cleanupIntervalSeconds: number; 3 | distance: VectorDistance; 4 | dynamicEfMin: number; 5 | dynamicEfMax: number; 6 | dynamicEfFactor: number; 7 | efConstruction: number; 8 | ef: number; 9 | filterStrategy: VectorIndexFilterStrategy; 10 | flatSearchCutoff: number; 11 | maxConnections: number; 12 | quantizer: PQConfig | BQConfig | SQConfig | undefined; 13 | skip: boolean; 14 | vectorCacheMaxObjects: number; 15 | type: 'hnsw'; 16 | }; 17 | 18 | export type VectorIndexConfigFlat = { 19 | distance: VectorDistance; 20 | vectorCacheMaxObjects: number; 21 | quantizer: BQConfig | undefined; 22 | type: 'flat'; 23 | }; 24 | 25 | export type VectorIndexConfigDynamic = { 26 | distance: VectorDistance; 27 | threshold: number; 28 | hnsw: VectorIndexConfigHNSW; 29 | flat: VectorIndexConfigFlat; 30 | type: 'dynamic'; 31 | }; 32 | 33 | export type VectorIndexConfigType = I extends 'hnsw' 34 | ? VectorIndexConfigHNSW 35 | : I extends 'flat' 36 | ? VectorIndexConfigFlat 37 | : I extends 'dynamic' 38 | ? VectorIndexConfigDynamic 39 | : I extends string 40 | ? Record 41 | : never; 42 | 43 | export type BQConfig = { 44 | cache: boolean; 45 | rescoreLimit: number; 46 | type: 'bq'; 47 | }; 48 | 49 | export type SQConfig = { 50 | rescoreLimit: number; 51 | trainingLimit: number; 52 | type: 'sq'; 53 | }; 54 | 55 | export type PQConfig = { 56 | bitCompression: boolean; 57 | centroids: number; 58 | encoder: PQEncoderConfig; 59 | segments: number; 60 | trainingLimit: number; 61 | type: 'pq'; 62 | }; 63 | 64 | export type PQEncoderConfig = { 65 | type: PQEncoderType; 66 | distribution: PQEncoderDistribution; 67 | }; 68 | 69 | export type VectorDistance = 'cosine' | 'dot' | 'l2-squared' | 'hamming'; 70 | 71 | export type PQEncoderType = 'kmeans' | 'tile'; 72 | export type PQEncoderDistribution = 'log-normal' | 'normal'; 73 | 74 | export type VectorIndexType = 'hnsw' | 'flat' | 'dynamic' | string; 75 | 76 | export type VectorIndexFilterStrategy = 'sweeping' | 'acorn'; 77 | 78 | export type VectorIndexConfig = VectorIndexConfigHNSW | VectorIndexConfigFlat | VectorIndexConfigDynamic; 79 | 80 | export type QuantizerConfig = PQConfig | BQConfig | SQConfig; 81 | -------------------------------------------------------------------------------- /src/collections/configure/parsing.ts: -------------------------------------------------------------------------------- 1 | import { 2 | BQConfigCreate, 3 | BQConfigUpdate, 4 | PQConfigCreate, 5 | PQConfigUpdate, 6 | SQConfigCreate, 7 | SQConfigUpdate, 8 | } from './types/index.js'; 9 | 10 | type QuantizerConfig = 11 | | PQConfigCreate 12 | | PQConfigUpdate 13 | | BQConfigCreate 14 | | BQConfigUpdate 15 | | SQConfigCreate 16 | | SQConfigUpdate; 17 | 18 | export class QuantizerGuards { 19 | static isPQCreate(config?: QuantizerConfig): config is PQConfigCreate { 20 | return (config as PQConfigCreate)?.type === 'pq'; 21 | } 22 | static isPQUpdate(config?: QuantizerConfig): config is PQConfigUpdate { 23 | return (config as PQConfigUpdate)?.type === 'pq'; 24 | } 25 | static isBQCreate(config?: QuantizerConfig): config is BQConfigCreate { 26 | return (config as BQConfigCreate)?.type === 'bq'; 27 | } 28 | static isBQUpdate(config?: QuantizerConfig): config is BQConfigUpdate { 29 | return (config as BQConfigUpdate)?.type === 'bq'; 30 | } 31 | static isSQCreate(config?: QuantizerConfig): config is SQConfigCreate { 32 | return (config as SQConfigCreate)?.type === 'sq'; 33 | } 34 | static isSQUpdate(config?: QuantizerConfig): config is SQConfigUpdate { 35 | return (config as SQConfigUpdate)?.type === 'sq'; 36 | } 37 | } 38 | 39 | export function parseWithDefault(value: D | undefined, defaultValue: D): D { 40 | return value !== undefined ? value : defaultValue; 41 | } 42 | -------------------------------------------------------------------------------- /src/collections/configure/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from './base.js'; 2 | export * from './generative.js'; 3 | export * from './vectorIndex.js'; 4 | export * from './vectorizer.js'; 5 | -------------------------------------------------------------------------------- /src/collections/filters/index.ts: -------------------------------------------------------------------------------- 1 | export { Filters } from './classes.js'; 2 | export type { 3 | Filter, 4 | FilterByCount, 5 | FilterById, 6 | FilterByProperty, 7 | FilterByTime, 8 | FilterValue, 9 | GeoRangeFilter, 10 | Operator, 11 | } from './types.js'; 12 | 13 | import { ExtractCrossReferenceType, NonRefKeys, RefKeys } from '../types/internal.js'; 14 | 15 | import { 16 | FilterCount, 17 | FilterCreationTime, 18 | FilterId, 19 | FilterProperty, 20 | FilterRef, 21 | FilterUpdateTime, 22 | } from './classes.js'; 23 | import { Filter } from './types.js'; 24 | 25 | const filter = (): Filter => { 26 | return { 27 | byProperty: & string>(name: K, length = false) => { 28 | return new FilterProperty(name, length); 29 | }, 30 | byRef: & string>(linkOn: K) => { 31 | return new FilterRef>({ type_: 'single', linkOn: linkOn }); 32 | }, 33 | byRefMultiTarget: & string>(linkOn: K, targetCollection: string) => { 34 | return new FilterRef>({ 35 | type_: 'multi', 36 | linkOn: linkOn, 37 | targetCollection: targetCollection, 38 | }); 39 | }, 40 | byRefCount: & string>(linkOn: K) => { 41 | return new FilterCount(linkOn); 42 | }, 43 | byId: () => { 44 | return new FilterId(); 45 | }, 46 | byCreationTime: () => { 47 | return new FilterCreationTime(); 48 | }, 49 | byUpdateTime: () => { 50 | return new FilterUpdateTime(); 51 | }, 52 | }; 53 | }; 54 | 55 | export default filter; 56 | -------------------------------------------------------------------------------- /src/collections/filters/utils.ts: -------------------------------------------------------------------------------- 1 | import { CountRef, FilterTargetInternal, MultiTargetRef, SingleTargetRef } from './types.js'; 2 | 3 | export class TargetGuards { 4 | public static isSingleTargetRef(target?: FilterTargetInternal): target is SingleTargetRef { 5 | if (!target) return false; 6 | return (target as SingleTargetRef).type_ === 'single'; 7 | } 8 | 9 | public static isMultiTargetRef(target?: FilterTargetInternal): target is MultiTargetRef { 10 | if (!target) return false; 11 | return (target as MultiTargetRef).type_ === 'multi'; 12 | } 13 | 14 | public static isCountRef(target?: FilterTargetInternal): target is CountRef { 15 | if (!target) return false; 16 | return (target as CountRef).type_ === 'count'; 17 | } 18 | 19 | public static isProperty(target?: FilterTargetInternal): target is string { 20 | if (!target) return false; 21 | return typeof target === 'string'; 22 | } 23 | 24 | public static isTargetRef(target?: FilterTargetInternal): target is SingleTargetRef | MultiTargetRef { 25 | if (!target) return false; 26 | return TargetGuards.isSingleTargetRef(target) || TargetGuards.isMultiTargetRef(target); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/collections/iterator/index.ts: -------------------------------------------------------------------------------- 1 | import { WeaviateDeserializationError } from '../../errors.js'; 2 | import { WeaviateObject } from '../types/index.js'; 3 | 4 | const ITERATOR_CACHE_SIZE = 100; 5 | 6 | export class Iterator { 7 | private cache: WeaviateObject[] = []; 8 | private last: string | undefined = undefined; 9 | constructor(private query: (limit: number, after?: string) => Promise[]>) { 10 | this.query = query; 11 | } 12 | 13 | [Symbol.asyncIterator]() { 14 | return { 15 | next: async (): Promise>> => { 16 | const objects = await this.query(ITERATOR_CACHE_SIZE, this.last); 17 | this.cache = objects; 18 | if (this.cache.length == 0) { 19 | return { 20 | done: true, 21 | value: undefined, 22 | }; 23 | } 24 | const obj = this.cache.shift(); 25 | if (obj === undefined) { 26 | throw new WeaviateDeserializationError('Object iterator returned an object that is undefined'); 27 | } 28 | this.last = obj?.uuid; 29 | if (this.last === undefined) { 30 | throw new WeaviateDeserializationError('Object iterator returned an object without a UUID'); 31 | } 32 | return { 33 | done: false, 34 | value: obj, 35 | }; 36 | }, 37 | }; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/collections/query/utils.ts: -------------------------------------------------------------------------------- 1 | import { MultiTargetVectorJoin } from '../index.js'; 2 | import { Bm25OperatorOptions, Bm25OperatorOr, NearVectorInputType, TargetVectorInputType } from './types.js'; 3 | 4 | export class NearVectorInputGuards { 5 | public static is1DArray(input: NearVectorInputType): input is number[] { 6 | return Array.isArray(input) && input.length > 0 && !Array.isArray(input[0]); 7 | } 8 | 9 | public static isObject(input: NearVectorInputType): input is Record { 10 | return !Array.isArray(input); 11 | } 12 | } 13 | 14 | export class ArrayInputGuards { 15 | public static is1DArray(input: U | T): input is T { 16 | return Array.isArray(input) && input.length > 0 && !Array.isArray(input[0]); 17 | } 18 | public static is2DArray(input: U | T): input is T { 19 | return Array.isArray(input) && input.length > 0 && Array.isArray(input[0]); 20 | } 21 | } 22 | 23 | export class TargetVectorInputGuards { 24 | public static isSingle(input: TargetVectorInputType): input is string { 25 | return typeof input === 'string'; 26 | } 27 | 28 | public static isMulti(input: TargetVectorInputType): input is string[] { 29 | return Array.isArray(input); 30 | } 31 | 32 | public static isMultiJoin(input: TargetVectorInputType): input is MultiTargetVectorJoin { 33 | const i = input as MultiTargetVectorJoin; 34 | return i.combination !== undefined && i.targetVectors !== undefined; 35 | } 36 | } 37 | 38 | export class Bm25Operator { 39 | static and(): Bm25OperatorOptions { 40 | return { operator: 'And' }; 41 | } 42 | 43 | static or(opts: Omit): Bm25OperatorOptions { 44 | return { ...opts, operator: 'Or' }; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/collections/references/classes.ts: -------------------------------------------------------------------------------- 1 | import { Properties, ReferenceInput, ReferenceToMultiTarget, WeaviateObject } from '../types/index.js'; 2 | import { Beacon } from './types.js'; 3 | import { uuidToBeacon } from './utils.js'; 4 | 5 | export class ReferenceManager { 6 | public objects: WeaviateObject[]; 7 | public targetCollection: string; 8 | public uuids?: string[]; 9 | 10 | constructor(targetCollection: string, objects?: WeaviateObject[], uuids?: string[]) { 11 | this.objects = objects ?? []; 12 | this.targetCollection = targetCollection; 13 | this.uuids = uuids; 14 | } 15 | 16 | public toBeaconObjs(): Beacon[] { 17 | return this.uuids ? this.uuids.map((uuid) => uuidToBeacon(uuid, this.targetCollection)) : []; 18 | } 19 | 20 | public toBeaconStrings(): string[] { 21 | return this.uuids ? this.uuids.map((uuid) => uuidToBeacon(uuid, this.targetCollection).beacon) : []; 22 | } 23 | 24 | public isMultiTarget(): boolean { 25 | return this.targetCollection !== ''; 26 | } 27 | } 28 | 29 | /** 30 | * A factory class to create references from objects to other objects. 31 | */ 32 | export class Reference { 33 | /** 34 | * Create a single-target reference with given UUID(s). 35 | * 36 | * @param {string | string[]} uuids The UUID(s) of the target object(s). 37 | * @returns {ReferenceManager} The reference manager object. 38 | */ 39 | public static to( 40 | uuids: string | string[] 41 | ): ReferenceManager { 42 | return new ReferenceManager('', undefined, Array.isArray(uuids) ? uuids : [uuids]); 43 | } 44 | /** 45 | * Create a multi-target reference with given UUID(s) pointing to a specific target collection. 46 | * 47 | * @param {string | string[]} uuids The UUID(s) of the target object(s). 48 | * @param {string} targetCollection The target collection name. 49 | * @returns {ReferenceManager} The reference manager object. 50 | */ 51 | public static toMultiTarget( 52 | uuids: string | string[], 53 | targetCollection: string 54 | ): ReferenceManager { 55 | return new ReferenceManager( 56 | targetCollection, 57 | undefined, 58 | Array.isArray(uuids) ? uuids : [uuids] 59 | ); 60 | } 61 | } 62 | 63 | export class ReferenceGuards { 64 | public static isReferenceManager(arg: ReferenceInput): arg is ReferenceManager { 65 | return arg instanceof ReferenceManager; 66 | } 67 | 68 | public static isUuid(arg: ReferenceInput): arg is string { 69 | return typeof arg === 'string'; 70 | } 71 | 72 | public static isUuids(arg: ReferenceInput): arg is string[] { 73 | return Array.isArray(arg); 74 | } 75 | 76 | public static isMultiTarget(arg: ReferenceInput): arg is ReferenceToMultiTarget { 77 | return (arg as ReferenceToMultiTarget).targetCollection !== undefined; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/collections/references/index.ts: -------------------------------------------------------------------------------- 1 | export { Reference, ReferenceManager } from './classes.js'; 2 | export type { Beacon, CrossReference, CrossReferenceDefault, CrossReferences, UnionOf } from './types.js'; 3 | -------------------------------------------------------------------------------- /src/collections/references/types.ts: -------------------------------------------------------------------------------- 1 | import { Properties, WeaviateNonGenericObject } from '../types/index.js'; 2 | import { ReferenceManager } from './classes.js'; 3 | 4 | export type CrossReference = ReferenceManager; 5 | 6 | export type CrossReferenceDefault = { 7 | objects: WeaviateNonGenericObject[]; 8 | }; 9 | 10 | export type CrossReferences = ReferenceManager>; 11 | 12 | export type UnionOf = T extends (infer U)[] ? U : never; 13 | 14 | export type Beacon = { 15 | beacon: string; 16 | }; 17 | -------------------------------------------------------------------------------- /src/collections/references/utils.ts: -------------------------------------------------------------------------------- 1 | import { ReferenceInput } from '../types/index.js'; 2 | import { ReferenceGuards, ReferenceManager } from './classes.js'; 3 | import { Beacon } from './types.js'; 4 | 5 | export function uuidToBeacon(uuid: string, targetCollection?: string): Beacon { 6 | return { 7 | beacon: `weaviate://localhost/${targetCollection ? `${targetCollection}/` : ''}${uuid}`, 8 | }; 9 | } 10 | 11 | export const referenceFromObjects = ( 12 | objects: any[], 13 | targetCollection: string, 14 | uuids: string[] 15 | ): ReferenceManager => { 16 | return new ReferenceManager(targetCollection, objects, uuids); 17 | }; 18 | 19 | export const referenceToBeacons = (ref: ReferenceInput): Beacon[] => { 20 | if (ReferenceGuards.isReferenceManager(ref)) { 21 | return ref.toBeaconObjs(); 22 | } else if (ReferenceGuards.isUuid(ref)) { 23 | return [uuidToBeacon(ref)]; 24 | } else if (ReferenceGuards.isUuids(ref)) { 25 | return ref.map((uuid) => uuidToBeacon(uuid)); 26 | } else if (ReferenceGuards.isMultiTarget(ref)) { 27 | return typeof ref.uuids === 'string' 28 | ? [uuidToBeacon(ref.uuids, ref.targetCollection)] 29 | : ref.uuids.map((uuid) => uuidToBeacon(uuid, ref.targetCollection)); 30 | } 31 | return []; 32 | }; 33 | -------------------------------------------------------------------------------- /src/collections/sort/classes.ts: -------------------------------------------------------------------------------- 1 | import { SortBy } from '../types/index.js'; 2 | import { NonRefKeys } from '../types/internal.js'; 3 | 4 | export class Sorting { 5 | public sorts: SortBy[]; 6 | 7 | constructor() { 8 | this.sorts = []; 9 | } 10 | 11 | /** Sort by the objects' property. */ 12 | public byProperty>(property: K, ascending = true) { 13 | this.sorts.push({ property, ascending }); 14 | return this; 15 | } 16 | 17 | /** Sort by the objects' ID. */ 18 | public byId(ascending = true) { 19 | this.sorts.push({ property: '_id', ascending }); 20 | return this; 21 | } 22 | 23 | /** Sort by the objects' creation time. */ 24 | public byCreationTime(ascending = true) { 25 | this.sorts.push({ property: '_creationTimeUnix', ascending }); 26 | return this; 27 | } 28 | 29 | /** Sort by the objects' last update time. */ 30 | public byUpdateTime(ascending = true) { 31 | this.sorts.push({ property: '_lastUpdateTimeUnix', ascending }); 32 | return this; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/collections/sort/index.ts: -------------------------------------------------------------------------------- 1 | export type { Sort } from './types.js'; 2 | 3 | import { NonRefKeys } from '../types/internal.js'; 4 | import { Sorting } from './classes.js'; 5 | import { Sort } from './types.js'; 6 | 7 | const sort = (): Sort => { 8 | return { 9 | byProperty>(property: K, ascending = true) { 10 | return new Sorting().byProperty(property, ascending); 11 | }, 12 | byId(ascending = true) { 13 | return new Sorting().byId(ascending); 14 | }, 15 | byCreationTime(ascending = true) { 16 | return new Sorting().byCreationTime(ascending); 17 | }, 18 | byUpdateTime(ascending = true) { 19 | return new Sorting().byUpdateTime(ascending); 20 | }, 21 | }; 22 | }; 23 | 24 | export default sort; 25 | 26 | export { Sorting }; 27 | -------------------------------------------------------------------------------- /src/collections/sort/types.ts: -------------------------------------------------------------------------------- 1 | import { NonRefKeys } from '../types/internal.js'; 2 | import { Sorting } from './classes.js'; 3 | 4 | /** 5 | * Define how the query's sort operation should be performed using the available methods. 6 | */ 7 | export interface Sort { 8 | /** Sort by an object property. */ 9 | byProperty>(property: K, ascending?: boolean): Sorting; 10 | /** Sort by the objects' ID. */ 11 | byId(ascending?: boolean): Sorting; 12 | /** Sort by the objects' creation time. */ 13 | byCreationTime(ascending?: boolean): Sorting; 14 | /** Sort by the objects' last update time. */ 15 | byUpdateTime(ascending?: boolean): Sorting; 16 | } 17 | -------------------------------------------------------------------------------- /src/collections/tenants/types.ts: -------------------------------------------------------------------------------- 1 | /** The base type for a tenant. Only the name is required. */ 2 | export type TenantBase = { 3 | /** The name of the tenant. */ 4 | name: string; 5 | }; 6 | 7 | /** The expected type when creating a tenant. */ 8 | export type TenantCreate = TenantBase & { 9 | /** The activity status of the tenant. Defaults to 'ACTIVE' if not provided. */ 10 | activityStatus?: 'ACTIVE' | 'INACTIVE'; 11 | }; 12 | 13 | /** The expected type when updating a tenant. */ 14 | export type TenantUpdate = TenantBase & { 15 | /** The activity status of the tenant. Must be set to one of the options. */ 16 | activityStatus: 'ACTIVE' | 'INACTIVE' | 'OFFLOADED'; 17 | }; 18 | 19 | /** The expected type when getting tenants. */ 20 | export type TenantsGetOptions = { 21 | tenants?: string; 22 | }; 23 | 24 | /** 25 | * The expected type returned by all tenant methods. 26 | */ 27 | export type Tenant = TenantBase & { 28 | /** There are two statuses that are immutable: `OFFLOADED` and `ONLOADING, which are set by the server: 29 | * - `ONLOADING`, which means the tenant is transitioning from the `OFFLOADED` status to `ACTIVE/INACTIVE`. 30 | * - `OFFLOADING`, which means the tenant is transitioning from `ACTIVE/INACTIVE` to the `OFFLOADED` status. 31 | * The other three statuses are mutable within the `.create` and `.update`, methods: 32 | * - `ACTIVE`, which means loaded fully into memory and ready for use. 33 | * - `INACTIVE`, which means not loaded into memory with files stored on disk. 34 | * - `OFFLOADED`, which means not loaded into memory with files stored on the cloud. 35 | */ 36 | activityStatus: 'ACTIVE' | 'INACTIVE' | 'OFFLOADED' | 'OFFLOADING' | 'ONLOADING'; 37 | }; 38 | 39 | /** This is the type of the Tenant as defined in Weaviate's OpenAPI schema. It is included here for Backwards Compatibility. */ 40 | export type TenantBC = TenantBase & { 41 | activityStatus?: 'HOT' | 'COLD' | 'FROZEN'; 42 | }; 43 | -------------------------------------------------------------------------------- /src/collections/types/batch.ts: -------------------------------------------------------------------------------- 1 | import { BatchReference } from '../../openapi/types.js'; 2 | import { BatchObject as BatchObjectGRPC } from '../../proto/v1/batch.js'; 3 | import { NonReferenceInputs, ReferenceInputs, Vectors } from '../index.js'; 4 | 5 | export type BatchObjectsReturn = { 6 | allResponses: (string | ErrorObject)[]; 7 | elapsedSeconds: number; 8 | errors: Record>; 9 | hasErrors: boolean; 10 | uuids: Record; 11 | }; 12 | 13 | export type ErrorObject = { 14 | code?: number; 15 | message: string; 16 | object: BatchObject; 17 | originalUuid?: string; 18 | }; 19 | 20 | export type BatchObject = { 21 | collection: string; 22 | properties?: NonReferenceInputs; 23 | references?: ReferenceInputs; 24 | id?: string; 25 | vectors?: number[] | Vectors; 26 | tenant?: string; 27 | }; 28 | 29 | export type BatchObjects = { 30 | batch: BatchObject[]; 31 | mapped: BatchObjectGRPC[]; 32 | }; 33 | 34 | export type ErrorReference = { 35 | message: string; 36 | reference: BatchReference; 37 | }; 38 | 39 | export type BatchReferencesReturn = { 40 | elapsedSeconds: number; 41 | errors: Record; 42 | hasErrors: boolean; 43 | }; 44 | -------------------------------------------------------------------------------- /src/collections/types/data.ts: -------------------------------------------------------------------------------- 1 | import { NonReferenceInputs, ReferenceInputs } from './internal.js'; 2 | import { Vectors } from './query.js'; 3 | 4 | export type DataObject = { 5 | id?: string; 6 | properties?: NonReferenceInputs; 7 | references?: ReferenceInputs; 8 | vectors?: number[] | Vectors; 9 | }; 10 | 11 | export type DeleteManyObject = { 12 | id: string; 13 | successful: boolean; 14 | error?: string; 15 | }; 16 | 17 | export type DeleteManyReturn = { 18 | failed: number; 19 | matches: number; 20 | objects: V extends true ? DeleteManyObject[] : undefined; 21 | successful: number; 22 | }; 23 | 24 | export type ReferenceToMultiTarget = { 25 | targetCollection: string; 26 | uuids: string | string[]; 27 | }; 28 | -------------------------------------------------------------------------------- /src/collections/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from '../config/types/index.js'; 2 | export * from '../configure/types/index.js'; 3 | export type { CollectionConfigCreate } from '../index.js'; 4 | export * from './batch.js'; 5 | export * from './data.js'; 6 | export * from './generate.js'; 7 | export type { 8 | IsEmptyType, 9 | IsNestedField, 10 | IsPrimitiveField, 11 | IsWeaviateField, 12 | NestedKeys, 13 | NonRefKeys, 14 | NonReferenceInputs, 15 | PrimitiveKeys, 16 | QueryNested, 17 | QueryProperty, 18 | QueryReference, 19 | RefKeys, 20 | ReferenceInput, 21 | ReferenceInputs, 22 | } from './internal.js'; 23 | export * from './query.js'; 24 | 25 | import { 26 | GeoCoordinate as GeoCoordinateGRPC, 27 | PhoneNumber as PhoneNumberGRPC, 28 | } from '../../proto/v1/properties.js'; 29 | 30 | import { CrossReference } from '../references/index.js'; 31 | 32 | // The order of type resolution is important here since object can be inferred as all other types 33 | // hence it should be the last type in the union 34 | export type DataType = T extends infer U | undefined 35 | ? U extends string 36 | ? 'text' | 'uuid' | 'blob' 37 | : U extends number 38 | ? 'number' | 'int' 39 | : U extends boolean 40 | ? 'boolean' 41 | : U extends Date 42 | ? 'date' 43 | : U extends string[] 44 | ? 'text[]' | 'uuid[]' 45 | : U extends number[] 46 | ? 'number[]' | 'int[]' 47 | : U extends boolean[] 48 | ? 'boolean[]' 49 | : U extends Date[] 50 | ? 'date[]' 51 | : U extends GeoCoordinate 52 | ? 'geoCoordinates' 53 | : U extends PhoneNumber 54 | ? 'phoneNumber' 55 | : U extends object[] 56 | ? 'object[]' 57 | : U extends object 58 | ? 'object' 59 | : never 60 | : never; 61 | 62 | export type GeoCoordinate = Required; 63 | 64 | export type PhoneNumber = Required; 65 | 66 | export type PrimitiveField = 67 | | string 68 | | string[] 69 | | boolean 70 | | boolean[] 71 | | number 72 | | number[] 73 | | Date 74 | | Date[] 75 | | Blob 76 | | GeoCoordinate 77 | | PhoneNumber 78 | | PhoneNumberInput 79 | | null; 80 | 81 | export type NestedField = NestedProperties | NestedProperties[]; 82 | 83 | export type WeaviateField = PrimitiveField | NestedField; 84 | 85 | export type Property = WeaviateField | CrossReference | undefined; 86 | 87 | export interface Properties { 88 | [k: string]: Property; 89 | } 90 | 91 | export interface NestedProperties { 92 | [k: string]: WeaviateField; 93 | } 94 | 95 | export type PhoneNumberInput = { 96 | number: string; 97 | defaultCountry?: string; 98 | }; 99 | -------------------------------------------------------------------------------- /src/collections/vectors/multiTargetVector.ts: -------------------------------------------------------------------------------- 1 | /** The allowed combination methods for multi-target vector joins */ 2 | export type MultiTargetVectorJoinCombination = 3 | | 'sum' 4 | | 'average' 5 | | 'minimum' 6 | | 'relative-score' 7 | | 'manual-weights'; 8 | 9 | /** Weights for each target vector in a multi-target vector join */ 10 | export type MultiTargetVectorWeights = Record; 11 | 12 | /** A multi-target vector join used when specifying a vector-based query */ 13 | export type MultiTargetVectorJoin = { 14 | /** The combination method to use for the target vectors */ 15 | combination: MultiTargetVectorJoinCombination; 16 | /** The target vectors to combine */ 17 | targetVectors: string[]; 18 | /** The weights to use for each target vector */ 19 | weights?: MultiTargetVectorWeights; 20 | }; 21 | 22 | export default () => { 23 | return { 24 | sum: (targetVectors: string[]): MultiTargetVectorJoin => { 25 | return { combination: 'sum' as MultiTargetVectorJoinCombination, targetVectors }; 26 | }, 27 | average: (targetVectors: string[]): MultiTargetVectorJoin => { 28 | return { combination: 'average' as MultiTargetVectorJoinCombination, targetVectors }; 29 | }, 30 | minimum: (targetVectors: string[]): MultiTargetVectorJoin => { 31 | return { combination: 'minimum' as MultiTargetVectorJoinCombination, targetVectors }; 32 | }, 33 | relativeScore: (weights: MultiTargetVectorWeights): MultiTargetVectorJoin => { 34 | return { 35 | combination: 'relative-score' as MultiTargetVectorJoinCombination, 36 | targetVectors: Object.keys(weights), 37 | weights, 38 | }; 39 | }, 40 | manualWeights: (weights: MultiTargetVectorWeights): MultiTargetVectorJoin => { 41 | return { 42 | combination: 'manual-weights' as MultiTargetVectorJoinCombination, 43 | targetVectors: Object.keys(weights), 44 | weights, 45 | }; 46 | }, 47 | }; 48 | }; 49 | 50 | export interface MultiTargetVector { 51 | /** Create a multi-target vector join that sums the vector scores over the target vectors */ 52 | sum: (targetVectors: string[]) => MultiTargetVectorJoin; 53 | /** Create a multi-target vector join that averages the vector scores over the target vectors */ 54 | average: (targetVectors: string[]) => MultiTargetVectorJoin; 55 | /** Create a multi-target vector join that takes the minimum vector score over the target vectors */ 56 | minimum: (targetVectors: string[]) => MultiTargetVectorJoin; 57 | /** Create a multi-target vector join that uses relative weights for each target vector */ 58 | relativeScore: (weights: MultiTargetVectorWeights) => MultiTargetVectorJoin; 59 | /** Create a multi-target vector join that uses manual weights for each target vector */ 60 | manualWeights: (weights: MultiTargetVectorWeights) => MultiTargetVectorJoin; 61 | } 62 | -------------------------------------------------------------------------------- /src/connection/gql.ts: -------------------------------------------------------------------------------- 1 | import { GraphQLClient as Client, Variables } from 'graphql-request'; 2 | import ConnectionREST, { InternalConnectionParams } from './http.js'; 3 | 4 | export default class ConnectionGQL extends ConnectionREST { 5 | private gql: GraphQLClient; 6 | 7 | constructor(params: InternalConnectionParams) { 8 | super(params); 9 | this.gql = gqlClient(params); 10 | } 11 | 12 | query = (query: any, variables?: V) => { 13 | if (this.authEnabled) { 14 | return this.login().then((token) => { 15 | const headers = { Authorization: `Bearer ${token}` }; 16 | return this.gql.query(query, variables, headers); 17 | }); 18 | } 19 | return this.gql.query(query, variables); 20 | }; 21 | 22 | close = () => this.http.close(); 23 | } 24 | 25 | export * from './auth.js'; 26 | 27 | export type TQuery = any; 28 | export interface GraphQLClient { 29 | query: ( 30 | query: TQuery, 31 | variables?: V, 32 | headers?: HeadersInit 33 | ) => Promise<{ data: T }>; 34 | } 35 | 36 | export const gqlClient = (config: InternalConnectionParams): GraphQLClient => { 37 | const version = '/v1/graphql'; 38 | const baseUri = `${config.host}${version}`; 39 | const defaultHeaders = config.headers; 40 | return { 41 | // for backward compatibility with replaced graphql-client lib, 42 | // results are wrapped into { data: data } 43 | query: (query: TQuery, variables?: V, headers?: HeadersInit) => { 44 | return new Client(baseUri, { 45 | headers: { 46 | ...defaultHeaders, 47 | ...headers, 48 | }, 49 | }) 50 | .request(query, variables, headers) 51 | .then((data) => ({ data })); 52 | }, 53 | }; 54 | }; 55 | -------------------------------------------------------------------------------- /src/connection/helpers.test.ts: -------------------------------------------------------------------------------- 1 | import weaviate from '../index.js'; 2 | 3 | const WCD_URL = 'https://piblpmmdsiknacjnm1ltla.c1.europe-west3.gcp.weaviate.cloud'; 4 | const WCD_KEY = 'cy4ua772mBlMdfw3YnclqAWzFhQt0RLIN0sl'; 5 | 6 | describe('Testing of the connection helper methods', () => { 7 | it('should connect to a WCS cluster', () => { 8 | return weaviate 9 | .connectToWeaviateCloud(WCD_URL, { 10 | authCredentials: new weaviate.ApiKey(WCD_KEY), 11 | }) 12 | .then((client) => client.getMeta()) 13 | .then((res: any) => { 14 | expect(res.version).toBeDefined(); 15 | }) 16 | .catch((e: any) => { 17 | throw new Error('it should not have errord: ' + e); 18 | }); 19 | }); 20 | 21 | it('should connect to a local cluster', () => { 22 | return weaviate 23 | .connectToLocal() 24 | .then((client) => client.getMeta()) 25 | .then((res: any) => { 26 | expect(res.version).toBeDefined(); 27 | }) 28 | .catch((e: any) => { 29 | throw new Error('it should not have errord: ' + e); 30 | }); 31 | }); 32 | }); 33 | -------------------------------------------------------------------------------- /src/connection/index.ts: -------------------------------------------------------------------------------- 1 | import ConnectionGQL from './gql.js'; 2 | import ConnectionGRPC from './grpc.js'; 3 | import ConnectionREST from './http.js'; 4 | 5 | export default ConnectionGQL; 6 | 7 | export type { 8 | ConnectToCustomOptions, 9 | ConnectToLocalOptions, 10 | ConnectToWCDOptions, 11 | ConnectToWCSOptions, 12 | ConnectToWeaviateCloudOptions, 13 | } from './helpers.js'; 14 | export type { InternalConnectionParams } from './http.js'; 15 | export { ConnectionGQL, ConnectionGRPC, ConnectionREST }; 16 | -------------------------------------------------------------------------------- /src/connection/integration.test.ts: -------------------------------------------------------------------------------- 1 | import { StartedWeaviateContainer, WeaviateContainer } from '@testcontainers/weaviate'; 2 | import weaviate from '..'; 3 | import { WeaviateStartUpError } from '../errors'; 4 | import { Meta } from '../openapi/types'; 5 | import { DbVersion } from '../utils/dbVersion'; 6 | 7 | describe('Integration testing of the ConnectionGRPC class', () => { 8 | let container: StartedWeaviateContainer; 9 | 10 | const getVersion = () => 11 | fetch(`http://${container.getHost()}:${container.getMappedPort(8080)}/v1/meta`) 12 | .then((res) => res.json() as Promise) 13 | .then((meta) => DbVersion.fromString(meta.version!)); 14 | 15 | beforeAll(async () => { 16 | container = await new WeaviateContainer(`semitechnologies/weaviate:${process.env.WEAVIATE_VERSION}`) 17 | .withExposedPorts(8080, 50051) 18 | .withEnvironment({ 19 | GRPC_MAX_MESSAGE_SIZE: '1', 20 | }) 21 | .start(); 22 | expect(container).toBeDefined(); 23 | }); 24 | afterAll(async () => { 25 | await container.stop(); 26 | }); 27 | it('should fail to startup due to message-size limit', async () => { 28 | const dbVersion = await getVersion(); 29 | try { 30 | await weaviate.connectToLocal({ 31 | host: container.getHost(), 32 | port: container.getMappedPort(8080), 33 | grpcPort: container.getMappedPort(50051), 34 | }); 35 | expect(dbVersion.isLowerThan(1, 27, 1)).toBe(true); 36 | } catch (err) { 37 | expect(err).toBeInstanceOf(WeaviateStartUpError); 38 | expect((err as WeaviateStartUpError).message).toContain( 39 | 'RESOURCE_EXHAUSTED: Attempted to send message with a size larger than 1' 40 | ); 41 | expect(dbVersion.isAtLeast(1, 27, 1)).toBe(true); 42 | } 43 | }); 44 | }); 45 | -------------------------------------------------------------------------------- /src/connection/proxy.test.ts: -------------------------------------------------------------------------------- 1 | import weaviate from '../index.js'; 2 | 3 | describe('Testing of the client connecting to a proxied Weaviate instance', () => { 4 | // Skip because Envoy Proxy in CI is too flaky with strange error: 5 | // ClientError: /grpc.health.v1.Health/Check INTERNAL: Received RST_STREAM with code 2 triggered by internal client error: Protocol error 6 | it.skip('should connect to a local instance using simultaneous http and grpc proxies', async () => { 7 | const client = await weaviate.connectToCustom({ 8 | httpHost: 'localhost', 9 | httpPath: '/http', 10 | httpPort: 10000, 11 | httpSecure: false, 12 | grpcHost: 'weaviate-proxy', 13 | grpcPort: 8021, 14 | proxies: { 15 | grpc: 'http://localhost:10001', 16 | }, 17 | }); 18 | expect(client).toBeDefined(); 19 | return client.collections 20 | .delete('Test') 21 | .then(() => 22 | client.collections.create({ 23 | name: 'Test', 24 | }) 25 | ) 26 | .then(async (collection) => { 27 | await collection.data.insert(); 28 | return collection; 29 | }) 30 | .then((collection) => collection.query.fetchObjects()) 31 | .then((res) => expect(res.objects).toHaveLength(1)); 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /src/data/checker.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import { CommandBase } from '../validation/commandBase.js'; 3 | import { ObjectsPath } from './path.js'; 4 | import { ConsistencyLevel } from './replication.js'; 5 | 6 | export default class Checker extends CommandBase { 7 | private className!: string; 8 | private consistencyLevel?: ConsistencyLevel; 9 | private id!: string; 10 | private tenant?: string; 11 | private objectsPath: ObjectsPath; 12 | 13 | constructor(client: Connection, objectsPath: ObjectsPath) { 14 | super(client); 15 | this.objectsPath = objectsPath; 16 | } 17 | 18 | withId = (id: string) => { 19 | this.id = id; 20 | return this; 21 | }; 22 | 23 | withClassName = (className: string) => { 24 | this.className = className; 25 | return this; 26 | }; 27 | 28 | withTenant = (tenant: string) => { 29 | this.tenant = tenant; 30 | return this; 31 | }; 32 | 33 | withConsistencyLevel = (consistencyLevel: ConsistencyLevel) => { 34 | this.consistencyLevel = consistencyLevel; 35 | return this; 36 | }; 37 | 38 | buildPath = () => { 39 | return this.objectsPath.buildCheck(this.id, this.className, this.consistencyLevel, this.tenant); 40 | }; 41 | 42 | validateIsSet = (prop: string | undefined | null, name: string, setter: string) => { 43 | if (prop == undefined || prop == null || prop.length == 0) { 44 | this.addError(`${name} must be set - set with ${setter}`); 45 | } 46 | }; 47 | 48 | validateId = () => { 49 | this.validateIsSet(this.id, 'id', '.withId(id)'); 50 | }; 51 | 52 | validate = () => { 53 | this.validateId(); 54 | }; 55 | 56 | do = (): Promise => { 57 | if (this.errors.length > 0) { 58 | return Promise.reject(new Error('invalid usage: ' + this.errors.join(', '))); 59 | } 60 | this.validate(); 61 | 62 | return this.buildPath().then((path: string) => this.client.head(path, undefined)); 63 | }; 64 | } 65 | -------------------------------------------------------------------------------- /src/data/creator.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import { Properties, WeaviateObject } from '../openapi/types.js'; 3 | import { CommandBase } from '../validation/commandBase.js'; 4 | import { isValidStringProperty } from '../validation/string.js'; 5 | import { ObjectsPath } from './path.js'; 6 | import { ConsistencyLevel } from './replication.js'; 7 | 8 | export default class Creator extends CommandBase { 9 | private className?: string; 10 | private consistencyLevel?: ConsistencyLevel; 11 | private id?: string; 12 | private objectsPath: ObjectsPath; 13 | private properties?: Properties; 14 | private vector?: number[]; 15 | private vectors?: Record; 16 | private tenant?: string; 17 | 18 | constructor(client: Connection, objectsPath: ObjectsPath) { 19 | super(client); 20 | this.objectsPath = objectsPath; 21 | } 22 | 23 | withVector = (vector: number[]) => { 24 | this.vector = vector; 25 | return this; 26 | }; 27 | 28 | withVectors = (vectors: Record) => { 29 | this.vectors = vectors; 30 | return this; 31 | }; 32 | 33 | withClassName = (className: string) => { 34 | this.className = className; 35 | return this; 36 | }; 37 | 38 | withProperties = (properties: Properties) => { 39 | this.properties = properties; 40 | return this; 41 | }; 42 | 43 | withId = (id: string) => { 44 | this.id = id; 45 | return this; 46 | }; 47 | 48 | withConsistencyLevel = (cl: ConsistencyLevel) => { 49 | this.consistencyLevel = cl; 50 | return this; 51 | }; 52 | 53 | withTenant = (tenant: string) => { 54 | this.tenant = tenant; 55 | return this; 56 | }; 57 | 58 | validateClassName = () => { 59 | if (!isValidStringProperty(this.className)) { 60 | this.addError('className must be set - set with .withClassName(className)'); 61 | } 62 | }; 63 | 64 | // as Record required below because server uses swagger object as interface{} in Go to perform type switching 65 | // actual types are []number and [][]number but unions don't work in go-swagger 66 | payload = (): WeaviateObject => ({ 67 | tenant: this.tenant, 68 | vector: this.vector, 69 | properties: this.properties, 70 | class: this.className, 71 | id: this.id, 72 | vectors: this.vectors as Record, 73 | }); 74 | 75 | validate = () => { 76 | this.validateClassName(); 77 | }; 78 | 79 | do = (): Promise => { 80 | this.validate(); 81 | if (this.errors.length > 0) { 82 | return Promise.reject(new Error('invalid usage: ' + this.errors.join(', '))); 83 | } 84 | 85 | return this.objectsPath 86 | .buildCreate(this.consistencyLevel) 87 | .then((path: string) => this.client.postReturn(path, this.payload())); 88 | }; 89 | } 90 | -------------------------------------------------------------------------------- /src/data/deleter.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import { CommandBase } from '../validation/commandBase.js'; 3 | import { ObjectsPath } from './path.js'; 4 | import { ConsistencyLevel } from './replication.js'; 5 | 6 | export default class Deleter extends CommandBase { 7 | private className!: string; 8 | private consistencyLevel?: ConsistencyLevel; 9 | private id!: string; 10 | private tenant?: string; 11 | private objectsPath: ObjectsPath; 12 | 13 | constructor(client: Connection, objectsPath: ObjectsPath) { 14 | super(client); 15 | this.objectsPath = objectsPath; 16 | } 17 | 18 | withId = (id: string) => { 19 | this.id = id; 20 | return this; 21 | }; 22 | 23 | withClassName = (className: string) => { 24 | this.className = className; 25 | return this; 26 | }; 27 | 28 | withConsistencyLevel = (cl: ConsistencyLevel) => { 29 | this.consistencyLevel = cl; 30 | return this; 31 | }; 32 | 33 | withTenant = (tenant: string) => { 34 | this.tenant = tenant; 35 | return this; 36 | }; 37 | 38 | validateIsSet = (prop: string | undefined | null, name: string, setter: string) => { 39 | if (prop == undefined || prop == null || prop.length == 0) { 40 | this.addError(`${name} must be set - set with ${setter}`); 41 | } 42 | }; 43 | 44 | validateId = () => { 45 | this.validateIsSet(this.id, 'id', '.withId(id)'); 46 | }; 47 | 48 | validate = () => { 49 | this.validateId(); 50 | }; 51 | 52 | do = () => { 53 | if (this.errors.length > 0) { 54 | return Promise.reject(new Error('invalid usage: ' + this.errors.join(', '))); 55 | } 56 | this.validate(); 57 | 58 | return this.objectsPath 59 | .buildDelete(this.id, this.className, this.consistencyLevel, this.tenant) 60 | .then((path: string) => { 61 | return this.client.delete(path, undefined, false); 62 | }); 63 | }; 64 | } 65 | -------------------------------------------------------------------------------- /src/data/getter.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import { WeaviateObjectsList } from '../openapi/types.js'; 3 | import { CommandBase } from '../validation/commandBase.js'; 4 | import { ObjectsPath } from './path.js'; 5 | 6 | export default class Getter extends CommandBase { 7 | private additional: string[]; 8 | private after!: string; 9 | private className?: string; 10 | private limit?: number; 11 | private tenant?: string; 12 | private objectsPath: ObjectsPath; 13 | 14 | constructor(client: Connection, objectsPath: ObjectsPath) { 15 | super(client); 16 | this.objectsPath = objectsPath; 17 | this.additional = []; 18 | } 19 | 20 | withClassName = (className: string) => { 21 | this.className = className; 22 | return this; 23 | }; 24 | 25 | withAfter = (id: string) => { 26 | this.after = id; 27 | return this; 28 | }; 29 | 30 | withLimit = (limit: number) => { 31 | this.limit = limit; 32 | return this; 33 | }; 34 | 35 | withTenant = (tenant: string) => { 36 | this.tenant = tenant; 37 | return this; 38 | }; 39 | 40 | extendAdditional = (prop: string) => { 41 | this.additional = [...this.additional, prop]; 42 | return this; 43 | }; 44 | 45 | withAdditional = (additionalFlag: any) => this.extendAdditional(additionalFlag); 46 | 47 | withVector = () => this.extendAdditional('vector'); 48 | 49 | validate() { 50 | // nothing to validate 51 | } 52 | 53 | do = (): Promise => { 54 | if (this.errors.length > 0) { 55 | return Promise.reject(new Error('invalid usage: ' + this.errors.join(', '))); 56 | } 57 | 58 | return this.objectsPath 59 | .buildGet(this.className, this.limit, this.additional, this.after, this.tenant) 60 | .then((path: string) => { 61 | return this.client.get(path); 62 | }); 63 | }; 64 | } 65 | -------------------------------------------------------------------------------- /src/data/getterById.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import { WeaviateObject } from '../openapi/types.js'; 3 | import { CommandBase } from '../validation/commandBase.js'; 4 | import { ObjectsPath } from './path.js'; 5 | import { ConsistencyLevel } from './replication.js'; 6 | 7 | export default class GetterById extends CommandBase { 8 | private additional: string[]; 9 | private className!: string; 10 | private id!: string; 11 | private consistencyLevel?: ConsistencyLevel; 12 | private nodeName?: string; 13 | private tenant?: string; 14 | private objectsPath: ObjectsPath; 15 | 16 | constructor(client: Connection, objectsPath: ObjectsPath) { 17 | super(client); 18 | this.objectsPath = objectsPath; 19 | this.additional = []; 20 | } 21 | 22 | withId = (id: string) => { 23 | this.id = id; 24 | return this; 25 | }; 26 | 27 | withClassName = (className: string) => { 28 | this.className = className; 29 | return this; 30 | }; 31 | 32 | withTenant = (tenant: string) => { 33 | this.tenant = tenant; 34 | return this; 35 | }; 36 | 37 | extendAdditional = (prop: string) => { 38 | this.additional = [...this.additional, prop]; 39 | return this; 40 | }; 41 | 42 | withAdditional = (additionalFlag: string) => this.extendAdditional(additionalFlag); 43 | 44 | withVector = () => this.extendAdditional('vector'); 45 | 46 | withConsistencyLevel = (cl: ConsistencyLevel) => { 47 | this.consistencyLevel = cl; 48 | return this; 49 | }; 50 | 51 | withNodeName = (nodeName: string) => { 52 | this.nodeName = nodeName; 53 | return this; 54 | }; 55 | 56 | validateId = () => { 57 | if (this.id == undefined || this.id == null || this.id.length == 0) { 58 | this.addError('id must be set - initialize with getterById(id)'); 59 | } 60 | }; 61 | 62 | validate = () => { 63 | this.validateId(); 64 | }; 65 | 66 | buildPath = (): Promise => { 67 | return this.objectsPath.buildGetOne( 68 | this.id, 69 | this.className, 70 | this.additional, 71 | this.consistencyLevel, 72 | this.nodeName, 73 | this.tenant 74 | ); 75 | }; 76 | 77 | do = (): Promise => { 78 | this.validate(); 79 | if (this.errors.length > 0) { 80 | return Promise.reject(new Error('invalid usage: ' + this.errors.join(', '))); 81 | } 82 | 83 | return this.buildPath().then((path) => { 84 | return this.client.get(path); 85 | }); 86 | }; 87 | } 88 | -------------------------------------------------------------------------------- /src/data/index.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import { BeaconPath } from '../utils/beaconPath.js'; 3 | import { DbVersionSupport } from '../utils/dbVersion.js'; 4 | import Checker from './checker.js'; 5 | import Creator from './creator.js'; 6 | import Deleter from './deleter.js'; 7 | import Getter from './getter.js'; 8 | import GetterById from './getterById.js'; 9 | import Merger from './merger.js'; 10 | import { ObjectsPath, ReferencesPath } from './path.js'; 11 | import ReferenceCreator from './referenceCreator.js'; 12 | import ReferenceDeleter from './referenceDeleter.js'; 13 | import ReferencePayloadBuilder from './referencePayloadBuilder.js'; 14 | import ReferenceReplacer from './referenceReplacer.js'; 15 | import Updater from './updater.js'; 16 | import Validator from './validator.js'; 17 | 18 | export interface Data { 19 | creator: () => Creator; 20 | validator: () => Validator; 21 | updater: () => Updater; 22 | merger: () => Merger; 23 | getter: () => Getter; 24 | getterById: () => GetterById; 25 | deleter: () => Deleter; 26 | checker: () => Checker; 27 | referenceCreator: () => ReferenceCreator; 28 | referenceReplacer: () => ReferenceReplacer; 29 | referenceDeleter: () => ReferenceDeleter; 30 | referencePayloadBuilder: () => ReferencePayloadBuilder; 31 | } 32 | 33 | const data = (client: Connection, dbVersionSupport: DbVersionSupport): Data => { 34 | const objectsPath = new ObjectsPath(dbVersionSupport); 35 | const referencesPath = new ReferencesPath(dbVersionSupport); 36 | const beaconPath = new BeaconPath(dbVersionSupport); 37 | 38 | return { 39 | creator: () => new Creator(client, objectsPath), 40 | validator: () => new Validator(client), 41 | updater: () => new Updater(client, objectsPath), 42 | merger: () => new Merger(client, objectsPath), 43 | getter: () => new Getter(client, objectsPath), 44 | getterById: () => new GetterById(client, objectsPath), 45 | deleter: () => new Deleter(client, objectsPath), 46 | checker: () => new Checker(client, objectsPath), 47 | referenceCreator: () => new ReferenceCreator(client, referencesPath, beaconPath), 48 | referenceReplacer: () => new ReferenceReplacer(client, referencesPath, beaconPath), 49 | referenceDeleter: () => new ReferenceDeleter(client, referencesPath, beaconPath), 50 | referencePayloadBuilder: () => new ReferencePayloadBuilder(client), 51 | }; 52 | }; 53 | 54 | export default data; 55 | export { default as Checker } from './checker.js'; 56 | export { default as Creator } from './creator.js'; 57 | export { default as Deleter } from './deleter.js'; 58 | export { default as Getter } from './getter.js'; 59 | export { default as GetterById } from './getterById.js'; 60 | export { default as Merger } from './merger.js'; 61 | export { default as ReferenceCreator } from './referenceCreator.js'; 62 | export { default as ReferenceDeleter } from './referenceDeleter.js'; 63 | export { default as ReferencePayloadBuilder } from './referencePayloadBuilder.js'; 64 | export { default as ReferenceReplacer } from './referenceReplacer.js'; 65 | export { default as Updater } from './updater.js'; 66 | export { default as Validator } from './validator.js'; 67 | 68 | export type { ConsistencyLevel } from './replication.js'; 69 | -------------------------------------------------------------------------------- /src/data/merger.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import { Properties, WeaviateObject } from '../openapi/types.js'; 3 | import { CommandBase } from '../validation/commandBase.js'; 4 | import { isValidStringProperty } from '../validation/string.js'; 5 | import { ObjectsPath } from './path.js'; 6 | import { ConsistencyLevel } from './replication.js'; 7 | 8 | export default class Merger extends CommandBase { 9 | private className!: string; 10 | private consistencyLevel?: ConsistencyLevel; 11 | private id!: string; 12 | private objectsPath: ObjectsPath; 13 | private properties?: Properties; 14 | private tenant?: string; 15 | 16 | constructor(client: Connection, objectsPath: ObjectsPath) { 17 | super(client); 18 | this.objectsPath = objectsPath; 19 | } 20 | 21 | withProperties = (properties: Properties) => { 22 | this.properties = properties; 23 | return this; 24 | }; 25 | 26 | withClassName = (className: string) => { 27 | this.className = className; 28 | return this; 29 | }; 30 | 31 | withId = (id: string) => { 32 | this.id = id; 33 | return this; 34 | }; 35 | 36 | withConsistencyLevel = (cl: ConsistencyLevel) => { 37 | this.consistencyLevel = cl; 38 | return this; 39 | }; 40 | 41 | withTenant = (tenant: string) => { 42 | this.tenant = tenant; 43 | return this; 44 | }; 45 | 46 | validateClassName = () => { 47 | if (!isValidStringProperty(this.className)) { 48 | this.addError('className must be set - set with withClassName(className)'); 49 | } 50 | }; 51 | 52 | validateId = () => { 53 | if (this.id == undefined || this.id == null || this.id.length == 0) { 54 | this.addError('id must be set - set with withId(id)'); 55 | } 56 | }; 57 | 58 | payload = (): WeaviateObject => ({ 59 | tenant: this.tenant, 60 | properties: this.properties, 61 | class: this.className, 62 | id: this.id, 63 | }); 64 | 65 | validate = () => { 66 | this.validateClassName(); 67 | this.validateId(); 68 | }; 69 | 70 | do = () => { 71 | this.validate(); 72 | 73 | if (this.errors.length > 0) { 74 | return Promise.reject(new Error('invalid usage: ' + this.errors.join(', '))); 75 | } 76 | 77 | return this.objectsPath 78 | .buildMerge(this.id, this.className, this.consistencyLevel) 79 | .then((path: string) => this.client.patch(path, this.payload())); 80 | }; 81 | } 82 | -------------------------------------------------------------------------------- /src/data/path.test.ts: -------------------------------------------------------------------------------- 1 | import { TestDbVersionProvider } from '../../test/dbVersionProvider.js'; 2 | import { DbVersionSupport } from '../utils/dbVersion.js'; 3 | import { ObjectsPath, ReferencesPath } from './path.js'; 4 | 5 | // This can be anything > 1.14.2, to support class-namespaced urls. 6 | // The actual value is not used for anything else 7 | const version = '1.18.0'; 8 | 9 | const objectsPathBuilder = new ObjectsPath(new DbVersionSupport(new TestDbVersionProvider(version))); 10 | 11 | const refsPathBuilder = new ReferencesPath(new DbVersionSupport(new TestDbVersionProvider(version))); 12 | 13 | describe('paths', () => { 14 | it('builds object create', () => { 15 | return objectsPathBuilder 16 | .buildCreate('ONE') 17 | .then((path) => expect(path).toEqual('/objects?consistency_level=ONE')) 18 | .catch((e) => fail(`unexpected error: ${e}`)); 19 | }); 20 | 21 | it('builds object delete', () => { 22 | return objectsPathBuilder 23 | .buildDelete('123456', 'SomeClass', 'ALL') 24 | .then((path) => expect(path).toEqual('/objects/SomeClass/123456?consistency_level=ALL')) 25 | .catch((e) => fail(`unexpected error: ${e}`)); 26 | }); 27 | 28 | it('builds object merge', () => { 29 | return objectsPathBuilder 30 | .buildMerge('123456', 'SomeClass', 'QUORUM') 31 | .then((path) => expect(path).toEqual('/objects/SomeClass/123456?consistency_level=QUORUM')) 32 | .catch((e) => fail(`unexpected error: ${e}`)); 33 | }); 34 | 35 | it('builds object update', () => { 36 | return objectsPathBuilder 37 | .buildUpdate('123456', 'SomeClass', 'ONE') 38 | .then((path) => expect(path).toEqual('/objects/SomeClass/123456?consistency_level=ONE')) 39 | .catch((e) => fail(`unexpected error: ${e}`)); 40 | }); 41 | 42 | it('builds references', () => { 43 | return refsPathBuilder 44 | .build('123456', 'SomeClass', 'SomeProp', 'ALL') 45 | .then((path) => 46 | expect(path).toEqual('/objects/SomeClass/123456/references/SomeProp?consistency_level=ALL') 47 | ) 48 | .catch((e) => fail(`unexpected error: ${e}`)); 49 | }); 50 | }); 51 | 52 | describe('paths with tenantKey', () => { 53 | it('builds object delete', () => { 54 | return objectsPathBuilder 55 | .buildDelete('123456', 'SomeClass', 'ALL', 'tenantA') 56 | .then((path) => expect(path).toEqual('/objects/SomeClass/123456?consistency_level=ALL&tenant=tenantA')) 57 | .catch((e) => fail(`unexpected error: ${e}`)); 58 | }); 59 | 60 | it('builds references', () => { 61 | return refsPathBuilder 62 | .build('123456', 'SomeClass', 'SomeProp', 'ALL', 'tenantA') 63 | .then((path) => 64 | expect(path).toEqual( 65 | '/objects/SomeClass/123456/references/SomeProp?consistency_level=ALL&tenant=tenantA' 66 | ) 67 | ) 68 | .catch((e) => fail(`unexpected error: ${e}`)); 69 | }); 70 | }); 71 | -------------------------------------------------------------------------------- /src/data/referenceCreator.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import { Reference } from '../openapi/types.js'; 3 | import { BeaconPath } from '../utils/beaconPath.js'; 4 | import { CommandBase } from '../validation/commandBase.js'; 5 | import { ReferencesPath } from './path.js'; 6 | import { ConsistencyLevel } from './replication.js'; 7 | 8 | export default class ReferenceCreator extends CommandBase { 9 | private beaconPath: BeaconPath; 10 | private className!: string; 11 | private consistencyLevel?: ConsistencyLevel; 12 | private id!: string; 13 | private reference!: Reference; 14 | private referencesPath: ReferencesPath; 15 | private refProp!: string; 16 | private tenant?: string; 17 | 18 | constructor(client: Connection, referencesPath: ReferencesPath, beaconPath: BeaconPath) { 19 | super(client); 20 | this.referencesPath = referencesPath; 21 | this.beaconPath = beaconPath; 22 | } 23 | 24 | withId = (id: string) => { 25 | this.id = id; 26 | return this; 27 | }; 28 | 29 | withClassName(className: string) { 30 | this.className = className; 31 | return this; 32 | } 33 | 34 | withReference = (ref: Reference) => { 35 | this.reference = ref; 36 | return this; 37 | }; 38 | 39 | withReferenceProperty = (refProp: string) => { 40 | this.refProp = refProp; 41 | return this; 42 | }; 43 | 44 | withConsistencyLevel = (cl: ConsistencyLevel) => { 45 | this.consistencyLevel = cl; 46 | return this; 47 | }; 48 | 49 | withTenant = (tenant: string) => { 50 | this.tenant = tenant; 51 | return this; 52 | }; 53 | 54 | validateIsSet = (prop: string | undefined | null, name: string, setter: string) => { 55 | if (prop == undefined || prop == null || prop.length == 0) { 56 | this.addError(`${name} must be set - set with ${setter}`); 57 | } 58 | }; 59 | 60 | validate = () => { 61 | this.validateIsSet(this.id, 'id', '.withId(id)'); 62 | this.validateIsSet(this.refProp, 'referenceProperty', '.withReferenceProperty(refProp)'); 63 | }; 64 | 65 | payload = () => this.reference; 66 | 67 | do = () => { 68 | this.validate(); 69 | if (this.errors.length > 0) { 70 | return Promise.reject(new Error('invalid usage: ' + this.errors.join(', '))); 71 | } 72 | 73 | if (!this.reference.beacon) { 74 | throw new Error('reference beacon must be set'); 75 | } 76 | 77 | return Promise.all([ 78 | this.referencesPath.build(this.id, this.className, this.refProp, this.consistencyLevel, this.tenant), 79 | this.beaconPath.rebuild(this.reference.beacon), 80 | ]).then((results) => { 81 | const path = results[0]; 82 | const beacon = results[1]; 83 | return this.client.postEmpty(path, { beacon }); 84 | }); 85 | }; 86 | } 87 | -------------------------------------------------------------------------------- /src/data/referenceDeleter.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import { Reference } from '../openapi/types.js'; 3 | import { BeaconPath } from '../utils/beaconPath.js'; 4 | import { CommandBase } from '../validation/commandBase.js'; 5 | import { ReferencesPath } from './path.js'; 6 | import { ConsistencyLevel } from './replication.js'; 7 | 8 | export default class ReferenceDeleter extends CommandBase { 9 | private beaconPath: BeaconPath; 10 | private className!: string; 11 | private consistencyLevel?: ConsistencyLevel; 12 | private id!: string; 13 | private reference!: Reference; 14 | private referencesPath: ReferencesPath; 15 | private refProp!: string; 16 | private tenant?: string; 17 | 18 | constructor(client: Connection, referencesPath: ReferencesPath, beaconPath: BeaconPath) { 19 | super(client); 20 | this.referencesPath = referencesPath; 21 | this.beaconPath = beaconPath; 22 | } 23 | 24 | withId = (id: string) => { 25 | this.id = id; 26 | return this; 27 | }; 28 | 29 | withClassName(className: string) { 30 | this.className = className; 31 | return this; 32 | } 33 | 34 | withReference = (ref: Reference) => { 35 | this.reference = ref; 36 | return this; 37 | }; 38 | 39 | withReferenceProperty = (refProp: string) => { 40 | this.refProp = refProp; 41 | return this; 42 | }; 43 | 44 | withConsistencyLevel = (cl: ConsistencyLevel) => { 45 | this.consistencyLevel = cl; 46 | return this; 47 | }; 48 | 49 | withTenant = (tenant: string) => { 50 | this.tenant = tenant; 51 | return this; 52 | }; 53 | 54 | validateIsSet = (prop: string | undefined | null, name: string, setter: string) => { 55 | if (prop == undefined || prop == null || prop.length == 0) { 56 | this.addError(`${name} must be set - set with ${setter}`); 57 | } 58 | }; 59 | 60 | validate = () => { 61 | this.validateIsSet(this.id, 'id', '.withId(id)'); 62 | this.validateIsSet(this.refProp, 'referenceProperty', '.withReferenceProperty(refProp)'); 63 | }; 64 | 65 | payload = () => this.reference; 66 | 67 | do = () => { 68 | this.validate(); 69 | if (this.errors.length > 0) { 70 | return Promise.reject(new Error('invalid usage: ' + this.errors.join(', '))); 71 | } 72 | 73 | if (!this.reference.beacon) { 74 | throw new Error('reference beacon must be set'); 75 | } 76 | 77 | return Promise.all([ 78 | this.referencesPath.build(this.id, this.className, this.refProp, this.consistencyLevel, this.tenant), 79 | this.beaconPath.rebuild(this.reference.beacon), 80 | ]).then((results) => { 81 | const path = results[0]; 82 | const beacon = results[1]; 83 | return this.client.delete(path, { beacon }, false); 84 | }); 85 | }; 86 | } 87 | -------------------------------------------------------------------------------- /src/data/referencePayloadBuilder.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import { Reference } from '../openapi/types.js'; 3 | import { CommandBase } from '../validation/commandBase.js'; 4 | import { isValidStringProperty } from '../validation/string.js'; 5 | 6 | export default class ReferencePayloadBuilder extends CommandBase { 7 | private className?: string; 8 | private id?: string; 9 | 10 | constructor(client: Connection) { 11 | super(client); 12 | } 13 | 14 | withId = (id: string) => { 15 | this.id = id; 16 | return this; 17 | }; 18 | 19 | withClassName(className: string) { 20 | this.className = className; 21 | return this; 22 | } 23 | 24 | validateIsSet = (prop: string | undefined | null, name: string, setter: string) => { 25 | if (prop == undefined || prop == null || prop.length == 0) { 26 | this.addError(`${name} must be set - set with ${setter}`); 27 | } 28 | }; 29 | 30 | validate = () => { 31 | this.validateIsSet(this.id, 'id', '.withId(id)'); 32 | }; 33 | 34 | payload = (): Reference => { 35 | this.validate(); 36 | if (this.errors.length > 0) { 37 | throw new Error(this.errors.join(', ')); 38 | } 39 | 40 | let beacon = `weaviate://localhost`; 41 | if (isValidStringProperty(this.className)) { 42 | beacon = `${beacon}/${this.className}`; 43 | } 44 | return { 45 | beacon: `${beacon}/${this.id}`, 46 | }; 47 | }; 48 | 49 | do(): Promise { 50 | return Promise.reject(new Error('Should never be called')); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/data/referenceReplacer.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import { Reference } from '../openapi/types.js'; 3 | import { BeaconPath } from '../utils/beaconPath.js'; 4 | import { CommandBase } from '../validation/commandBase.js'; 5 | import { ReferencesPath } from './path.js'; 6 | import { ConsistencyLevel } from './replication.js'; 7 | 8 | export default class ReferenceReplacer extends CommandBase { 9 | private beaconPath: BeaconPath; 10 | private className!: string; 11 | private consistencyLevel?: ConsistencyLevel; 12 | private id!: string; 13 | private references!: Reference[]; 14 | private referencesPath: ReferencesPath; 15 | private refProp!: string; 16 | private tenant?: string; 17 | 18 | constructor(client: Connection, referencesPath: ReferencesPath, beaconPath: BeaconPath) { 19 | super(client); 20 | this.beaconPath = beaconPath; 21 | this.referencesPath = referencesPath; 22 | } 23 | 24 | withId = (id: string) => { 25 | this.id = id; 26 | return this; 27 | }; 28 | 29 | withClassName(className: string) { 30 | this.className = className; 31 | return this; 32 | } 33 | 34 | withReferences = (refs: any) => { 35 | this.references = refs; 36 | return this; 37 | }; 38 | 39 | withReferenceProperty = (refProp: string) => { 40 | this.refProp = refProp; 41 | return this; 42 | }; 43 | 44 | withConsistencyLevel = (cl: ConsistencyLevel) => { 45 | this.consistencyLevel = cl; 46 | return this; 47 | }; 48 | 49 | withTenant = (tenant: string) => { 50 | this.tenant = tenant; 51 | return this; 52 | }; 53 | 54 | validateIsSet = (prop: string | undefined | null, name: string, setter: string) => { 55 | if (prop == undefined || prop == null || prop.length == 0) { 56 | this.addError(`${name} must be set - set with ${setter}`); 57 | } 58 | }; 59 | 60 | validate = () => { 61 | this.validateIsSet(this.id, 'id', '.withId(id)'); 62 | this.validateIsSet(this.refProp, 'referenceProperty', '.withReferenceProperty(refProp)'); 63 | }; 64 | 65 | payload = () => this.references; 66 | 67 | do = () => { 68 | this.validate(); 69 | if (this.errors.length > 0) { 70 | return Promise.reject(new Error('invalid usage: ' + this.errors.join(', '))); 71 | } 72 | 73 | const payloadPromise = Array.isArray(this.references) 74 | ? Promise.all(this.references.map((ref) => this.rebuildReferencePromise(ref))) 75 | : Promise.resolve([]); 76 | 77 | return Promise.all([ 78 | this.referencesPath.build(this.id, this.className, this.refProp, this.consistencyLevel, this.tenant), 79 | payloadPromise, 80 | ]).then((results) => { 81 | const path = results[0]; 82 | const payload = results[1]; 83 | return this.client.put(path, payload, false); 84 | }); 85 | }; 86 | 87 | rebuildReferencePromise(reference: any) { 88 | return this.beaconPath.rebuild(reference.beacon).then((beacon: any) => ({ beacon })); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/data/replication.ts: -------------------------------------------------------------------------------- 1 | export type ConsistencyLevel = 'ALL' | 'ONE' | 'QUORUM'; 2 | -------------------------------------------------------------------------------- /src/data/updater.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import { Properties, WeaviateObject } from '../openapi/types.js'; 3 | import { CommandBase } from '../validation/commandBase.js'; 4 | import { isValidStringProperty } from '../validation/string.js'; 5 | import { ObjectsPath } from './path.js'; 6 | import { ConsistencyLevel } from './replication.js'; 7 | 8 | export default class Updater extends CommandBase { 9 | private className!: string; 10 | private consistencyLevel?: ConsistencyLevel; 11 | private id!: string; 12 | private objectsPath: ObjectsPath; 13 | private properties?: Properties; 14 | private tenant?: string; 15 | private vector?: number[]; 16 | private vectors?: Record; 17 | 18 | constructor(client: Connection, objectsPath: ObjectsPath) { 19 | super(client); 20 | this.objectsPath = objectsPath; 21 | } 22 | 23 | withVector = (vector: number[]) => { 24 | this.vector = vector; 25 | return this; 26 | }; 27 | 28 | withVectors = (vectors: Record) => { 29 | this.vectors = vectors; 30 | return this; 31 | }; 32 | 33 | withProperties = (properties: Properties) => { 34 | this.properties = properties; 35 | return this; 36 | }; 37 | 38 | withId = (id: string) => { 39 | this.id = id; 40 | return this; 41 | }; 42 | 43 | withClassName = (className: string) => { 44 | this.className = className; 45 | return this; 46 | }; 47 | 48 | withTenant = (tenant: string) => { 49 | this.tenant = tenant; 50 | return this; 51 | }; 52 | 53 | validateClassName = () => { 54 | if (!isValidStringProperty(this.className)) { 55 | this.addError('className must be set - use withClassName(className)'); 56 | } 57 | }; 58 | 59 | validateId = () => { 60 | if (this.id == undefined || this.id == null || this.id.length == 0) { 61 | this.addError('id must be set - initialize with updater(id)'); 62 | } 63 | }; 64 | 65 | withConsistencyLevel = (cl: ConsistencyLevel) => { 66 | this.consistencyLevel = cl; 67 | return this; 68 | }; 69 | 70 | // as Record required below because server uses swagger object as interface{} in Go to perform type switching 71 | // actual types are []number and [][]number but unions don't work in go-swagger 72 | payload = (): WeaviateObject => ({ 73 | tenant: this.tenant, 74 | properties: this.properties, 75 | class: this.className, 76 | id: this.id, 77 | vector: this.vector, 78 | vectors: this.vectors as Record, 79 | }); 80 | 81 | validate = () => { 82 | this.validateClassName(); 83 | this.validateId(); 84 | }; 85 | 86 | do = () => { 87 | this.validate(); 88 | 89 | if (this.errors.length > 0) { 90 | return Promise.reject(new Error('invalid usage: ' + this.errors.join(', '))); 91 | } 92 | 93 | return this.objectsPath 94 | .buildUpdate(this.id, this.className, this.consistencyLevel) 95 | .then((path: string) => this.client.put(path, this.payload())); 96 | }; 97 | } 98 | -------------------------------------------------------------------------------- /src/data/validator.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import { Properties } from '../openapi/types.js'; 3 | import { CommandBase } from '../validation/commandBase.js'; 4 | import { isValidStringProperty } from '../validation/string.js'; 5 | 6 | export default class Validator extends CommandBase { 7 | private className?: string; 8 | private id?: string; 9 | private properties?: Properties; 10 | 11 | constructor(client: Connection) { 12 | super(client); 13 | } 14 | 15 | withClassName = (className: string) => { 16 | this.className = className; 17 | return this; 18 | }; 19 | 20 | withProperties = (properties: Properties) => { 21 | this.properties = properties; 22 | return this; 23 | }; 24 | 25 | withId = (id: string) => { 26 | this.id = id; 27 | return this; 28 | }; 29 | 30 | validateClassName = () => { 31 | if (!isValidStringProperty(this.className)) { 32 | this.addError('className must be set - set with .withClassName(className)'); 33 | } 34 | }; 35 | 36 | payload = () => ({ 37 | properties: this.properties, 38 | class: this.className, 39 | id: this.id, 40 | }); 41 | 42 | validate = () => { 43 | this.validateClassName(); 44 | }; 45 | 46 | do = () => { 47 | this.validate(); 48 | if (this.errors.length > 0) { 49 | return Promise.reject(new Error('invalid usage: ' + this.errors.join(', '))); 50 | } 51 | const path = `/objects/validate`; 52 | return this.client.postEmpty(path, this.payload()).then(() => true); 53 | }; 54 | } 55 | -------------------------------------------------------------------------------- /src/graphql/ask.ts: -------------------------------------------------------------------------------- 1 | export interface AskArgs { 2 | autocorrect?: boolean; 3 | certainty?: number; 4 | distance?: number; 5 | properties?: string[]; 6 | question?: string; 7 | rerank?: boolean; 8 | } 9 | 10 | export default class GraphQLAsk { 11 | private autocorrect?: boolean; 12 | private certainty?: number; 13 | private distance?: number; 14 | private properties?: string[]; 15 | private question?: string; 16 | private rerank?: boolean; 17 | 18 | constructor(args: AskArgs) { 19 | this.autocorrect = args.autocorrect; 20 | this.certainty = args.certainty; 21 | this.distance = args.distance; 22 | this.properties = args.properties; 23 | this.question = args.question; 24 | this.rerank = args.rerank; 25 | } 26 | 27 | toString(wrap = true) { 28 | this.validate(); 29 | 30 | let args: any[] = []; 31 | 32 | if (this.question) { 33 | args = [...args, `question:${JSON.stringify(this.question)}`]; 34 | } 35 | 36 | if (this.properties) { 37 | args = [...args, `properties:${JSON.stringify(this.properties)}`]; 38 | } 39 | 40 | if (this.certainty) { 41 | args = [...args, `certainty:${this.certainty}`]; 42 | } 43 | 44 | if (this.distance) { 45 | args = [...args, `distance:${this.distance}`]; 46 | } 47 | 48 | if (this.autocorrect !== undefined) { 49 | args = [...args, `autocorrect:${this.autocorrect}`]; 50 | } 51 | 52 | if (this.rerank !== undefined) { 53 | args = [...args, `rerank:${this.rerank}`]; 54 | } 55 | 56 | if (!wrap) { 57 | return `${args.join(',')}`; 58 | } 59 | return `{${args.join(',')}}`; 60 | } 61 | 62 | validate() { 63 | if (!this.question) { 64 | throw new Error('ask filter: question needs to be set'); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/graphql/bm25.ts: -------------------------------------------------------------------------------- 1 | export interface Bm25Args { 2 | properties?: string[]; 3 | query: string; 4 | } 5 | 6 | export default class GraphQLBm25 { 7 | private properties?: string[]; 8 | private query: string; 9 | 10 | constructor(args: Bm25Args) { 11 | this.properties = args.properties; 12 | this.query = args.query; 13 | } 14 | 15 | toString() { 16 | let args = [`query:${JSON.stringify(this.query)}`]; // query must always be set 17 | 18 | if (this.properties !== undefined) { 19 | args = [...args, `properties:${JSON.stringify(this.properties)}`]; 20 | } 21 | 22 | return `{${args.join(',')}}`; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/graphql/generate.ts: -------------------------------------------------------------------------------- 1 | export interface GenerateArgs { 2 | groupedTask?: string; 3 | groupedProperties?: string[]; 4 | singlePrompt?: string; 5 | } 6 | 7 | export interface GenerateParts { 8 | singleResult?: string; 9 | groupedResult?: string; 10 | results: string[]; 11 | } 12 | 13 | export class GraphQLGenerate { 14 | private groupedTask?: string; 15 | private groupedProperties?: string[]; 16 | private singlePrompt?: string; 17 | 18 | constructor(args: GenerateArgs) { 19 | this.groupedTask = args.groupedTask; 20 | this.groupedProperties = args.groupedProperties; 21 | this.singlePrompt = args.singlePrompt; 22 | } 23 | 24 | toString(): string { 25 | this.validate(); 26 | 27 | let str = 'generate('; 28 | const results = ['error']; 29 | if (this.singlePrompt) { 30 | str += `singleResult:{prompt:"${this.singlePrompt.replace(/[\n\r]+/g, '')}"}`; 31 | results.push('singleResult'); 32 | } 33 | if (this.groupedTask || (this.groupedProperties !== undefined && this.groupedProperties.length > 0)) { 34 | const args: string[] = []; 35 | if (this.groupedTask) { 36 | args.push(`task:"${this.groupedTask.replace(/[\n\r]+/g, '')}"`); 37 | } 38 | if (this.groupedProperties !== undefined && this.groupedProperties.length > 0) { 39 | args.push(`properties:${JSON.stringify(this.groupedProperties)}`); 40 | } 41 | str += `groupedResult:{${args.join(',')}}`; 42 | results.push('groupedResult'); 43 | } 44 | str += `){${results.join(' ')}}`; 45 | return str; 46 | } 47 | 48 | private validate() { 49 | if (!this.groupedTask && !this.singlePrompt) { 50 | throw new Error('must provide at least one of `singlePrompt` or `groupTask`'); 51 | } 52 | if (this.groupedTask !== undefined && this.groupedTask == '') { 53 | throw new Error('groupedTask must not be empty'); 54 | } 55 | if (this.singlePrompt !== undefined && this.singlePrompt == '') { 56 | throw new Error('singlePrompt must not be empty'); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/graphql/group.ts: -------------------------------------------------------------------------------- 1 | export interface GroupArgs { 2 | type: string; 3 | force: number; 4 | } 5 | 6 | export default class GraphQLGroup { 7 | private args: GroupArgs; 8 | 9 | constructor(args: GroupArgs) { 10 | this.args = args; 11 | } 12 | 13 | toString() { 14 | let parts: any[] = []; 15 | 16 | if (this.args.type) { 17 | // value is a graphQL enum, so doesn't need to be quoted 18 | parts = [...parts, `type:${this.args.type}`]; 19 | } 20 | 21 | if (this.args.force) { 22 | parts = [...parts, `force:${this.args.force}`]; 23 | } 24 | 25 | return `{${parts.join(',')}}`; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/graphql/groupBy.ts: -------------------------------------------------------------------------------- 1 | export interface GroupByArgs { 2 | path: string[]; 3 | groups: number; 4 | objectsPerGroup: number; 5 | } 6 | 7 | export default class GraphQLGroupBy { 8 | private args: GroupByArgs; 9 | 10 | constructor(args: GroupByArgs) { 11 | this.args = args; 12 | } 13 | 14 | toString() { 15 | let parts: string[] = []; 16 | 17 | if (this.args.path) { 18 | parts = [...parts, `path:${JSON.stringify(this.args.path)}`]; 19 | } 20 | 21 | if (this.args.groups) { 22 | parts = [...parts, `groups:${this.args.groups}`]; 23 | } 24 | 25 | if (this.args.objectsPerGroup) { 26 | parts = [...parts, `objectsPerGroup:${this.args.objectsPerGroup}`]; 27 | } 28 | 29 | return `{${parts.join(',')}}`; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/graphql/index.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import Aggregator from './aggregator.js'; 3 | import Explorer from './explorer.js'; 4 | import GraphQLGetter from './getter.js'; 5 | import Raw from './raw.js'; 6 | 7 | export interface GraphQL { 8 | get: () => GraphQLGetter; 9 | aggregate: () => Aggregator; 10 | explore: () => Explorer; 11 | raw: () => Raw; 12 | } 13 | 14 | const graphql = (client: Connection): GraphQL => { 15 | return { 16 | get: () => new GraphQLGetter(client), 17 | aggregate: () => new Aggregator(client), 18 | explore: () => new Explorer(client), 19 | raw: () => new Raw(client), 20 | }; 21 | }; 22 | 23 | export default graphql; 24 | export { default as Aggregator } from './aggregator.js'; 25 | export { default as Explorer } from './explorer.js'; 26 | export { FusionType, default as GraphQLGetter } from './getter.js'; 27 | export { default as Raw } from './raw.js'; 28 | -------------------------------------------------------------------------------- /src/graphql/nearImage.ts: -------------------------------------------------------------------------------- 1 | import { NearMediaBase } from './nearMedia.js'; 2 | 3 | export interface NearImageArgs extends NearMediaBase { 4 | image?: string; 5 | targetVectors?: string[]; 6 | } 7 | 8 | export default class GraphQLNearImage { 9 | private certainty?: number; 10 | private distance?: number; 11 | private image?: string; 12 | private targetVectors?: string[]; 13 | 14 | constructor(args: NearImageArgs) { 15 | this.certainty = args.certainty; 16 | this.distance = args.distance; 17 | this.image = args.image; 18 | this.targetVectors = args.targetVectors; 19 | } 20 | 21 | toString(wrap = true) { 22 | this.validate(); 23 | 24 | let args: string[] = []; 25 | 26 | if (this.image) { 27 | let img = this.image; 28 | if (img.startsWith('data:')) { 29 | const base64part = ';base64,'; 30 | img = img.substring(img.indexOf(base64part) + base64part.length); 31 | } 32 | args = [...args, `image:${JSON.stringify(img)}`]; 33 | } 34 | 35 | if (this.certainty) { 36 | args = [...args, `certainty:${this.certainty}`]; 37 | } 38 | 39 | if (this.distance) { 40 | args = [...args, `distance:${this.distance}`]; 41 | } 42 | 43 | if (this.targetVectors && this.targetVectors.length > 0) { 44 | args = [...args, `targetVectors:${JSON.stringify(this.targetVectors)}`]; 45 | } 46 | 47 | if (!wrap) { 48 | return `${args.join(',')}`; 49 | } 50 | return `{${args.join(',')}}`; 51 | } 52 | 53 | validate() { 54 | if (!this.image) { 55 | throw new Error('nearImage filter: image field must be present'); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/graphql/nearMedia.ts: -------------------------------------------------------------------------------- 1 | export interface NearMediaBase { 2 | certainty?: number; 3 | distance?: number; 4 | targetVectors?: string[]; 5 | } 6 | export interface NearMediaArgs extends NearMediaBase { 7 | media: string; 8 | type: NearMediaType; 9 | } 10 | export interface NearImageArgs extends NearMediaBase { 11 | image: string; 12 | } 13 | export interface NearAudioArgs extends NearMediaBase { 14 | audio: string; 15 | } 16 | export interface NearVideoArgs extends NearMediaBase { 17 | video: string; 18 | } 19 | export interface NearThermalArgs extends NearMediaBase { 20 | thermal: string; 21 | } 22 | export interface NearDepthArgs extends NearMediaBase { 23 | depth: string; 24 | } 25 | export interface NearIMUArgs extends NearMediaBase { 26 | imu: string; 27 | } 28 | 29 | export enum NearMediaType { 30 | Image = 'Image', 31 | Audio = 'Audio', 32 | Video = 'Video', 33 | Thermal = 'Thermal', 34 | Depth = 'Depth', 35 | IMU = 'IMU', 36 | } 37 | 38 | export default class GraphQLNearMedia { 39 | private certainty?: number; 40 | private distance?: number; 41 | private media: string; 42 | private type: NearMediaType; 43 | private targetVectors?: string[]; 44 | 45 | constructor(args: NearMediaArgs) { 46 | this.certainty = args.certainty; 47 | this.distance = args.distance; 48 | this.media = args.media; 49 | this.type = args.type; 50 | this.targetVectors = args.targetVectors; 51 | } 52 | 53 | toString(wrap = true) { 54 | let args: string[] = []; 55 | 56 | if (this.media.startsWith('data:')) { 57 | const base64part = ';base64,'; 58 | this.media = this.media.substring(this.media.indexOf(base64part) + base64part.length); 59 | } 60 | args = [...args, `${this.type.toLowerCase()}:${JSON.stringify(this.media)}`]; 61 | 62 | if (this.certainty) { 63 | args = [...args, `certainty:${this.certainty}`]; 64 | } 65 | 66 | if (this.distance) { 67 | args = [...args, `distance:${this.distance}`]; 68 | } 69 | 70 | if (this.targetVectors && this.targetVectors.length > 0) { 71 | args = [...args, `targetVectors:${JSON.stringify(this.targetVectors)}`]; 72 | } 73 | 74 | if (!wrap) { 75 | return `${args.join(',')}`; 76 | } 77 | return `{${args.join(',')}}`; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/graphql/nearObject.ts: -------------------------------------------------------------------------------- 1 | export interface NearObjectArgs { 2 | beacon?: string; 3 | certainty?: number; 4 | distance?: number; 5 | id?: string; 6 | targetVectors?: string[]; 7 | } 8 | 9 | export default class GraphQLNearObject { 10 | private beacon?: string; 11 | private certainty?: number; 12 | private distance?: number; 13 | private id?: string; 14 | private targetVectors?: string[]; 15 | 16 | constructor(args: NearObjectArgs) { 17 | this.beacon = args.beacon; 18 | this.certainty = args.certainty; 19 | this.distance = args.distance; 20 | this.id = args.id; 21 | this.targetVectors = args.targetVectors; 22 | } 23 | 24 | toString(wrap = true) { 25 | this.validate(); 26 | 27 | let args: any[] = []; 28 | 29 | if (this.id) { 30 | args = [...args, `id:${JSON.stringify(this.id)}`]; 31 | } 32 | 33 | if (this.beacon) { 34 | args = [...args, `beacon:${JSON.stringify(this.beacon)}`]; 35 | } 36 | 37 | if (this.certainty) { 38 | args = [...args, `certainty:${this.certainty}`]; 39 | } 40 | 41 | if (this.distance) { 42 | args = [...args, `distance:${this.distance}`]; 43 | } 44 | 45 | if (this.targetVectors && this.targetVectors.length > 0) { 46 | args = [...args, `targetVectors:${JSON.stringify(this.targetVectors)}`]; 47 | } 48 | 49 | if (!wrap) { 50 | return `${args.join(',')}`; 51 | } 52 | return `{${args.join(',')}}`; 53 | } 54 | 55 | validate() { 56 | if (!this.id && !this.beacon) { 57 | throw new Error('nearObject filter: id or beacon needs to be set'); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/graphql/nearVector.ts: -------------------------------------------------------------------------------- 1 | export interface NearVectorArgs { 2 | certainty?: number; 3 | distance?: number; 4 | vector: number[]; 5 | targetVectors?: string[]; 6 | } 7 | 8 | export default class GraphQLNearVector { 9 | private certainty?: number; 10 | private distance?: number; 11 | private vector: number[]; 12 | private targetVectors?: string[]; 13 | 14 | constructor(args: NearVectorArgs) { 15 | this.certainty = args.certainty; 16 | this.distance = args.distance; 17 | this.vector = args.vector; 18 | this.targetVectors = args.targetVectors; 19 | } 20 | 21 | toString(wrap = true) { 22 | let args = [`vector:${JSON.stringify(this.vector)}`]; // vector must always be set 23 | 24 | if (this.certainty) { 25 | args = [...args, `certainty:${this.certainty}`]; 26 | } 27 | 28 | if (this.distance) { 29 | args = [...args, `distance:${this.distance}`]; 30 | } 31 | 32 | if (this.targetVectors && this.targetVectors.length > 0) { 33 | args = [...args, `targetVectors:${JSON.stringify(this.targetVectors)}`]; 34 | } 35 | 36 | if (!wrap) { 37 | return `${args.join(',')}`; 38 | } 39 | return `{${args.join(',')}}`; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/graphql/raw.test.ts: -------------------------------------------------------------------------------- 1 | import Raw from './raw.js'; 2 | 3 | test('a simple raw query', () => { 4 | const mockClient: any = { 5 | query: jest.fn(), 6 | }; 7 | 8 | const expectedQuery = `{Get{Person{name}}}`; 9 | 10 | new Raw(mockClient).withQuery(expectedQuery).do(); 11 | 12 | expect(mockClient.query).toHaveBeenCalledWith(expectedQuery); 13 | }); 14 | 15 | test('reject empty raw query', () => { 16 | const mockClient: any = { 17 | query: jest.fn(), 18 | }; 19 | 20 | new Raw(mockClient).do().catch((err: Error) => { 21 | expect(err.message).toEqual('invalid usage: query must be set - set with .raw().withQuery(query)'); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /src/graphql/raw.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import { CommandBase } from '../validation/commandBase.js'; 3 | 4 | export default class RawGraphQL extends CommandBase { 5 | private query?: string; 6 | 7 | constructor(client: Connection) { 8 | super(client); 9 | } 10 | 11 | withQuery = (query: string) => { 12 | this.query = query; 13 | return this; 14 | }; 15 | 16 | validateIsSet = (prop: string | undefined | null, name: string, setter: string) => { 17 | if (prop == undefined || prop == null || prop.length == 0) { 18 | this.addError(`${name} must be set - set with ${setter}`); 19 | } 20 | }; 21 | 22 | validate = () => { 23 | this.validateIsSet(this.query, 'query', '.raw().withQuery(query)'); 24 | }; 25 | 26 | do = (): Promise => { 27 | const params = ''; 28 | 29 | this.validate(); 30 | if (this.errors.length > 0) { 31 | return Promise.reject(new Error('invalid usage: ' + this.errors.join(', '))); 32 | } 33 | 34 | if (this.query) { 35 | return this.client.query(this.query); 36 | } 37 | 38 | return Promise.resolve(undefined); 39 | }; 40 | } 41 | -------------------------------------------------------------------------------- /src/graphql/sort.ts: -------------------------------------------------------------------------------- 1 | export interface SortArgs { 2 | path: string[]; 3 | order?: string; 4 | } 5 | 6 | export type SortOrder = 'asc' | 'desc'; 7 | 8 | export default class GraphQLSort { 9 | private args: SortArgs[]; 10 | 11 | constructor(args: SortArgs[]) { 12 | this.args = args; 13 | } 14 | 15 | toString(): string { 16 | const parts: string[] = []; 17 | 18 | for (const arg of this.args) { 19 | let part = `{path:${JSON.stringify(arg.path)}`; 20 | if (arg.order) { 21 | part = part.concat(`,order:${arg.order}}`); 22 | } else { 23 | part = part.concat('}'); 24 | } 25 | parts.push(part); 26 | } 27 | 28 | return parts.join(','); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/grpc/base.ts: -------------------------------------------------------------------------------- 1 | import { ConsistencyLevel } from '../data/index.js'; 2 | 3 | import { Metadata } from 'nice-grpc'; 4 | import { RetryOptions } from 'nice-grpc-client-middleware-retry'; 5 | import { ConsistencyLevel as ConsistencyLevelGRPC } from '../proto/v1/base.js'; 6 | import { WeaviateClient } from '../proto/v1/weaviate.js'; 7 | 8 | export default class Base { 9 | protected connection: WeaviateClient; 10 | protected collection: string; 11 | protected timeout: number; 12 | protected consistencyLevel?: ConsistencyLevelGRPC; 13 | protected tenant?: string; 14 | protected metadata?: Metadata; 15 | 16 | protected constructor( 17 | connection: WeaviateClient, 18 | collection: string, 19 | metadata: Metadata, 20 | timeout: number, 21 | consistencyLevel?: ConsistencyLevel, 22 | tenant?: string 23 | ) { 24 | this.connection = connection; 25 | this.collection = collection; 26 | this.metadata = metadata; 27 | this.timeout = timeout; 28 | this.consistencyLevel = this.mapConsistencyLevel(consistencyLevel); 29 | this.tenant = tenant; 30 | } 31 | 32 | private mapConsistencyLevel(consistencyLevel?: ConsistencyLevel): ConsistencyLevelGRPC { 33 | switch (consistencyLevel) { 34 | case 'ALL': 35 | return ConsistencyLevelGRPC.CONSISTENCY_LEVEL_ALL; 36 | case 'QUORUM': 37 | return ConsistencyLevelGRPC.CONSISTENCY_LEVEL_QUORUM; 38 | case 'ONE': 39 | return ConsistencyLevelGRPC.CONSISTENCY_LEVEL_ONE; 40 | default: 41 | return ConsistencyLevelGRPC.CONSISTENCY_LEVEL_UNSPECIFIED; 42 | } 43 | } 44 | 45 | protected sendWithTimeout = (send: (signal: AbortSignal) => Promise): Promise => { 46 | const controller = new AbortController(); 47 | const timeoutId = setTimeout(() => controller.abort(), this.timeout * 1000); 48 | return send(controller.signal).finally(() => clearTimeout(timeoutId)); 49 | }; 50 | } 51 | -------------------------------------------------------------------------------- /src/grpc/retry.ts: -------------------------------------------------------------------------------- 1 | import { ClientError, Status } from 'nice-grpc'; 2 | import { RetryOptions } from 'nice-grpc-client-middleware-retry'; 3 | 4 | export const retryOptions: RetryOptions = { 5 | retry: true, 6 | retryMaxAttempts: 5, 7 | retryableStatuses: [Status.UNAVAILABLE], 8 | onRetryableError(error: ClientError, attempt: number, delayMs: number) { 9 | console.warn(error, `Attempt ${attempt} failed. Retrying in ${delayMs}ms.`); 10 | }, 11 | }; 12 | -------------------------------------------------------------------------------- /src/grpc/tenantsManager.ts: -------------------------------------------------------------------------------- 1 | import { isAbortError } from 'abort-controller-x'; 2 | import { Metadata, ServerError, Status } from 'nice-grpc'; 3 | import { RetryOptions } from 'nice-grpc-client-middleware-retry'; 4 | import { 5 | WeaviateInsufficientPermissionsError, 6 | WeaviateRequestTimeoutError, 7 | WeaviateTenantsGetError, 8 | } from '../errors.js'; 9 | import { TenantsGetReply, TenantsGetRequest } from '../proto/v1/tenants.js'; 10 | import { WeaviateClient } from '../proto/v1/weaviate.js'; 11 | import Base from './base.js'; 12 | import { retryOptions } from './retry.js'; 13 | 14 | export type TenantsGetArgs = { 15 | names?: string[]; 16 | }; 17 | 18 | export interface Tenants { 19 | withGet: (args: TenantsGetArgs) => Promise; 20 | } 21 | 22 | export default class TenantsManager extends Base implements Tenants { 23 | public static use( 24 | connection: WeaviateClient, 25 | collection: string, 26 | metadata: Metadata, 27 | timeout: number 28 | ): Tenants { 29 | return new TenantsManager(connection, collection, metadata, timeout); 30 | } 31 | 32 | public withGet = (args: TenantsGetArgs) => 33 | this.call(TenantsGetRequest.fromPartial({ names: args.names ? { values: args.names } : undefined })); 34 | 35 | private call(message: TenantsGetRequest) { 36 | return this.sendWithTimeout((signal: AbortSignal) => 37 | this.connection 38 | .tenantsGet( 39 | { 40 | ...message, 41 | collection: this.collection, 42 | }, 43 | { 44 | metadata: this.metadata, 45 | signal, 46 | ...retryOptions, 47 | } 48 | ) 49 | .catch((err) => { 50 | if (err instanceof ServerError && err.code === Status.PERMISSION_DENIED) { 51 | throw new WeaviateInsufficientPermissionsError(7, err.message); 52 | } 53 | if (isAbortError(err)) { 54 | throw new WeaviateRequestTimeoutError(`timed out after ${this.timeout}ms`); 55 | } 56 | throw new WeaviateTenantsGetError(err.message); 57 | }) 58 | ); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/integration.test.ts: -------------------------------------------------------------------------------- 1 | import weaviate from './index.js'; 2 | 3 | describe('Integration testing of the client methods', () => { 4 | it('should connect using connectToLocal defaults', () => { 5 | return weaviate.connectToLocal(); 6 | }); 7 | 8 | it('should connect using connectToLocal with schema-ed host', () => { 9 | const logSpy = jest.spyOn(console, 'warn'); 10 | return weaviate 11 | .connectToLocal({ 12 | host: 'http://localhost', 13 | }) 14 | .then(() => expect(logSpy).toHaveBeenCalledTimes(2)); 15 | }); 16 | 17 | it('should connect using connectToLocal with non-schema-ed host', () => { 18 | return weaviate.connectToLocal({ 19 | host: 'localhost', 20 | }); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /src/misc/index.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import { DbVersionProvider } from '../utils/dbVersion.js'; 3 | import LiveChecker from './liveChecker.js'; 4 | import MetaGetter from './metaGetter.js'; 5 | import OpenidConfigurationGetter from './openidConfigurationGetter.js'; 6 | import ReadyChecker from './readyChecker.js'; 7 | 8 | export interface Misc { 9 | liveChecker: () => LiveChecker; 10 | readyChecker: () => ReadyChecker; 11 | metaGetter: () => MetaGetter; 12 | openidConfigurationGetter: () => OpenidConfigurationGetter; 13 | } 14 | 15 | const misc = (client: Connection, dbVersionProvider: DbVersionProvider): Misc => { 16 | return { 17 | liveChecker: () => new LiveChecker(client, dbVersionProvider), 18 | readyChecker: () => new ReadyChecker(client, dbVersionProvider), 19 | metaGetter: () => new MetaGetter(client), 20 | openidConfigurationGetter: () => new OpenidConfigurationGetter(client.http), 21 | }; 22 | }; 23 | 24 | export default misc; 25 | export { default as LiveChecker } from './liveChecker.js'; 26 | export { default as MetaGetter } from './metaGetter.js'; 27 | export { default as OpenidConfigurationGetter } from './openidConfigurationGetter.js'; 28 | export { default as ReadyChecker } from './readyChecker.js'; 29 | -------------------------------------------------------------------------------- /src/misc/journey.test.ts: -------------------------------------------------------------------------------- 1 | import weaviate from '../v2/index.js'; 2 | 3 | describe('misc endpoints', () => { 4 | const client = weaviate.client({ 5 | scheme: 'http', 6 | host: 'localhost:8080', 7 | }); 8 | 9 | const authClient = weaviate.client({ 10 | scheme: 'http', 11 | host: 'localhost:8085', 12 | }); 13 | 14 | it('reports as live', () => { 15 | return client.misc 16 | .liveChecker() 17 | .do() 18 | .then((res: any) => expect(res).toEqual(true)) 19 | .catch((e: any) => { 20 | throw new Error('it should not have errord: ' + e); 21 | }); 22 | }); 23 | 24 | it('reports as not live with a broken url', () => { 25 | const brokenClient = weaviate.client({ 26 | scheme: 'http', 27 | host: 'localhost:12345', // note the incorrect port 28 | }); 29 | 30 | return brokenClient.misc 31 | .liveChecker() 32 | .do() 33 | .then((res: any) => expect(res).toEqual(false)) 34 | .catch((e: any) => { 35 | throw new Error('it should not have errord: ' + e); 36 | }); 37 | }); 38 | 39 | it('reports as ready', () => { 40 | return client.misc 41 | .readyChecker() 42 | .do() 43 | .then((res: any) => expect(res).toEqual(true)) 44 | .catch((e: any) => { 45 | throw new Error('it should not have errord: ' + e); 46 | }); 47 | }); 48 | 49 | it('reports as not ready with a broken url', () => { 50 | const brokenClient = weaviate.client({ 51 | scheme: 'http', 52 | host: 'localhost:12345', // note the incorrect port 53 | }); 54 | 55 | return brokenClient.misc 56 | .readyChecker() 57 | .do() 58 | .then((res: any) => expect(res).toEqual(false)) 59 | .catch((e: any) => { 60 | throw new Error('it should not have errord: ' + e); 61 | }); 62 | }); 63 | 64 | it('displays meta info', () => { 65 | return client.misc 66 | .metaGetter() 67 | .do() 68 | .then((res: any) => { 69 | expect(res.version).toBeDefined(); 70 | expect(res.modules['text2vec-contextionary'].wordCount).toBeDefined(); 71 | expect(res.modules['text2vec-contextionary'].wordCount).toBeGreaterThan(100); 72 | }) 73 | .catch((e: any) => { 74 | throw new Error('it should not have errord: ' + e); 75 | }); 76 | }); 77 | 78 | it('shows oidc config as undefined when not set', () => { 79 | return client.misc 80 | .openidConfigurationGetter() 81 | .do() 82 | .then((res: any) => { 83 | expect(res).toBeUndefined(); 84 | }) 85 | .catch((e: any) => { 86 | throw new Error('it should not have errord: ' + e); 87 | }); 88 | }); 89 | 90 | it('shows oidc config when set', () => { 91 | return authClient.misc 92 | .openidConfigurationGetter() 93 | .do() 94 | .then((res: any) => { 95 | expect(res.clientId).toEqual('wcs'); 96 | expect(res.href).toContain('.well-known/openid-configuration'); 97 | expect(res.scopes).toEqual(['openid', 'email']); 98 | }); 99 | }); 100 | }); 101 | -------------------------------------------------------------------------------- /src/misc/liveChecker.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import { DbVersionProvider } from '../utils/dbVersion.js'; 3 | import { CommandBase } from '../validation/commandBase.js'; 4 | 5 | export default class LiveChecker extends CommandBase { 6 | private dbVersionProvider: DbVersionProvider; 7 | 8 | constructor(client: Connection, dbVersionProvider: DbVersionProvider) { 9 | super(client); 10 | this.dbVersionProvider = dbVersionProvider; 11 | } 12 | 13 | validate() { 14 | // nothing to validate 15 | } 16 | 17 | do = () => { 18 | return this.client 19 | .get('/.well-known/live', false) 20 | .then(() => { 21 | setTimeout(() => this.dbVersionProvider.refresh()); 22 | return Promise.resolve(true); 23 | }) 24 | .catch(() => Promise.resolve(false)); 25 | }; 26 | } 27 | -------------------------------------------------------------------------------- /src/misc/metaGetter.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import { Meta } from '../openapi/types.js'; 3 | import { CommandBase } from '../validation/commandBase.js'; 4 | 5 | export default class MetaGetter extends CommandBase { 6 | constructor(client: Connection) { 7 | super(client); 8 | } 9 | 10 | validate() { 11 | // nothing to validate 12 | } 13 | 14 | do = (): Promise => { 15 | return this.client.get('/meta', true); 16 | }; 17 | } 18 | -------------------------------------------------------------------------------- /src/misc/openidConfigurationGetter.ts: -------------------------------------------------------------------------------- 1 | import { HttpClient } from '../connection/http.js'; 2 | 3 | export default class OpenidConfigurationGetterGetter { 4 | private client: HttpClient; 5 | constructor(client: HttpClient) { 6 | this.client = client; 7 | } 8 | 9 | do = () => { 10 | return this.client 11 | .getRaw('/.well-known/openid-configuration') 12 | .then((res: { status: number; json: () => any }) => { 13 | if (res.status < 400) { 14 | return res.json(); 15 | } 16 | 17 | if (res.status == 404) { 18 | // OIDC is not configured 19 | return Promise.resolve(undefined); 20 | } 21 | 22 | return Promise.reject(new Error(`unexpected status code: ${res.status}`)); 23 | }); 24 | }; 25 | } 26 | -------------------------------------------------------------------------------- /src/misc/readyChecker.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import { DbVersionProvider } from '../utils/dbVersion.js'; 3 | import { CommandBase } from '../validation/commandBase.js'; 4 | 5 | export default class ReadyChecker extends CommandBase { 6 | private dbVersionProvider: DbVersionProvider; 7 | 8 | constructor(client: Connection, dbVersionProvider: DbVersionProvider) { 9 | super(client); 10 | this.dbVersionProvider = dbVersionProvider; 11 | } 12 | 13 | validate() { 14 | // nothing to validate 15 | } 16 | 17 | do = () => { 18 | return this.client 19 | .get('/.well-known/ready', false) 20 | .then(() => { 21 | setTimeout(() => this.dbVersionProvider.refresh()); 22 | return Promise.resolve(true); 23 | }) 24 | .catch(() => Promise.resolve(false)); 25 | }; 26 | } 27 | -------------------------------------------------------------------------------- /src/roles/types.ts: -------------------------------------------------------------------------------- 1 | import { Action, WeaviateUserType } from '../openapi/types.js'; 2 | 3 | export type BackupsAction = Extract; 4 | export type ClusterAction = Extract; 5 | export type CollectionsAction = Extract< 6 | Action, 7 | | 'create_collections' 8 | | 'delete_collections' 9 | | 'read_collections' 10 | | 'update_collections' 11 | | 'manage_collections' 12 | >; 13 | export type DataAction = Extract< 14 | Action, 15 | 'create_data' | 'delete_data' | 'read_data' | 'update_data' | 'manage_data' 16 | >; 17 | export type NodesAction = Extract; 18 | export type RolesAction = Extract; 19 | export type TenantsAction = Extract< 20 | Action, 21 | 'create_tenants' | 'delete_tenants' | 'read_tenants' | 'update_tenants' 22 | >; 23 | export type UsersAction = Extract; 24 | 25 | export type UserAssignment = { 26 | id: string; 27 | userType: WeaviateUserType; 28 | }; 29 | 30 | export type BackupsPermission = { 31 | collection: string; 32 | actions: BackupsAction[]; 33 | }; 34 | 35 | export type ClusterPermission = { 36 | actions: ClusterAction[]; 37 | }; 38 | 39 | export type CollectionsPermission = { 40 | collection: string; 41 | actions: CollectionsAction[]; 42 | }; 43 | 44 | export type DataPermission = { 45 | collection: string; 46 | tenant: string; 47 | actions: DataAction[]; 48 | }; 49 | 50 | export type NodesPermission = { 51 | collection: string; 52 | verbosity: 'verbose' | 'minimal'; 53 | actions: NodesAction[]; 54 | }; 55 | 56 | export type RolesPermission = { 57 | role: string; 58 | actions: RolesAction[]; 59 | }; 60 | 61 | export type TenantsPermission = { 62 | collection: string; 63 | tenant: string; 64 | actions: TenantsAction[]; 65 | }; 66 | 67 | export type UsersPermission = { 68 | users: string; 69 | actions: UsersAction[]; 70 | }; 71 | 72 | export type Role = { 73 | name: string; 74 | backupsPermissions: BackupsPermission[]; 75 | clusterPermissions: ClusterPermission[]; 76 | collectionsPermissions: CollectionsPermission[]; 77 | dataPermissions: DataPermission[]; 78 | nodesPermissions: NodesPermission[]; 79 | rolesPermissions: RolesPermission[]; 80 | tenantsPermissions: TenantsPermission[]; 81 | usersPermissions: UsersPermission[]; 82 | }; 83 | 84 | export type Permission = 85 | | BackupsPermission 86 | | ClusterPermission 87 | | CollectionsPermission 88 | | DataPermission 89 | | NodesPermission 90 | | RolesPermission 91 | | TenantsPermission 92 | | UsersPermission; 93 | 94 | export type PermissionsInput = Permission | Permission[] | Permission[][] | (Permission | Permission[])[]; 95 | -------------------------------------------------------------------------------- /src/schema/classCreator.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import { WeaviateClass } from '../openapi/types.js'; 3 | import { CommandBase } from '../validation/commandBase.js'; 4 | 5 | export default class ClassCreator extends CommandBase { 6 | private class!: WeaviateClass; 7 | 8 | constructor(client: Connection) { 9 | super(client); 10 | } 11 | 12 | withClass = (classObj: object) => { 13 | this.class = classObj; 14 | return this; 15 | }; 16 | 17 | validateClass = () => { 18 | if (this.class == undefined || this.class == null) { 19 | this.addError('class object must be set - set with .withClass(class)'); 20 | } 21 | }; 22 | 23 | validate() { 24 | this.validateClass(); 25 | } 26 | 27 | do = (): Promise => { 28 | this.validateClass(); 29 | if (this.errors.length > 0) { 30 | return Promise.reject(new Error('invalid usage: ' + this.errors.join(', '))); 31 | } 32 | const path = `/schema`; 33 | return this.client.postReturn(path, this.class); 34 | }; 35 | } 36 | -------------------------------------------------------------------------------- /src/schema/classDeleter.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import { CommandBase } from '../validation/commandBase.js'; 3 | import { isValidStringProperty } from '../validation/string.js'; 4 | 5 | export default class ClassDeleter extends CommandBase { 6 | private className?: string; 7 | 8 | constructor(client: Connection) { 9 | super(client); 10 | } 11 | 12 | withClassName = (className: string) => { 13 | this.className = className; 14 | return this; 15 | }; 16 | 17 | validateClassName = () => { 18 | if (!isValidStringProperty(this.className)) { 19 | this.addError('className must be set - set with .withClassName(className)'); 20 | } 21 | }; 22 | 23 | validate = () => { 24 | this.validateClassName(); 25 | }; 26 | 27 | do = (): Promise => { 28 | this.validate(); 29 | if (this.errors.length > 0) { 30 | return Promise.reject(new Error('invalid usage: ' + this.errors.join(', '))); 31 | } 32 | const path = `/schema/${this.className}`; 33 | return this.client.delete(path, undefined, false); 34 | }; 35 | } 36 | -------------------------------------------------------------------------------- /src/schema/classExists.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import { WeaviateSchema } from '../openapi/types.js'; 3 | import { CommandBase } from '../validation/commandBase.js'; 4 | import { isValidStringProperty } from '../validation/string.js'; 5 | 6 | export default class ClassExists extends CommandBase { 7 | private className?: string; 8 | 9 | constructor(client: Connection) { 10 | super(client); 11 | } 12 | 13 | withClassName = (className: string) => { 14 | this.className = className; 15 | return this; 16 | }; 17 | 18 | validateClassName = () => { 19 | if (!isValidStringProperty(this.className)) { 20 | this.addError('className must be set - set with .withClassName(className)'); 21 | } 22 | }; 23 | 24 | validate = () => { 25 | this.validateClassName(); 26 | }; 27 | 28 | do = (): Promise => { 29 | this.validate(); 30 | if (this.errors.length > 0) { 31 | return Promise.reject(new Error('invalid usage: ' + this.errors.join(', '))); 32 | } 33 | const path = `/schema`; 34 | return this.client 35 | .get(path) 36 | .then((res) => (res.classes ? res.classes.some((c) => c.class === this.className) : false)); 37 | }; 38 | } 39 | -------------------------------------------------------------------------------- /src/schema/classGetter.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import { WeaviateClass } from '../openapi/types.js'; 3 | import { CommandBase } from '../validation/commandBase.js'; 4 | import { isValidStringProperty } from '../validation/string.js'; 5 | 6 | export default class ClassGetter extends CommandBase { 7 | private className?: string; 8 | 9 | constructor(client: Connection) { 10 | super(client); 11 | } 12 | 13 | withClassName = (className: string) => { 14 | this.className = className; 15 | return this; 16 | }; 17 | 18 | validateClassName = () => { 19 | if (!isValidStringProperty(this.className)) { 20 | this.addError('className must be set - set with .withClassName(className)'); 21 | } 22 | }; 23 | 24 | validate = () => { 25 | this.validateClassName(); 26 | }; 27 | 28 | do = (): Promise => { 29 | this.validate(); 30 | if (this.errors.length > 0) { 31 | return Promise.reject(new Error('invalid usage: ' + this.errors.join(', '))); 32 | } 33 | const path = `/schema/${this.className}`; 34 | return this.client.get(path); 35 | }; 36 | } 37 | -------------------------------------------------------------------------------- /src/schema/classUpdater.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import { WeaviateClass } from '../openapi/types.js'; 3 | import { CommandBase } from '../validation/commandBase.js'; 4 | 5 | export default class ClassUpdater extends CommandBase { 6 | private class!: WeaviateClass; 7 | 8 | constructor(client: Connection) { 9 | super(client); 10 | } 11 | 12 | withClass = (classObj: WeaviateClass) => { 13 | this.class = classObj; 14 | return this; 15 | }; 16 | 17 | validateClass = () => { 18 | if (this.class == undefined || this.class == null) { 19 | this.addError('class object must be set - set with .withClass(class)'); 20 | } 21 | }; 22 | 23 | validate() { 24 | this.validateClass(); 25 | } 26 | 27 | do = (): Promise => { 28 | this.validateClass(); 29 | if (this.errors.length > 0) { 30 | return Promise.reject(new Error('invalid usage: ' + this.errors.join(', '))); 31 | } 32 | const path = `/schema/${this.class.class}`; 33 | return this.client.put(path, this.class, false); 34 | }; 35 | } 36 | -------------------------------------------------------------------------------- /src/schema/deleteAll.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import ClassDeleter from './classDeleter.js'; 3 | import SchemaGetter from './getter.js'; 4 | 5 | export default async (client: Connection) => { 6 | const getter = new SchemaGetter(client); 7 | const schema = await getter.do(); 8 | await Promise.all( 9 | schema.classes 10 | ? schema.classes.map((c) => { 11 | const deleter = new ClassDeleter(client); 12 | return deleter.withClassName(c.class as string).do(); 13 | }) 14 | : [] 15 | ); 16 | }; 17 | -------------------------------------------------------------------------------- /src/schema/getter.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import { WeaviateSchema } from '../openapi/types.js'; 3 | import { CommandBase } from '../validation/commandBase.js'; 4 | 5 | export default class SchemaGetter extends CommandBase { 6 | constructor(client: Connection) { 7 | super(client); 8 | } 9 | 10 | validate() { 11 | // nothing to validate 12 | } 13 | 14 | do = (): Promise => { 15 | if (this.errors.length > 0) { 16 | return Promise.reject(new Error('invalid usage: ' + this.errors.join(', '))); 17 | } 18 | const path = `/schema`; 19 | return this.client.get(path); 20 | }; 21 | } 22 | -------------------------------------------------------------------------------- /src/schema/propertyCreator.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import { Property } from '../openapi/types.js'; 3 | import { CommandBase } from '../validation/commandBase.js'; 4 | import { isValidStringProperty } from '../validation/string.js'; 5 | 6 | export default class PropertyCreator extends CommandBase { 7 | private className!: string; 8 | private property!: Property; 9 | 10 | constructor(client: Connection) { 11 | super(client); 12 | } 13 | 14 | withClassName = (className: string) => { 15 | this.className = className; 16 | return this; 17 | }; 18 | 19 | withProperty = (property: Property) => { 20 | this.property = property; 21 | return this; 22 | }; 23 | 24 | validateClassName = () => { 25 | if (!isValidStringProperty(this.className)) { 26 | this.addError('className must be set - set with .withClassName(className)'); 27 | } 28 | }; 29 | 30 | validateProperty = () => { 31 | if (this.property == undefined || this.property == null) { 32 | this.addError('property must be set - set with .withProperty(property)'); 33 | } 34 | }; 35 | 36 | validate = () => { 37 | this.validateClassName(); 38 | this.validateProperty(); 39 | }; 40 | 41 | do = (): Promise => { 42 | this.validate(); 43 | if (this.errors.length > 0) { 44 | return Promise.reject(new Error('invalid usage: ' + this.errors.join(', '))); 45 | } 46 | const path = `/schema/${this.className}/properties`; 47 | return this.client.postReturn(path, this.property); 48 | }; 49 | } 50 | -------------------------------------------------------------------------------- /src/schema/shardUpdater.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import { CommandBase } from '../validation/commandBase.js'; 3 | import { isValidStringProperty } from '../validation/string.js'; 4 | 5 | export default class ShardUpdater extends CommandBase { 6 | private className!: string; 7 | private shardName!: string; 8 | private status!: string; 9 | 10 | constructor(client: Connection) { 11 | super(client); 12 | } 13 | 14 | withClassName = (className: string) => { 15 | this.className = className; 16 | return this; 17 | }; 18 | 19 | validateClassName = () => { 20 | if (!isValidStringProperty(this.className)) { 21 | this.addError('className must be set - set with .withClassName(className)'); 22 | } 23 | }; 24 | 25 | withShardName = (shardName: string) => { 26 | this.shardName = shardName; 27 | return this; 28 | }; 29 | 30 | validateShardName = () => { 31 | if (!isValidStringProperty(this.shardName)) { 32 | this.addError('shardName must be set - set with .withShardName(shardName)'); 33 | } 34 | }; 35 | 36 | withStatus = (status: string) => { 37 | this.status = status; 38 | return this; 39 | }; 40 | 41 | validateStatus = () => { 42 | if (!isValidStringProperty(this.status)) { 43 | this.addError('status must be set - set with .withStatus(status)'); 44 | } 45 | }; 46 | 47 | validate = () => { 48 | this.validateClassName(); 49 | this.validateShardName(); 50 | this.validateStatus(); 51 | }; 52 | 53 | do = () => { 54 | this.validate(); 55 | if (this.errors.length > 0) { 56 | return Promise.reject(new Error(`invalid usage: ${this.errors.join(', ')}`)); 57 | } 58 | 59 | return updateShard(this.client, this.className, this.shardName, this.status); 60 | }; 61 | } 62 | 63 | export function updateShard(client: Connection, className: string, shardName: string, status: string) { 64 | const path = `/schema/${className}/shards/${shardName}`; 65 | return client.put(path, { status: status }, true); 66 | } 67 | -------------------------------------------------------------------------------- /src/schema/shardsGetter.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import { ShardStatusList } from '../openapi/types.js'; 3 | import { CommandBase } from '../validation/commandBase.js'; 4 | import { isValidStringProperty } from '../validation/string.js'; 5 | 6 | export default class ShardsGetter extends CommandBase { 7 | private className?: string; 8 | private tenant?: string; 9 | 10 | constructor(client: Connection) { 11 | super(client); 12 | } 13 | 14 | withClassName = (className: string) => { 15 | this.className = className; 16 | return this; 17 | }; 18 | 19 | withTenant = (tenant: string) => { 20 | this.tenant = tenant; 21 | return this; 22 | }; 23 | 24 | validateClassName = () => { 25 | if (!isValidStringProperty(this.className)) { 26 | this.addError('className must be set - set with .withClassName(className)'); 27 | } 28 | }; 29 | 30 | validate = () => { 31 | this.validateClassName(); 32 | }; 33 | 34 | do = (): Promise => { 35 | this.validate(); 36 | if (this.errors.length > 0) { 37 | return Promise.reject(new Error(`invalid usage: ${this.errors.join(', ')}`)); 38 | } 39 | 40 | return getShards(this.client, this.className, this.tenant); 41 | }; 42 | } 43 | 44 | export function getShards(client: Connection, className: any, tenant?: string) { 45 | const path = `/schema/${className}/shards${tenant ? `?tenant=${tenant}` : ''}`; 46 | return client.get(path); 47 | } 48 | -------------------------------------------------------------------------------- /src/schema/shardsUpdater.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import { ShardStatusList } from '../openapi/types.js'; 3 | import { CommandBase } from '../validation/commandBase.js'; 4 | import { isValidStringProperty } from '../validation/string.js'; 5 | import { updateShard } from './shardUpdater.js'; 6 | import { getShards } from './shardsGetter.js'; 7 | 8 | export default class ShardsUpdater extends CommandBase { 9 | private className!: string; 10 | private shards: ShardStatusList; 11 | private status!: string; 12 | 13 | constructor(client: Connection) { 14 | super(client); 15 | this.shards = []; 16 | } 17 | 18 | withClassName = (className: string) => { 19 | this.className = className; 20 | return this; 21 | }; 22 | 23 | validateClassName = () => { 24 | if (!isValidStringProperty(this.className)) { 25 | this.addError('className must be set - set with .withClassName(className)'); 26 | } 27 | }; 28 | 29 | withStatus = (status: string) => { 30 | this.status = status; 31 | return this; 32 | }; 33 | 34 | validateStatus = () => { 35 | if (!isValidStringProperty(this.status)) { 36 | this.addError('status must be set - set with .withStatus(status)'); 37 | } 38 | }; 39 | 40 | validate = () => { 41 | this.validateClassName(); 42 | this.validateStatus(); 43 | }; 44 | 45 | updateShards = async () => { 46 | const payload: any = await Promise.all( 47 | Array.from({ length: this.shards.length }, (_, i) => 48 | updateShard(this.client, this.className, this.shards[i].name || '', this.status) 49 | .then((res: any) => { 50 | return { name: this.shards[i].name, status: res.status }; 51 | }) 52 | .catch((err: any) => this.addError(err.toString())) 53 | ) 54 | ); 55 | 56 | if (this.errors.length > 0) { 57 | return Promise.reject(new Error(`failed to update shards: ${this.errors.join(', ')}`)); 58 | } 59 | 60 | return Promise.resolve(payload); 61 | }; 62 | 63 | do = (): Promise => { 64 | this.validate(); 65 | if (this.errors.length > 0) { 66 | return Promise.reject(new Error(`invalid usage: ${this.errors.join(', ')}`)); 67 | } 68 | 69 | return getShards(this.client, this.className) 70 | .then((shards: ShardStatusList) => (this.shards = shards)) 71 | .then(() => { 72 | return this.updateShards(); 73 | }) 74 | .then((payload: ShardStatusList) => { 75 | return payload; 76 | }) 77 | .catch((err: any) => { 78 | return Promise.reject(err); 79 | }); 80 | }; 81 | } 82 | -------------------------------------------------------------------------------- /src/schema/tenantsCreator.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import { Tenant } from '../openapi/types.js'; 3 | import { CommandBase } from '../validation/commandBase.js'; 4 | 5 | export default class TenantsCreator extends CommandBase { 6 | private className: string; 7 | private tenants: Array; 8 | 9 | constructor(client: Connection, className: string, tenants: Array) { 10 | super(client); 11 | this.className = className; 12 | this.tenants = tenants; 13 | } 14 | 15 | validate = () => { 16 | // nothing to validate 17 | }; 18 | 19 | do = (): Promise> => { 20 | return this.client.postReturn(`/schema/${this.className}/tenants`, this.tenants); 21 | }; 22 | } 23 | -------------------------------------------------------------------------------- /src/schema/tenantsDeleter.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import { CommandBase } from '../validation/commandBase.js'; 3 | 4 | export default class TenantsDeleter extends CommandBase { 5 | private className: string; 6 | private tenants: Array; 7 | 8 | constructor(client: Connection, className: string, tenants: Array) { 9 | super(client); 10 | this.className = className; 11 | this.tenants = tenants; 12 | } 13 | 14 | validate = () => { 15 | // nothing to validate 16 | }; 17 | 18 | do = (): Promise => { 19 | return this.client.delete(`/schema/${this.className}/tenants`, this.tenants, false); 20 | }; 21 | } 22 | -------------------------------------------------------------------------------- /src/schema/tenantsExists.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import { CommandBase } from '../validation/commandBase.js'; 3 | 4 | export default class TenantsExists extends CommandBase { 5 | private className: string; 6 | private tenant: string; 7 | 8 | constructor(client: Connection, className: string, tenant: string) { 9 | super(client); 10 | this.className = className; 11 | this.tenant = tenant; 12 | } 13 | 14 | validate = () => { 15 | // nothing to validate 16 | }; 17 | 18 | do = (): Promise => { 19 | return this.client.head(`/schema/${this.className}/tenants/${this.tenant}`, undefined); 20 | }; 21 | } 22 | -------------------------------------------------------------------------------- /src/schema/tenantsGetter.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import { Tenant } from '../openapi/types.js'; 3 | import { CommandBase } from '../validation/commandBase.js'; 4 | 5 | export default class TenantsGetter extends CommandBase { 6 | private className: string; 7 | 8 | constructor(client: Connection, className: string) { 9 | super(client); 10 | this.className = className; 11 | } 12 | 13 | validate = () => { 14 | // nothing to validate 15 | }; 16 | 17 | do = (): Promise> => { 18 | return this.client.get(`/schema/${this.className}/tenants`); 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /src/schema/tenantsUpdater.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import { Tenant } from '../openapi/types.js'; 3 | import { CommandBase } from '../validation/commandBase.js'; 4 | 5 | export default class TenantsUpdater extends CommandBase { 6 | private className: string; 7 | private tenants: Array; 8 | 9 | constructor(client: Connection, className: string, tenants: Array) { 10 | super(client); 11 | this.className = className; 12 | this.tenants = tenants; 13 | } 14 | 15 | validate = () => { 16 | // nothing to validate 17 | }; 18 | 19 | do = (): Promise> => { 20 | return this.client.put(`/schema/${this.className}/tenants`, this.tenants); 21 | }; 22 | } 23 | -------------------------------------------------------------------------------- /src/schema/vectorAdder.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | import { VectorConfig } from '../index.js'; 3 | import { CommandBase } from '../validation/commandBase.js'; 4 | import { isValidStringProperty } from '../validation/string.js'; 5 | import ClassGetter from './classGetter.js'; 6 | 7 | export default class VectorAdder extends CommandBase { 8 | private className!: string; 9 | private vectors!: Record; 10 | 11 | constructor(client: Connection) { 12 | super(client); 13 | } 14 | 15 | withClassName = (className: string) => { 16 | this.className = className; 17 | return this; 18 | }; 19 | withVectors = (vectors: Record) => { 20 | this.vectors = vectors; 21 | return this; 22 | }; 23 | 24 | validateClassName = () => { 25 | if (!isValidStringProperty(this.className)) { 26 | this.addError('className must be set - set with .withClassName(className)'); 27 | } 28 | }; 29 | 30 | validate = () => { 31 | this.validateClassName(); 32 | }; 33 | 34 | do = (): Promise => { 35 | this.validate(); 36 | if (this.errors.length > 0) { 37 | return Promise.reject(new Error('invalid usage: ' + this.errors.join(', '))); 38 | } 39 | 40 | return new ClassGetter(this.client) 41 | .withClassName(this.className) 42 | .do() 43 | .then(async (schema) => { 44 | if (schema.vectorConfig === undefined) { 45 | schema.vectorConfig = {}; 46 | } 47 | 48 | for (const [key, value] of Object.entries(this.vectors)) { 49 | if (schema.vectorConfig[key] !== undefined) { 50 | continue; 51 | } 52 | schema.vectorConfig![key] = { ...value }; 53 | } 54 | 55 | const path = `/schema/${this.className}`; 56 | await this.client.put(path, schema); 57 | }); 58 | }; 59 | } 60 | -------------------------------------------------------------------------------- /src/users/types.ts: -------------------------------------------------------------------------------- 1 | import { WeaviateUserTypeDB as UserTypeDB, WeaviateUserTypeInternal } from '../openapi/types.js'; 2 | import { Role } from '../roles/types.js'; 3 | 4 | export type User = { 5 | id: string; 6 | roles?: Role[]; 7 | }; 8 | 9 | export type UserDB = { 10 | userType: UserTypeDB; 11 | id: string; 12 | roleNames: string[]; 13 | active: boolean; 14 | 15 | createdAt?: Date; 16 | lastUsedAt?: Date; 17 | apiKeyFirstLetters?: string; 18 | }; 19 | 20 | /** Optional arguments to /user/{type}/{username} enpoint. */ 21 | export type GetAssignedRolesOptions = { 22 | includePermissions?: boolean; 23 | }; 24 | 25 | /** Optional arguments to /assign and /revoke endpoints. */ 26 | export type AssignRevokeOptions = { userType?: WeaviateUserTypeInternal }; 27 | 28 | /** Optional arguments to /deactivate endpoint. */ 29 | export type DeactivateOptions = { revokeKey?: boolean }; 30 | 31 | /** Optional arguments to /users and /users/ endpoints. */ 32 | export type GetUserOptions = { includeLastUsedTime?: boolean }; 33 | -------------------------------------------------------------------------------- /src/utils/base64.test.ts: -------------------------------------------------------------------------------- 1 | import { httpClient } from '../connection/http.js'; 2 | import { downloadImageFromURLAsBase64 } from './base64.js'; 3 | 4 | jest.mock('../connection/http.js'); 5 | 6 | describe('downloadImageFromURLAsBase64()', () => { 7 | const mockHttpClient = { 8 | externalGet: jest.fn(), 9 | }; 10 | 11 | beforeEach(() => { 12 | jest.clearAllMocks(); 13 | (httpClient as jest.Mock).mockReturnValue(mockHttpClient); 14 | }); 15 | 16 | it('should convert a downloaded image to base64', async () => { 17 | const mockUrl = 'https://example.com/image.jpg'; 18 | const mockImageData = Buffer.from('image binary data'); 19 | 20 | mockHttpClient.externalGet.mockResolvedValue(mockImageData); 21 | 22 | const result = await downloadImageFromURLAsBase64(mockUrl); 23 | 24 | expect(result).toBe(mockImageData.toString('base64')); 25 | expect(httpClient).toHaveBeenCalledWith({ headers: { 'Content-Type': 'image/*' }, host: '' }); 26 | expect(mockHttpClient.externalGet).toHaveBeenCalledWith(mockUrl); 27 | }); 28 | 29 | it('should throw an error if the URL is invalid', async () => { 30 | const invalidUrl = 'invalid-url'; 31 | 32 | await expect(downloadImageFromURLAsBase64(invalidUrl)).rejects.toThrow('Invalid URL'); 33 | }); 34 | 35 | it('should throw an error if the image download fails', async () => { 36 | const mockUrl = 'https://example.com/image.jpg'; 37 | 38 | mockHttpClient.externalGet.mockRejectedValue(new Error('Network error')); 39 | 40 | await expect(downloadImageFromURLAsBase64(mockUrl)).rejects.toThrow('Failed to download image from URL'); 41 | expect(httpClient).toHaveBeenCalledWith({ headers: { 'Content-Type': 'image/*' }, host: '' }); 42 | expect(mockHttpClient.externalGet).toHaveBeenCalledWith(mockUrl); 43 | }); 44 | 45 | it('should handle empty response data gracefully', async () => { 46 | const mockUrl = 'https://example.com/image.jpg'; 47 | 48 | mockHttpClient.externalGet.mockResolvedValue(Buffer.alloc(0)); 49 | 50 | const result = await downloadImageFromURLAsBase64(mockUrl); 51 | 52 | expect(result).toBe(''); 53 | expect(httpClient).toHaveBeenCalledWith({ headers: { 'Content-Type': 'image/*' }, host: '' }); 54 | expect(mockHttpClient.externalGet).toHaveBeenCalledWith(mockUrl); 55 | }); 56 | 57 | it('should throw an error if the response is not a buffer', async () => { 58 | const mockUrl = 'wrong-url.com'; 59 | 60 | mockHttpClient.externalGet.mockResolvedValue('not a buffer'); 61 | 62 | await expect(downloadImageFromURLAsBase64(mockUrl)).rejects.toThrow('Invalid URL'); 63 | }); 64 | }); 65 | -------------------------------------------------------------------------------- /src/utils/base64.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import { httpClient } from '../connection/http.js'; 3 | 4 | const isFilePromise = (file: string | Buffer): Promise => 5 | new Promise((resolve, reject) => { 6 | if (file instanceof Buffer) { 7 | resolve(false); 8 | } 9 | fs.stat(file, (err, stats) => { 10 | if (err) { 11 | if (err.code == 'ENAMETOOLONG') { 12 | resolve(false); 13 | return; 14 | } 15 | reject(err); 16 | return; 17 | } 18 | if (stats === undefined) { 19 | resolve(false); 20 | return; 21 | } 22 | resolve(stats.isFile()); 23 | }); 24 | }); 25 | 26 | const isUrl = (file: string): file is string => { 27 | if (typeof file !== 'string') return false; 28 | try { 29 | const url = new URL(file); 30 | return !!url; 31 | } catch { 32 | return false; 33 | } 34 | }; 35 | 36 | export const downloadImageFromURLAsBase64 = async (url: string): Promise => { 37 | if (!isUrl(url)) { 38 | throw new Error('Invalid URL'); 39 | } 40 | 41 | try { 42 | const client = httpClient({ 43 | headers: { 'Content-Type': 'image/*' }, 44 | host: '', 45 | }); 46 | 47 | const response = await client.externalGet(url); 48 | 49 | if (!Buffer.isBuffer(response)) { 50 | throw new Error('Response is not a buffer'); 51 | } 52 | 53 | return response.toString('base64'); 54 | } catch (error) { 55 | throw new Error(`Failed to download image from URL: ${url}`); 56 | } 57 | }; 58 | 59 | const isBuffer = (file: string | Buffer): file is Buffer => file instanceof Buffer; 60 | 61 | const fileToBase64 = (file: string | Buffer): Promise => 62 | isFilePromise(file).then((isFile) => 63 | isFile 64 | ? new Promise((resolve, reject) => { 65 | fs.readFile(file, (err, data) => { 66 | if (err) { 67 | reject(err); 68 | } 69 | resolve(data.toString('base64')); 70 | }); 71 | }) 72 | : isBuffer(file) 73 | ? Promise.resolve(file.toString('base64')) 74 | : isUrl(file) 75 | ? downloadImageFromURLAsBase64(file) 76 | : Promise.resolve(file) 77 | ); 78 | 79 | /** 80 | * This function converts a file buffer into a base64 string so that it can be 81 | * sent to Weaviate and stored as a media field. 82 | * 83 | * @param {string | Buffer} file The media to convert either as a base64 string, a file path string, an url, or as a buffer. If you passed a base64 string, the function does nothing and returns the string as is. 84 | * @returns {string} The base64 string 85 | */ 86 | export const toBase64FromMedia = (media: string | Buffer): Promise => fileToBase64(media); 87 | -------------------------------------------------------------------------------- /src/utils/beaconPath.ts: -------------------------------------------------------------------------------- 1 | import { isValidStringProperty } from '../validation/string.js'; 2 | import { isValidWeaviateVersion } from '../validation/version.js'; 3 | import { DbVersionSupport } from './dbVersion.js'; 4 | 5 | const beaconPathPrefix = 'weaviate://localhost'; 6 | 7 | export class BeaconPath { 8 | private dbVersionSupport: DbVersionSupport; 9 | private beaconRegExp: RegExp; 10 | 11 | constructor(dbVersionSupport: DbVersionSupport) { 12 | this.dbVersionSupport = dbVersionSupport; 13 | // matches 14 | // weaviate://localhost/class/id => match[2] = class, match[4] = id 15 | // weaviate://localhost/class/id/ => match[2] = class, match[4] = id 16 | // weaviate://localhost/id => match[2] = id, match[4] = undefined 17 | // weaviate://localhost/id/ => match[2] = id, match[4] = undefined 18 | this.beaconRegExp = /^weaviate:\/\/localhost(\/([^\\/]+))?(\/([^\\/]+))?[\\/]?$/gi; 19 | } 20 | 21 | async rebuild(beacon: string) { 22 | const support = await this.dbVersionSupport.supportsClassNameNamespacedEndpointsPromise(); 23 | const match = new RegExp(this.beaconRegExp).exec(beacon); 24 | if (!match) { 25 | return beacon; 26 | } 27 | let className; 28 | let id; 29 | if (match[4] !== undefined) { 30 | id = match[4]; 31 | className = match[2]; 32 | } else { 33 | id = match[2]; 34 | } 35 | let beaconPath = beaconPathPrefix; 36 | if (support.supports) { 37 | if (isValidStringProperty(className)) { 38 | beaconPath = `${beaconPath}/${className}`; 39 | } else { 40 | support.warns.deprecatedNonClassNameNamespacedEndpointsForBeacons(); 41 | } 42 | } else { 43 | support.warns.notSupportedClassNamespacedEndpointsForBeacons(); 44 | } 45 | if (support.version) { 46 | if (!isValidWeaviateVersion(support.version)) { 47 | support.warns.deprecatedWeaviateTooOld(); 48 | } 49 | } 50 | if (isValidStringProperty(id)) { 51 | beaconPath = `${beaconPath}/${id}`; 52 | } 53 | return beaconPath; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/utils/uuid.ts: -------------------------------------------------------------------------------- 1 | import { v5 as uuid5 } from 'uuid'; 2 | 3 | // Generates UUIDv5, used to consistently generate the same UUID for 4 | // a specific identifier and namespace 5 | export function generateUuid5(identifier: string | number, namespace: string | number = ''): string { 6 | const stringified = identifier.toString() + namespace.toString(); 7 | return uuid5(stringified, uuid5.DNS).toString(); 8 | } 9 | -------------------------------------------------------------------------------- /src/validation/commandBase.ts: -------------------------------------------------------------------------------- 1 | import Connection from '../connection/index.js'; 2 | 3 | export interface ICommandBase { 4 | /** 5 | * The client's connection 6 | */ 7 | client: Connection; 8 | /** 9 | * An array of validation errors 10 | */ 11 | errors: string[]; 12 | /** 13 | * Execute the command 14 | */ 15 | do: () => Promise; 16 | /** 17 | * Optional method to build the payload of an actual call 18 | */ 19 | payload?: () => any; 20 | /** 21 | * validate that all the required parameters were feed to the builder 22 | */ 23 | validate: () => void; 24 | } 25 | 26 | export abstract class CommandBase implements ICommandBase { 27 | private _errors: string[]; 28 | public readonly client: Connection; 29 | 30 | protected constructor(client: Connection) { 31 | this.client = client; 32 | this._errors = []; 33 | } 34 | 35 | public get errors(): string[] { 36 | return this._errors; 37 | } 38 | 39 | addError(error: string) { 40 | this._errors = [...this.errors, error]; 41 | } 42 | 43 | addErrors(errors: string[]) { 44 | this._errors = [...this.errors, ...errors]; 45 | } 46 | 47 | abstract do(): Promise; 48 | 49 | abstract validate(): void; 50 | } 51 | -------------------------------------------------------------------------------- /src/validation/number.ts: -------------------------------------------------------------------------------- 1 | export function isValidIntProperty(input: any) { 2 | return Number.isInteger(input); 3 | } 4 | 5 | export function isValidPositiveIntProperty(input: any) { 6 | return isValidIntProperty(input) && input >= 0; 7 | } 8 | 9 | export function isValidNumber(input: any) { 10 | return typeof input == 'number'; 11 | } 12 | 13 | export function isValidNumberArray(input: any) { 14 | if (Array.isArray(input)) { 15 | for (const i in input) { 16 | if (!isValidNumber(input[i])) { 17 | return false; 18 | } 19 | } 20 | return true; 21 | } 22 | return false; 23 | } 24 | -------------------------------------------------------------------------------- /src/validation/string.ts: -------------------------------------------------------------------------------- 1 | export function isValidStringProperty(input: any) { 2 | return typeof input == 'string' && input.length > 0; 3 | } 4 | 5 | export function isValidStringArray(input: any) { 6 | if (Array.isArray(input)) { 7 | for (const i in input) { 8 | if (!isValidStringProperty(input[i])) { 9 | return false; 10 | } 11 | } 12 | return true; 13 | } 14 | return false; 15 | } 16 | -------------------------------------------------------------------------------- /src/validation/version.ts: -------------------------------------------------------------------------------- 1 | export function isValidWeaviateVersion(version: string) { 2 | if (typeof version === 'string') { 3 | const versionNumbers = version.split('.'); 4 | if (versionNumbers.length >= 2) { 5 | const major = parseInt(versionNumbers[0], 10); 6 | const minor = parseInt(versionNumbers[1], 10); 7 | return !(major <= 1 && minor < 16); 8 | } 9 | } 10 | return true; 11 | } 12 | -------------------------------------------------------------------------------- /test/dbVersionProvider.ts: -------------------------------------------------------------------------------- 1 | import { DbVersion, VersionProvider } from '../src/utils/dbVersion.js'; 2 | 3 | export class TestDbVersionProvider implements VersionProvider { 4 | private version: string; 5 | 6 | constructor(version: string) { 7 | this.version = version; 8 | } 9 | 10 | getVersionString(): Promise { 11 | return Promise.resolve(this.version); 12 | } 13 | 14 | getVersion(): Promise { 15 | return Promise.resolve(DbVersion.fromString(this.version)); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /test/server.ts: -------------------------------------------------------------------------------- 1 | import bodyParser from '@curveball/bodyparser'; 2 | import { Application } from '@curveball/core'; 3 | import { IncomingMessage, Server, ServerResponse } from 'http'; 4 | 5 | export interface IServerCache { 6 | server: Server; 7 | app: Application; 8 | lastRequest: () => any; 9 | port: number; 10 | url: string; 11 | close: () => Promise; 12 | } 13 | 14 | const port = 40101; 15 | let serverCache: IServerCache | null = null; 16 | 17 | export function testServer() { 18 | if (serverCache) { 19 | return serverCache; 20 | } 21 | 22 | let lastRequest: any = null; 23 | const app = new Application(); 24 | 25 | app.use((bodyParser as any)()); 26 | app.use((ctx, next) => { 27 | lastRequest = ctx.request; 28 | return next(); 29 | }); 30 | app.use(getLocalOidcConfig, getRemoteOidcConfig, issueToken, mockGetEndpoint, mockGraphQLResponse); 31 | const server = app.listen(port); 32 | 33 | serverCache = { 34 | server, 35 | app, 36 | lastRequest: () => lastRequest, 37 | port, 38 | url: 'http://localhost:' + port, 39 | close: () => { 40 | return new Promise((res: any) => { 41 | server.close(() => res()); 42 | }); 43 | }, 44 | }; 45 | 46 | return serverCache; 47 | } 48 | 49 | const mockGetEndpoint = (ctx: any, next: any) => { 50 | if (ctx.path !== '/v1/testEndpoint') { 51 | return next(); 52 | } 53 | 54 | ctx.response.status = 200; 55 | ctx.response.body = { message: 'test endpoint' }; 56 | }; 57 | 58 | const mockGraphQLResponse = (ctx: any, next: any) => { 59 | if (ctx.path !== '/v1/graphql') { 60 | return next(); 61 | } 62 | 63 | ctx.response.status = 200; 64 | ctx.response.body = { 65 | data: { 66 | someField: 'someValue', 67 | }, 68 | }; 69 | }; 70 | 71 | const getLocalOidcConfig = (ctx: any, next: any) => { 72 | if (ctx.path !== '/v1/.well-known/openid-configuration') { 73 | return next(); 74 | } 75 | 76 | ctx.response.type = 'application/json'; 77 | ctx.response.body = { 78 | clientId: 'client123', 79 | href: 'http://localhost:' + port + '/remote-openid-configuration', 80 | }; 81 | }; 82 | 83 | const getRemoteOidcConfig = (ctx: any, next: any) => { 84 | if (ctx.path !== '/remote-openid-configuration') { 85 | return next(); 86 | } 87 | 88 | ctx.response.type = 'application/json'; 89 | ctx.response.body = { 90 | token_endpoint: 'http://localhost:' + port + '/token', 91 | grant_types_supported: ['refresh_token', 'password'], 92 | }; 93 | }; 94 | 95 | const issueToken = (ctx: any, next: any) => { 96 | if (ctx.path !== '/token') { 97 | return next(); 98 | } 99 | 100 | ctx.response.type = 'application/json'; 101 | ctx.response.body = { 102 | access_token: 'access_token_000', 103 | refresh_token: 'refresh_token_000', 104 | expires_in: 3600, 105 | }; 106 | }; 107 | -------------------------------------------------------------------------------- /test/version.ts: -------------------------------------------------------------------------------- 1 | import { DbVersion } from '../src/utils/dbVersion'; 2 | 3 | const version = DbVersion.fromString(`v${process.env.WEAVIATE_VERSION!}`); 4 | 5 | /** Run the suite / test only for Weaviate version above this. */ 6 | export const requireAtLeast = (...semver: [...Parameters]) => 7 | version.isAtLeast(...semver) ? describe : describe.skip; 8 | -------------------------------------------------------------------------------- /tools/health.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The gRPC Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // The canonical version of this proto can be found at 16 | // https://github.com/grpc/grpc-proto/blob/master/grpc/health/v1/health.proto 17 | 18 | syntax = "proto3"; 19 | 20 | package grpc.health.v1; 21 | 22 | option csharp_namespace = "Grpc.Health.V1"; 23 | option go_package = "google.golang.org/grpc/health/grpc_health_v1"; 24 | option java_multiple_files = true; 25 | option java_outer_classname = "HealthProto"; 26 | option java_package = "io.grpc.health.v1"; 27 | 28 | message HealthCheckRequest { 29 | string service = 1; 30 | } 31 | 32 | message HealthCheckResponse { 33 | enum ServingStatus { 34 | UNKNOWN = 0; 35 | SERVING = 1; 36 | NOT_SERVING = 2; 37 | SERVICE_UNKNOWN = 3; // Used only by the Watch method. 38 | } 39 | ServingStatus status = 1; 40 | } 41 | 42 | service Health { 43 | // If the requested service is unknown, the call will fail with status 44 | // NOT_FOUND. 45 | rpc Check(HealthCheckRequest) returns (HealthCheckResponse); 46 | 47 | // Performs a watch for the serving status of the requested service. 48 | // The server will immediately send back a message indicating the current 49 | // serving status. It will then subsequently send a new message whenever 50 | // the service's serving status changes. 51 | // 52 | // If the requested service is unknown when the call is received, the 53 | // server will send a message setting the serving status to 54 | // SERVICE_UNKNOWN but will *not* terminate the call. If at some 55 | // future point, the serving status of the service becomes known, the 56 | // server will send a new message with the service's serving status. 57 | // 58 | // If the call terminates with status UNIMPLEMENTED, then clients 59 | // should assume this method is not supported and should not retry the 60 | // call. If the call terminates with any other status (including OK), 61 | // clients should retry the call with appropriate exponential backoff. 62 | rpc Watch(HealthCheckRequest) returns (stream HealthCheckResponse); 63 | } -------------------------------------------------------------------------------- /tools/prepare_release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -euo pipefail 4 | 5 | VERSION=${1-} 6 | REQUIRED_TOOLS="jq git" 7 | 8 | if test -z "$VERSION"; then 9 | echo "Missing version parameter. Usage: $0 VERSION" 10 | exit 1 11 | fi 12 | 13 | if case $VERSION in v*) false;; esac; then 14 | VERSION="v$VERSION" 15 | fi 16 | 17 | for tool in $REQUIRED_TOOLS; do 18 | if ! hash "$tool" 2>/dev/null; then 19 | echo "This script requires '$tool', but it is not installed." 20 | exit 1 21 | fi 22 | done 23 | 24 | if git rev-parse "$VERSION" >/dev/null 2>&1; then 25 | echo "Cannot prepare release, a release for $VERSION already exists" 26 | exit 1 27 | fi 28 | 29 | npm version "${VERSION/v}" 30 | -------------------------------------------------------------------------------- /tools/refresh_protos.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | branchOrTag="${1:-main}" 4 | dir="tools" 5 | mkdir -p ${dir} 6 | curl -LkSs https://api.github.com/repos/weaviate/weaviate/tarball/${branchOrTag} -o ${dir}/weaviate.tar.gz 7 | tar --strip-components=3 -C ${dir} -xvf ${dir}/weaviate.tar.gz $(tar -tf ${dir}/weaviate.tar.gz | grep '^weaviate-weaviate-[^/]\+/grpc/proto/v1') 8 | 9 | ./node_modules/.bin/grpc_tools_node_protoc -I ${dir} \ 10 | --ts_proto_out=./src/proto \ 11 | --ts_proto_opt=forceLong==bigint \ 12 | --ts_proto_opt=esModuleInterop=true \ 13 | --ts_proto_opt=outputServices=nice-grpc,outputServices=generic-definitions,useExactTypes=false \ 14 | ${dir}/v1/*.proto 15 | 16 | ./node_modules/.bin/grpc_tools_node_protoc -I ${dir} \ 17 | --ts_proto_out=./src/proto/google/health/v1 \ 18 | --ts_proto_opt=forceLong==bigint \ 19 | --ts_proto_opt=esModuleInterop=true \ 20 | --ts_proto_opt=outputServices=nice-grpc,outputServices=generic-definitions,useExactTypes=false \ 21 | ${dir}/health.proto 22 | 23 | rm ${dir}/weaviate.tar.gz 24 | 25 | sed -i '' 's/\"protobufjs\/minimal\"/\"protobufjs\/minimal.js\"/g' src/proto/v1/*.ts 26 | sed -i '' 's/\"protobufjs\/minimal\"/\"protobufjs\/minimal.js\"/g' src/proto/google/protobuf/struct.ts 27 | sed -i '' 's/\"protobufjs\/minimal\"/\"protobufjs\/minimal.js\"/g' src/proto/google/health/v1/health.ts 28 | 29 | sed -i '' 's/google\/protobuf\/struct"/google\/protobuf\/struct.js"/g' src/proto/v1/*.ts 30 | 31 | # replace import paths 32 | for filepath in ${dir}/v1/*; do # loops through known protos 33 | filename=${filepath##*/} # extract filename from path 34 | file=${filename%.*} # remove extension 35 | sed -i '' "s/\".\/${file}\"/\".\/${file}.js\"/g" src/proto/v1/*.ts # replace import paths 36 | # e.g. import { Vectors } from "./base"; => import { Vectors } from "./base.js"; 37 | done 38 | 39 | rm -rf ${dir}/v1 40 | 41 | echo "done" 42 | -------------------------------------------------------------------------------- /tools/refresh_schema.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -euo pipefail 4 | 5 | branchOrTag="${1:-main}" 6 | npx openapi-typescript https://raw.githubusercontent.com/weaviate/weaviate/${branchOrTag}/openapi-specs/schema.json -o ./src/openapi/schema.ts 7 | npx prettier --write --no-error-on-unmatched-pattern './src/openapi/schema.ts' 8 | -------------------------------------------------------------------------------- /tsconfig-test.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES6", 4 | "strict": true, 5 | "noImplicitAny": true, 6 | "noImplicitThis": true, 7 | "strictFunctionTypes": true, 8 | "module": "NodeNext", 9 | "moduleResolution": "NodeNext", 10 | "forceConsistentCasingInFileNames": true, 11 | "allowSyntheticDefaultImports": true, 12 | "outDir": "./dist" 13 | }, 14 | "include": ["./test/**/*.ts", "./src/**/*.ts"], 15 | "exclude": ["node_modules", "examples"] 16 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES6", 4 | "strict": true, 5 | "preserveConstEnums": true, 6 | "alwaysStrict": true, 7 | "noImplicitAny": true, 8 | "noImplicitThis": true, 9 | "strictFunctionTypes": true, 10 | "module": "NodeNext", 11 | "moduleResolution": "NodeNext", 12 | "skipLibCheck": true, 13 | "forceConsistentCasingInFileNames": true, 14 | "esModuleInterop": true, 15 | "outDir": "./dist/node", 16 | "declaration": true, 17 | "rootDir": "./src", 18 | "types": ["node", "uuid", "jest"] 19 | }, 20 | "include": ["./src/**/*"], 21 | "exclude": ["**/*.test.ts"] 22 | } 23 | -------------------------------------------------------------------------------- /tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'tsup'; 2 | 3 | export default defineConfig([ 4 | { 5 | entry: [ 6 | 'src/v2/index.ts', 7 | '!src/index.ts', 8 | '!src/**/*.test.ts', 9 | '!src/collections/**/*.ts', 10 | '!src/connection/grpc.ts', 11 | '!src/connection/helpers.ts', 12 | '!src/proto/**/*.ts', 13 | '!src/grpc', 14 | ], 15 | format: ['cjs', 'esm'], 16 | outDir: 'dist/web', 17 | clean: true, 18 | platform: 'browser', 19 | minify: true, 20 | dts: true, 21 | splitting: true, 22 | treeshake: true, 23 | }, 24 | // { 25 | // entry: { 26 | // index: 'src/index.ts', 27 | // }, 28 | // format: ['cjs'], 29 | // outDir: 'dist/node/cjs', 30 | // dts: true, 31 | // target: 'node16', 32 | // platform: 'node', 33 | // }, 34 | ]); 35 | --------------------------------------------------------------------------------