diff --git a/.github/workflows/update-example-deps.yml b/.github/workflows/update-example-deps.yml new file mode 100644 index 000000000..fd734f02a --- /dev/null +++ b/.github/workflows/update-example-deps.yml @@ -0,0 +1,29 @@ + on: + schedule: + - cron: '0 12 * * *' + # for testing, temporarily allow manual triggering + workflow_dispatch: + + jobs: + update-example-deps: + name: Update Momento deps in examples + runs-on: ubuntu-latest + env: + # TODO: remove token stored as secret in favor of using a + # momento-local instance that can be spun up for testing + MOMENTO_API_KEY: ${{ secrets.ALPHA_TEST_AUTH_TOKEN }} + + steps: + - name: Setup repo + uses: actions/checkout@v3 + + - name: Install Node + uses: actions/setup-node@v3 + with: + node-version: 16 + + - name: Run update script + id: validation + run: | + ./scripts/update-all-examples-dependencies.sh + diff --git a/packages/client-sdk-nodejs/package-lock.json b/packages/client-sdk-nodejs/package-lock.json index 1a22953b9..7b4dc6c67 100644 --- a/packages/client-sdk-nodejs/package-lock.json +++ b/packages/client-sdk-nodejs/package-lock.json @@ -9,7 +9,7 @@ "version": "0.0.1", "license": "Apache-2.0", "dependencies": { - "@gomomento/generated-types": "0.96.0", + "@gomomento/generated-types": "0.97.1", "@gomomento/sdk-core": "file:../core", "@grpc/grpc-js": "1.9.0", "@types/google-protobuf": "3.15.10", @@ -133,30 +133,30 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.3.tgz", - "integrity": "sha512-BmR4bWbDIoFJmJ9z2cZ8Gmm2MXgEDgjdWgpKmKWUt54UGFJdlj31ECtbaDvCG/qVdG3AQ1SfpZEs01lUFbzLOQ==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", + "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.3.tgz", - "integrity": "sha512-Jg+msLuNuCJDyBvFv5+OKOUjWMZgd85bKjbICd3zWrKAo+bJ49HJufi7CQE0q0uR8NGyO6xkCACScNqyjHSZew==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.5.tgz", + "integrity": "sha512-Cwc2XjUrG4ilcfOw4wBAK+enbdgwAcAJCfGUItPBKR7Mjw4aEfAFYrLxeRp4jWgtNIKn3n2AlBOfwwafl+42/g==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.3", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.5", "@babel/helper-compilation-targets": "^7.22.15", "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.23.2", - "@babel/parser": "^7.23.3", + "@babel/helpers": "^7.23.5", + "@babel/parser": "^7.23.5", "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.3", - "@babel/types": "^7.23.3", + "@babel/traverse": "^7.23.5", + "@babel/types": "^7.23.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -172,12 +172,12 @@ } }, "node_modules/@babel/core/node_modules/@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", "dev": true, "dependencies": { - "@babel/highlight": "^7.22.13", + "@babel/highlight": "^7.23.4", "chalk": "^2.4.2" }, "engines": { @@ -265,12 +265,12 @@ } }, "node_modules/@babel/generator": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.3.tgz", - "integrity": "sha512-keeZWAV4LU3tW0qRi19HRpabC/ilM0HRBBzf9/k8FFiG4KVpiv0FIy4hHfLfFQZNhziCTPTmd59zoyv6DNISzg==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.5.tgz", + "integrity": "sha512-BPssCHrBD+0YrxviOa3QzpqwhNIXKEtOa2jQrm4FlmkC2apYgRnQcmPWiGZDlGxiNtltnUFolMe8497Esry+jA==", "dev": true, "dependencies": { - "@babel/types": "^7.23.3", + "@babel/types": "^7.23.5", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -403,9 +403,9 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", + "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", "dev": true, "engines": { "node": ">=6.9.0" @@ -421,32 +421,32 @@ } }, "node_modules/@babel/helper-validator-option": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", - "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.2.tgz", - "integrity": "sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.5.tgz", + "integrity": "sha512-oO7us8FzTEsG3U6ag9MfdF1iA/7Z6dz+MtFhifZk8C8o453rGJFFWUP1t+ULM9TUIAzC9uxXEiXjOiVMyd7QPg==", "dev": true, "dependencies": { "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.2", - "@babel/types": "^7.23.0" + "@babel/traverse": "^7.23.5", + "@babel/types": "^7.23.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", - "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", "dev": true, "dependencies": { "@babel/helper-validator-identifier": "^7.22.20", @@ -529,9 +529,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.3.tgz", - "integrity": "sha512-uVsWNvlVsIninV2prNz/3lHCb+5CJ+e+IUBfbjToAHODtfGYLfCFuY4AU7TskI+dAKk+njsPiBjq1gKTvZOBaw==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.5.tgz", + "integrity": "sha512-hOOqoiNXrmGdFbhgCzu6GiURxUgM27Xwd/aPuu8RfHEZPBzL1Z54okAHAQjXfcQNwvrlkAmAp4SlRTZ45vlthQ==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -732,12 +732,12 @@ } }, "node_modules/@babel/template/node_modules/@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", "dev": true, "dependencies": { - "@babel/highlight": "^7.22.13", + "@babel/highlight": "^7.23.4", "chalk": "^2.4.2" }, "engines": { @@ -816,19 +816,19 @@ } }, "node_modules/@babel/traverse": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.3.tgz", - "integrity": "sha512-+K0yF1/9yR0oHdE0StHuEj3uTPzwwbrLGfNOndVJVV2TqA5+j3oljJUb4nmB954FLGjNem976+B+eDuLIjesiQ==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.5.tgz", + "integrity": "sha512-czx7Xy5a6sapWWRx61m1Ke1Ra4vczu1mCTtJam5zRTBOonfdJ+S/B6HYmGYu3fJtr8GGET3si6IhgWVBhJ/m8w==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.3", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.5", "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.3", - "@babel/types": "^7.23.3", + "@babel/parser": "^7.23.5", + "@babel/types": "^7.23.5", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -837,12 +837,12 @@ } }, "node_modules/@babel/traverse/node_modules/@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", "dev": true, "dependencies": { - "@babel/highlight": "^7.22.13", + "@babel/highlight": "^7.23.4", "chalk": "^2.4.2" }, "engines": { @@ -930,12 +930,12 @@ } }, "node_modules/@babel/types": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.3.tgz", - "integrity": "sha512-OZnvoH2l8PK5eUvEcUyCt/sXgr/h+UWpVuBbOljwcrAgUl6lpchoQ++PHGyQy1AtYnVA6CEq3y5xeEI10brpXw==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.5.tgz", + "integrity": "sha512-ON5kSOJwVO6xXVRTvOI0eOnWe7VdUcIpsovGo9U/Br4Ie4UVFQTboO2cYnDhAGU6Fp+UxSiT+pMft0SMHfuq6w==", "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-string-parser": "^7.23.4", "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" }, @@ -1029,9 +1029,9 @@ "link": true }, "node_modules/@gomomento/generated-types": { - "version": "0.96.0", - "resolved": "https://registry.npmjs.org/@gomomento/generated-types/-/generated-types-0.96.0.tgz", - "integrity": "sha512-o4bTdJ/PIkvEMZU4IHcrOGyiAxAnrkHZKFlIDmcmEki2zIvpj7Pqkp+7TqQ6BIH6gVo+IOmTecP56HADVUdM9g==", + "version": "0.97.1", + "resolved": "https://registry.npmjs.org/@gomomento/generated-types/-/generated-types-0.97.1.tgz", + "integrity": "sha512-a3JkF6Q/ehdn48n4IU+icND+2gWXb3Gbb9wLG9VbG2/TUFcR3JDk2YhDqKhEendTbB46IpxsDTsJdpq2eTHpgg==", "dependencies": { "@grpc/grpc-js": "1.9.0", "google-protobuf": "3.21.2", @@ -1641,9 +1641,9 @@ "dev": true }, "node_modules/@types/babel__core": { - "version": "7.20.4", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.4.tgz", - "integrity": "sha512-mLnSC22IC4vcWiuObSRjrLd9XcBTGf59vUSoq2jkQDJ/QQ8PMI9rSuzE+aEV8karUMbskw07bKYoUJCKTUaygg==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", "dev": true, "dependencies": { "@babel/parser": "^7.20.7", @@ -1747,9 +1747,9 @@ "integrity": "sha512-GtTH2crF4MtOIrrAa+jgTV9JX/PfoUCYr6MiZw7O/dkZu5b6gm5dc1nAL0jwGo4ortSBBtGyeVaxdC8X6V+pLg==" }, "node_modules/@types/semver": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.5.tgz", - "integrity": "sha512-+d+WYC1BxJ6yVOgUgzK8gWvp5qF8ssV5r4nsDcZWKRWcDQLQ619tvWAxJQYGgBrO1MnLJC7a5GtiYsAoQ47dJg==", + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", + "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", "dev": true }, "node_modules/@types/stack-utils": { @@ -1765,9 +1765,9 @@ "dev": true }, "node_modules/@types/yargs": { - "version": "17.0.31", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.31.tgz", - "integrity": "sha512-bocYSx4DI8TmdlvxqGpVNXOgCNR1Jj0gNPhhAY+iz1rgKDAaYrAYdFYnhDV1IFuiuVc9HkOwyDcFxaTElF3/wg==", + "version": "17.0.32", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", + "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", "dev": true, "dependencies": { "@types/yargs-parser": "*" @@ -1994,9 +1994,9 @@ } }, "node_modules/acorn-walk": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.0.tgz", - "integrity": "sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA==", + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.1.tgz", + "integrity": "sha512-TgUZgYvqZprrl7YldZNoa9OciCAyZR+Ejm9eXzKCmjsF5IKp/wgQ7Z/ZpjpGTIUPwrHQIcYeI8qDh4PsEwxMbw==", "dev": true, "engines": { "node": ">=0.4.0" @@ -2413,9 +2413,9 @@ } }, "node_modules/browserslist": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", - "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", + "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", "dev": true, "funding": [ { @@ -2432,9 +2432,9 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001541", - "electron-to-chromium": "^1.4.535", - "node-releases": "^2.0.13", + "caniuse-lite": "^1.0.30001565", + "electron-to-chromium": "^1.4.601", + "node-releases": "^2.0.14", "update-browserslist-db": "^1.0.13" }, "bin": { @@ -2504,9 +2504,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001563", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001563.tgz", - "integrity": "sha512-na2WUmOxnwIZtwnFI2CZ/3er0wdNzU7hN+cPYz/z2ajHThnkWjNBOpEPP4n+4r2WPM847JaMotaJE3bnfzjyKw==", + "version": "1.0.30001566", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001566.tgz", + "integrity": "sha512-ggIhCsTxmITBAMmK8yZjEhCO5/47jKXPu6Dha/wuCS4JePVL+3uiDEBuhu2aIoT+bqTOR8L76Ip1ARL9xYsEJA==", "dev": true, "funding": [ { @@ -2828,9 +2828,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.588", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.588.tgz", - "integrity": "sha512-soytjxwbgcCu7nh5Pf4S2/4wa6UIu+A3p03U2yVr53qGxi1/VTR3ENI+p50v+UxqqZAfl48j3z55ud7VHIOr9w==", + "version": "1.4.605", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.605.tgz", + "integrity": "sha512-V52j+P5z6cdRqTjPR/bYNxx7ETCHIkm5VIGuyCy3CMrfSnbEpIlLnk5oHmZo7gYvDfh2TfHeanB6rawyQ23ktg==", "dev": true }, "node_modules/emittery": { @@ -4983,12 +4983,12 @@ } }, "node_modules/jest-message-util/node_modules/@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", "dev": true, "dependencies": { - "@babel/highlight": "^7.22.13", + "@babel/highlight": "^7.23.4", "chalk": "^2.4.2" }, "engines": { @@ -5792,9 +5792,9 @@ "dev": true }, "node_modules/node-releases": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", - "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", "dev": true }, "node_modules/nopt": { @@ -5870,13 +5870,13 @@ } }, "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", "has-symbols": "^1.0.3", "object-keys": "^1.1.1" }, @@ -7298,9 +7298,9 @@ "dev": true }, "node_modules/v8-to-istanbul": { - "version": "9.1.3", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.3.tgz", - "integrity": "sha512-9lDD+EVI2fjFsMWXc6dy5JJzBsVTcQ2fVkfBvncZ6xJWG9wtBhOldG+mHkSL0+V1K/xgZz0JDO5UT5hFwHUghg==", + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz", + "integrity": "sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==", "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.12", diff --git a/packages/client-sdk-nodejs/package.json b/packages/client-sdk-nodejs/package.json index 4f38f2d48..298ffbaef 100644 --- a/packages/client-sdk-nodejs/package.json +++ b/packages/client-sdk-nodejs/package.json @@ -51,7 +51,7 @@ "uuid": "8.3.2" }, "dependencies": { - "@gomomento/generated-types": "0.96.0", + "@gomomento/generated-types": "0.97.1", "@gomomento/sdk-core": "file:../core", "@grpc/grpc-js": "1.9.0", "@types/google-protobuf": "3.15.10", diff --git a/packages/client-sdk-nodejs/src/internal/vector-index-data-client.ts b/packages/client-sdk-nodejs/src/internal/vector-index-data-client.ts index 2bc202ff7..8f9036c0f 100644 --- a/packages/client-sdk-nodejs/src/internal/vector-index-data-client.ts +++ b/packages/client-sdk-nodejs/src/internal/vector-index-data-client.ts @@ -1,6 +1,5 @@ import {version} from '../../package.json'; import {IVectorIndexDataClient} from '@gomomento/sdk-core/dist/src/internal/clients/vector/IVectorIndexDataClient'; -import {VectorIndexItem} from '@gomomento/sdk-core/dist/src/messages/vector-index'; import { CredentialProvider, InvalidArgumentError, @@ -10,7 +9,12 @@ import { VectorDeleteItemBatch, VectorSearch, VectorSearchAndFetchVectors, + VectorIndexMetadata, + VectorIndexItem, VectorUpsertItemBatch, + VectorIndexStoredItem, + VectorGetItemBatch, + VectorGetItemMetadataBatch, } from '@gomomento/sdk-core'; import {VectorIndexClientProps} from '../vector-index-client-props'; import {VectorIndexConfiguration} from '../config/vector-index-configuration'; @@ -265,7 +269,7 @@ export class VectorIndexDataClient implements IVectorIndexDataClient { private static deserializeMetadata( metadata: vectorindex._Metadata[], errorCallback: () => void - ): Record> { + ): VectorIndexMetadata { return metadata.reduce((acc, metadata) => { const field = metadata.field; switch (metadata.value) { @@ -289,7 +293,7 @@ export class VectorIndexDataClient implements IVectorIndexDataClient { break; } return acc; - }, {} as Record>); + }, {} as VectorIndexMetadata); } private async sendSearch( @@ -411,6 +415,155 @@ export class VectorIndexDataClient implements IVectorIndexDataClient { }); } + public async getItemBatch( + indexName: string, + ids: string[] + ): Promise { + try { + validateIndexName(indexName); + } catch (err) { + return new VectorGetItemBatch.Error(normalizeSdkError(err as Error)); + } + return await this.sendGetItemBatch(indexName, ids); + } + + private async sendGetItemBatch( + indexName: string, + ids: string[] + ): Promise { + const request = new vectorindex._GetItemBatchRequest({ + index_name: indexName, + ids: ids, + metadata_fields: VectorIndexDataClient.prepareMetadataRequest({ + metadataFields: ALL_VECTOR_METADATA, + }), + }); + return await new Promise(resolve => { + this.client.GetItemBatch( + request, + {interceptors: this.interceptors}, + (err, resp) => { + if (resp) { + resolve( + new VectorGetItemBatch.Success( + resp.item_response.reduce((acc, itemResponse) => { + switch (itemResponse.response) { + case 'hit': + acc[itemResponse.hit.id] = { + id: itemResponse.hit.id, + vector: itemResponse.hit.vector.elements, + metadata: VectorIndexDataClient.deserializeMetadata( + itemResponse.hit.metadata, + () => + resolve( + new VectorGetItemBatch.Error( + new UnknownError( + 'GetItemBatch responded with an unknown result' + ) + ) + ) + ), + }; + break; + case 'miss': + break; + default: + resolve( + new VectorGetItemBatch.Error( + new UnknownError( + 'GetItemBatch responded with an unknown result' + ) + ) + ); + break; + } + return acc; + }, {} as Record) + ) + ); + } else { + resolve(new VectorGetItemBatch.Error(cacheServiceErrorMapper(err))); + } + } + ); + }); + } + + public async getItemMetadataBatch( + indexName: string, + ids: string[] + ): Promise { + try { + validateIndexName(indexName); + } catch (err) { + return new VectorGetItemMetadataBatch.Error( + normalizeSdkError(err as Error) + ); + } + return await this.sendGetItemMetadataBatch(indexName, ids); + } + + private async sendGetItemMetadataBatch( + indexName: string, + ids: string[] + ): Promise { + const request = new vectorindex._GetItemMetadataBatchRequest({ + index_name: indexName, + ids: ids, + metadata_fields: VectorIndexDataClient.prepareMetadataRequest({ + metadataFields: ALL_VECTOR_METADATA, + }), + }); + return await new Promise(resolve => { + this.client.GetItemMetadataBatch( + request, + {interceptors: this.interceptors}, + (err, resp) => { + if (resp) { + resolve( + new VectorGetItemMetadataBatch.Success( + resp.item_metadata_response.reduce((acc, itemResponse) => { + switch (itemResponse.response) { + case 'hit': + acc[itemResponse.hit.id] = + VectorIndexDataClient.deserializeMetadata( + itemResponse.hit.metadata, + () => + resolve( + new VectorGetItemMetadataBatch.Error( + new UnknownError( + 'GetItemMetadataBatch responded with an unknown result' + ) + ) + ) + ); + break; + case 'miss': + break; + default: + resolve( + new VectorGetItemMetadataBatch.Error( + new UnknownError( + 'GetItemMetadataBatch responded with an unknown result' + ) + ) + ); + break; + } + return acc; + }, {} as Record) + ) + ); + } else { + resolve( + new VectorGetItemMetadataBatch.Error(cacheServiceErrorMapper(err)) + ); + } + } + ); + }); + } + private validateRequestTimeout(timeout?: number) { this.logger.debug(`Request timeout ms: ${String(timeout)}`); if (timeout !== undefined && timeout <= 0) { diff --git a/packages/client-sdk-nodejs/src/internal/webhook-client.ts b/packages/client-sdk-nodejs/src/internal/webhook-client.ts index 5e38aca64..a0b38f825 100644 --- a/packages/client-sdk-nodejs/src/internal/webhook-client.ts +++ b/packages/client-sdk-nodejs/src/internal/webhook-client.ts @@ -11,6 +11,7 @@ import { ListWebhooks, PostUrlWebhookDestination, GetWebhookSecret, + RotateWebhookSecret, } from '@gomomento/sdk-core'; import {ChannelCredentials, Interceptor} from '@grpc/grpc-js'; import {IWebhookClient} from '@gomomento/sdk-core/dist/src/internal/clients/pubsub/IWebhookClient'; @@ -190,4 +191,46 @@ export class WebhookClient implements IWebhookClient { ); }); } + + async rotateWebhookSecret( + id: WebhookId + ): Promise { + try { + validateCacheName(id.cacheName); + validateWebhookName(id.webhookName); + } catch (err) { + return new RotateWebhookSecret.Error(normalizeSdkError(err as Error)); + } + + const webhookId = grpcWebhook._WebhookId.fromObject({ + webhook_name: id.webhookName, + cache_name: id.cacheName, + }); + const request = new grpcWebhook._RotateWebhookSecretRequest({ + webhook_id: webhookId, + }); + this.logger.debug('issuing "RotateWebhookSecret" request'); + + return await new Promise(resolve => { + this.webhookClient.RotateWebhookSecret( + request, + {interceptors: this.unaryInterceptors}, + (err, resp) => { + if (err || !resp) { + resolve( + new RotateWebhookSecret.Error(cacheServiceErrorMapper(err)) + ); + } else { + resolve( + new RotateWebhookSecret.Success({ + secret: resp.secret_string, + webhookName: id.webhookName, + cacheName: id.cacheName, + }) + ); + } + } + ); + }); + } } diff --git a/packages/client-sdk-web/package-lock.json b/packages/client-sdk-web/package-lock.json index 111eb1bae..089009d0b 100644 --- a/packages/client-sdk-web/package-lock.json +++ b/packages/client-sdk-web/package-lock.json @@ -9,7 +9,7 @@ "version": "0.0.1", "license": "Apache-2.0", "dependencies": { - "@gomomento/generated-types-webtext": "0.96.0", + "@gomomento/generated-types-webtext": "0.97.1", "@gomomento/sdk-core": "file:../core", "google-protobuf": "3.21.2", "grpc-web": "1.4.2", @@ -30,7 +30,7 @@ "eslint-plugin-node": "11.1.0", "eslint-plugin-prettier": "4.2.1", "jest": "29.7.0", - "jest-ci-spec-reporter": "^1.0.3", + "jest-ci-spec-reporter": "1.0.3", "jest-environment-jsdom": "^29.7.0", "jest-extended": "4.0.2", "prettier": "2.8.8", @@ -45,6 +45,7 @@ } }, "../common-integration-tests": { + "name": "@gomomento/common-integration-tests", "version": "0.0.1", "dev": true, "license": "Apache-2.0", @@ -76,6 +77,7 @@ } }, "../core": { + "name": "@gomomento/sdk-core", "version": "0.0.1", "license": "Apache-2.0", "dependencies": { @@ -136,30 +138,30 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.3.tgz", - "integrity": "sha512-BmR4bWbDIoFJmJ9z2cZ8Gmm2MXgEDgjdWgpKmKWUt54UGFJdlj31ECtbaDvCG/qVdG3AQ1SfpZEs01lUFbzLOQ==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", + "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.3.tgz", - "integrity": "sha512-Jg+msLuNuCJDyBvFv5+OKOUjWMZgd85bKjbICd3zWrKAo+bJ49HJufi7CQE0q0uR8NGyO6xkCACScNqyjHSZew==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.5.tgz", + "integrity": "sha512-Cwc2XjUrG4ilcfOw4wBAK+enbdgwAcAJCfGUItPBKR7Mjw4aEfAFYrLxeRp4jWgtNIKn3n2AlBOfwwafl+42/g==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.3", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.5", "@babel/helper-compilation-targets": "^7.22.15", "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.23.2", - "@babel/parser": "^7.23.3", + "@babel/helpers": "^7.23.5", + "@babel/parser": "^7.23.5", "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.3", - "@babel/types": "^7.23.3", + "@babel/traverse": "^7.23.5", + "@babel/types": "^7.23.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -175,12 +177,12 @@ } }, "node_modules/@babel/core/node_modules/@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", "dev": true, "dependencies": { - "@babel/highlight": "^7.22.13", + "@babel/highlight": "^7.23.4", "chalk": "^2.4.2" }, "engines": { @@ -268,12 +270,12 @@ } }, "node_modules/@babel/generator": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.3.tgz", - "integrity": "sha512-keeZWAV4LU3tW0qRi19HRpabC/ilM0HRBBzf9/k8FFiG4KVpiv0FIy4hHfLfFQZNhziCTPTmd59zoyv6DNISzg==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.5.tgz", + "integrity": "sha512-BPssCHrBD+0YrxviOa3QzpqwhNIXKEtOa2jQrm4FlmkC2apYgRnQcmPWiGZDlGxiNtltnUFolMe8497Esry+jA==", "dev": true, "dependencies": { - "@babel/types": "^7.23.3", + "@babel/types": "^7.23.5", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -406,9 +408,9 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", + "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", "dev": true, "engines": { "node": ">=6.9.0" @@ -424,32 +426,32 @@ } }, "node_modules/@babel/helper-validator-option": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", - "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.2.tgz", - "integrity": "sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.5.tgz", + "integrity": "sha512-oO7us8FzTEsG3U6ag9MfdF1iA/7Z6dz+MtFhifZk8C8o453rGJFFWUP1t+ULM9TUIAzC9uxXEiXjOiVMyd7QPg==", "dev": true, "dependencies": { "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.2", - "@babel/types": "^7.23.0" + "@babel/traverse": "^7.23.5", + "@babel/types": "^7.23.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", - "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", "dev": true, "dependencies": { "@babel/helper-validator-identifier": "^7.22.20", @@ -532,9 +534,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.3.tgz", - "integrity": "sha512-uVsWNvlVsIninV2prNz/3lHCb+5CJ+e+IUBfbjToAHODtfGYLfCFuY4AU7TskI+dAKk+njsPiBjq1gKTvZOBaw==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.5.tgz", + "integrity": "sha512-hOOqoiNXrmGdFbhgCzu6GiURxUgM27Xwd/aPuu8RfHEZPBzL1Z54okAHAQjXfcQNwvrlkAmAp4SlRTZ45vlthQ==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -735,12 +737,12 @@ } }, "node_modules/@babel/template/node_modules/@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", "dev": true, "dependencies": { - "@babel/highlight": "^7.22.13", + "@babel/highlight": "^7.23.4", "chalk": "^2.4.2" }, "engines": { @@ -819,19 +821,19 @@ } }, "node_modules/@babel/traverse": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.3.tgz", - "integrity": "sha512-+K0yF1/9yR0oHdE0StHuEj3uTPzwwbrLGfNOndVJVV2TqA5+j3oljJUb4nmB954FLGjNem976+B+eDuLIjesiQ==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.5.tgz", + "integrity": "sha512-czx7Xy5a6sapWWRx61m1Ke1Ra4vczu1mCTtJam5zRTBOonfdJ+S/B6HYmGYu3fJtr8GGET3si6IhgWVBhJ/m8w==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.3", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.5", "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.3", - "@babel/types": "^7.23.3", + "@babel/parser": "^7.23.5", + "@babel/types": "^7.23.5", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -840,12 +842,12 @@ } }, "node_modules/@babel/traverse/node_modules/@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", "dev": true, "dependencies": { - "@babel/highlight": "^7.22.13", + "@babel/highlight": "^7.23.4", "chalk": "^2.4.2" }, "engines": { @@ -933,12 +935,12 @@ } }, "node_modules/@babel/types": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.3.tgz", - "integrity": "sha512-OZnvoH2l8PK5eUvEcUyCt/sXgr/h+UWpVuBbOljwcrAgUl6lpchoQ++PHGyQy1AtYnVA6CEq3y5xeEI10brpXw==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.5.tgz", + "integrity": "sha512-ON5kSOJwVO6xXVRTvOI0eOnWe7VdUcIpsovGo9U/Br4Ie4UVFQTboO2cYnDhAGU6Fp+UxSiT+pMft0SMHfuq6w==", "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-string-parser": "^7.23.4", "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" }, @@ -1032,9 +1034,9 @@ "link": true }, "node_modules/@gomomento/generated-types-webtext": { - "version": "0.96.0", - "resolved": "https://registry.npmjs.org/@gomomento/generated-types-webtext/-/generated-types-webtext-0.96.0.tgz", - "integrity": "sha512-P5j1i3ZFWido7XSX7RtXo486om6StBYkjjqDTYi3c8r/hzZikLC69mjQey3SY5RCbvWTeMdVl1rK6bI8qhh17Q==", + "version": "0.97.1", + "resolved": "https://registry.npmjs.org/@gomomento/generated-types-webtext/-/generated-types-webtext-0.97.1.tgz", + "integrity": "sha512-7Rjz2gPwyRo3L/bnU5eo0a0g7LjijF3pDDkN4yParUOO+DMbuRe4LTBtuvMVU3p1rmp6Y2LXr/9o7av8MW9wWg==", "dependencies": { "google-protobuf": "3.21.2", "grpc-web": "1.4.2" @@ -1563,9 +1565,9 @@ "dev": true }, "node_modules/@types/babel__core": { - "version": "7.20.4", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.4.tgz", - "integrity": "sha512-mLnSC22IC4vcWiuObSRjrLd9XcBTGf59vUSoq2jkQDJ/QQ8PMI9rSuzE+aEV8karUMbskw07bKYoUJCKTUaygg==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", "dev": true, "dependencies": { "@babel/parser": "^7.20.7", @@ -1682,9 +1684,9 @@ "dev": true }, "node_modules/@types/semver": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.5.tgz", - "integrity": "sha512-+d+WYC1BxJ6yVOgUgzK8gWvp5qF8ssV5r4nsDcZWKRWcDQLQ619tvWAxJQYGgBrO1MnLJC7a5GtiYsAoQ47dJg==", + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", + "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", "dev": true }, "node_modules/@types/stack-utils": { @@ -1706,9 +1708,9 @@ "dev": true }, "node_modules/@types/yargs": { - "version": "17.0.31", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.31.tgz", - "integrity": "sha512-bocYSx4DI8TmdlvxqGpVNXOgCNR1Jj0gNPhhAY+iz1rgKDAaYrAYdFYnhDV1IFuiuVc9HkOwyDcFxaTElF3/wg==", + "version": "17.0.32", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", + "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", "dev": true, "dependencies": { "@types/yargs-parser": "*" @@ -1912,6 +1914,7 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "deprecated": "Use your platform's native atob() and btoa() methods instead", "dev": true }, "node_modules/acorn": { @@ -1958,9 +1961,9 @@ } }, "node_modules/acorn-walk": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.0.tgz", - "integrity": "sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA==", + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.1.tgz", + "integrity": "sha512-TgUZgYvqZprrl7YldZNoa9OciCAyZR+Ejm9eXzKCmjsF5IKp/wgQ7Z/ZpjpGTIUPwrHQIcYeI8qDh4PsEwxMbw==", "dev": true, "engines": { "node": ">=0.4.0" @@ -2371,9 +2374,9 @@ } }, "node_modules/browserslist": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", - "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", + "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", "dev": true, "funding": [ { @@ -2390,9 +2393,9 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001541", - "electron-to-chromium": "^1.4.535", - "node-releases": "^2.0.13", + "caniuse-lite": "^1.0.30001565", + "electron-to-chromium": "^1.4.601", + "node-releases": "^2.0.14", "update-browserslist-db": "^1.0.13" }, "bin": { @@ -2462,9 +2465,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001563", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001563.tgz", - "integrity": "sha512-na2WUmOxnwIZtwnFI2CZ/3er0wdNzU7hN+cPYz/z2ajHThnkWjNBOpEPP4n+4r2WPM847JaMotaJE3bnfzjyKw==", + "version": "1.0.30001566", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001566.tgz", + "integrity": "sha512-ggIhCsTxmITBAMmK8yZjEhCO5/47jKXPu6Dha/wuCS4JePVL+3uiDEBuhu2aIoT+bqTOR8L76Ip1ARL9xYsEJA==", "dev": true, "funding": [ { @@ -2831,6 +2834,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", + "deprecated": "Use your platform's native DOMException instead", "dev": true, "dependencies": { "webidl-conversions": "^7.0.0" @@ -2840,9 +2844,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.588", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.588.tgz", - "integrity": "sha512-soytjxwbgcCu7nh5Pf4S2/4wa6UIu+A3p03U2yVr53qGxi1/VTR3ENI+p50v+UxqqZAfl48j3z55ud7VHIOr9w==", + "version": "1.4.605", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.605.tgz", + "integrity": "sha512-V52j+P5z6cdRqTjPR/bYNxx7ETCHIkm5VIGuyCy3CMrfSnbEpIlLnk5oHmZo7gYvDfh2TfHeanB6rawyQ23ktg==", "dev": true }, "node_modules/emittery": { @@ -5071,12 +5075,12 @@ } }, "node_modules/jest-message-util/node_modules/@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", "dev": true, "dependencies": { - "@babel/highlight": "^7.22.13", + "@babel/highlight": "^7.23.4", "chalk": "^2.4.2" }, "engines": { @@ -5877,9 +5881,9 @@ "dev": true }, "node_modules/node-releases": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", - "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", "dev": true }, "node_modules/normalize-path": { @@ -5928,13 +5932,13 @@ } }, "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", "has-symbols": "^1.0.3", "object-keys": "^1.1.1" }, @@ -7359,9 +7363,9 @@ "dev": true }, "node_modules/v8-to-istanbul": { - "version": "9.1.3", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.3.tgz", - "integrity": "sha512-9lDD+EVI2fjFsMWXc6dy5JJzBsVTcQ2fVkfBvncZ6xJWG9wtBhOldG+mHkSL0+V1K/xgZz0JDO5UT5hFwHUghg==", + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz", + "integrity": "sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==", "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.12", diff --git a/packages/client-sdk-web/package.json b/packages/client-sdk-web/package.json index 262a7b723..f4f02f536 100644 --- a/packages/client-sdk-web/package.json +++ b/packages/client-sdk-web/package.json @@ -56,7 +56,7 @@ "xhr2": "0.2.1" }, "dependencies": { - "@gomomento/generated-types-webtext": "0.96.0", + "@gomomento/generated-types-webtext": "0.97.1", "@gomomento/sdk-core": "file:../core", "google-protobuf": "3.21.2", "grpc-web": "1.4.2", diff --git a/packages/client-sdk-web/src/internal/vector-index-data-client.ts b/packages/client-sdk-web/src/internal/vector-index-data-client.ts index defd0ec61..9635b6203 100644 --- a/packages/client-sdk-web/src/internal/vector-index-data-client.ts +++ b/packages/client-sdk-web/src/internal/vector-index-data-client.ts @@ -1,14 +1,18 @@ import {VectorIndexClient} from '@gomomento/generated-types-webtext/dist/VectorindexServiceClientPb'; import * as vectorindex from '@gomomento/generated-types-webtext/dist/vectorindex_pb'; import {IVectorIndexDataClient} from '@gomomento/sdk-core/dist/src/internal/clients/vector/IVectorIndexDataClient'; -import {VectorIndexItem} from '@gomomento/sdk-core/dist/src/messages/vector-index'; import { MomentoLogger, SearchOptions, VectorDeleteItemBatch, VectorSearch, VectorSearchAndFetchVectors, + VectorIndexMetadata, + VectorIndexItem, VectorUpsertItemBatch, + VectorIndexStoredItem, + VectorGetItemBatch, + VectorGetItemMetadataBatch, InvalidArgumentError, UnknownError, } from '@gomomento/sdk-core'; @@ -238,7 +242,7 @@ export class VectorIndexDataClient implements IVectorIndexDataClient { private static deserializeMetadata( metadata: vectorindex._Metadata[], errorCallback: () => void - ): Record> { + ): VectorIndexMetadata { return metadata.reduce((acc, metadata) => { const field = metadata.getField(); switch (metadata.getValueCase()) { @@ -262,7 +266,7 @@ export class VectorIndexDataClient implements IVectorIndexDataClient { break; } return acc; - }, {} as Record>); + }, {} as VectorIndexMetadata); } private async sendSearch( @@ -400,6 +404,171 @@ export class VectorIndexDataClient implements IVectorIndexDataClient { }); } + public async getItemBatch( + indexName: string, + ids: string[] + ): Promise { + try { + validateIndexName(indexName); + } catch (err) { + return new VectorGetItemBatch.Error(normalizeSdkError(err as Error)); + } + return await this.sendGetItemBatch(indexName, ids); + } + + private async sendGetItemBatch( + indexName: string, + ids: string[] + ): Promise { + const request = new vectorindex._GetItemBatchRequest(); + request.setIndexName(indexName); + request.setIdsList(ids); + request.setMetadataFields( + VectorIndexDataClient.prepareMetadataRequest({ + metadataFields: ALL_VECTOR_METADATA, + }) + ); + + return await new Promise(resolve => { + this.client.getItemBatch( + request, + { + ...this.clientMetadataProvider.createClientMetadata(), + ...this.createVectorCallMetadata(this.deadlineMillis), + }, + (err, resp) => { + if (resp) { + resolve( + new VectorGetItemBatch.Success( + resp.getItemResponseList().reduce((acc, itemResponse) => { + let hit: vectorindex._ItemResponse._Hit | undefined; + switch (itemResponse.getResponseCase()) { + case vectorindex._ItemResponse.ResponseCase.HIT: + hit = itemResponse.getHit(); + acc[hit?.getId() ?? ''] = { + id: hit?.getId() ?? '', + vector: hit?.getVector()?.getElementsList() ?? [], + metadata: VectorIndexDataClient.deserializeMetadata( + hit?.getMetadataList() ?? [], + () => + resolve( + new VectorGetItemBatch.Error( + new UnknownError( + 'GetItemBatch responded with an unknown result' + ) + ) + ) + ), + }; + break; + case vectorindex._ItemResponse.ResponseCase.MISS: + break; + default: + resolve( + new VectorGetItemBatch.Error( + new UnknownError( + 'GetItemBatch responded with an unknown result' + ) + ) + ); + break; + } + return acc; + }, {} as Record) + ) + ); + } else { + resolve(new VectorGetItemBatch.Error(cacheServiceErrorMapper(err))); + } + } + ); + }); + } + + public async getItemMetadataBatch( + indexName: string, + ids: string[] + ): Promise { + try { + validateIndexName(indexName); + } catch (err) { + return new VectorGetItemMetadataBatch.Error( + normalizeSdkError(err as Error) + ); + } + return await this.sendGetItemMetadataBatch(indexName, ids); + } + + private async sendGetItemMetadataBatch( + indexName: string, + ids: string[] + ): Promise { + const request = new vectorindex._GetItemMetadataBatchRequest(); + request.setIndexName(indexName); + request.setIdsList(ids); + request.setMetadataFields( + VectorIndexDataClient.prepareMetadataRequest({ + metadataFields: ALL_VECTOR_METADATA, + }) + ); + + return await new Promise(resolve => { + this.client.getItemMetadataBatch( + request, + { + ...this.clientMetadataProvider.createClientMetadata(), + ...this.createVectorCallMetadata(this.deadlineMillis), + }, + (err, resp) => { + if (resp) { + resolve( + new VectorGetItemMetadataBatch.Success( + resp + .getItemMetadataResponseList() + .reduce((acc, itemResponse) => { + let hit: vectorindex._ItemMetadataResponse._Hit | undefined; + switch (itemResponse.getResponseCase()) { + case vectorindex._ItemMetadataResponse.ResponseCase.HIT: + hit = itemResponse.getHit(); + acc[hit?.getId() ?? ''] = + VectorIndexDataClient.deserializeMetadata( + hit?.getMetadataList() ?? [], + () => + resolve( + new VectorGetItemMetadataBatch.Error( + new UnknownError( + 'GetItemMetadataBatch responded with an unknown result' + ) + ) + ) + ); + break; + case vectorindex._ItemResponse.ResponseCase.MISS: + break; + default: + resolve( + new VectorGetItemMetadataBatch.Error( + new UnknownError( + 'GetItemMetadataBatch responded with an unknown result' + ) + ) + ); + break; + } + return acc; + }, {} as Record) + ) + ); + } else { + resolve( + new VectorGetItemMetadataBatch.Error(cacheServiceErrorMapper(err)) + ); + } + } + ); + }); + } + private createVectorCallMetadata(timeoutMillis: number): {deadline: string} { const deadline = Date.now() + timeoutMillis; return {deadline: deadline.toString()}; diff --git a/packages/client-sdk-web/src/internal/webhook-client.ts b/packages/client-sdk-web/src/internal/webhook-client.ts index 7d39205be..0c2e389f6 100644 --- a/packages/client-sdk-web/src/internal/webhook-client.ts +++ b/packages/client-sdk-web/src/internal/webhook-client.ts @@ -11,6 +11,7 @@ import { PostUrlWebhookDestination, WebhookDestinationType, GetWebhookSecret, + RotateWebhookSecret, } from '@gomomento/sdk-core'; import {IWebhookClient} from '@gomomento/sdk-core/dist/src/internal/clients/pubsub/IWebhookClient'; import {cacheServiceErrorMapper} from '../errors/cache-service-error-mapper'; @@ -31,6 +32,7 @@ import { _Webhook, _WebhookDestination, _WebhookId, + _RotateWebhookSecretRequest, } from '@gomomento/generated-types-webtext/dist/webhook_pb'; export class WebhookClient implements IWebhookClient { @@ -207,4 +209,44 @@ export class WebhookClient implements IWebhookClient { ); }); } + + async rotateWebhookSecret( + id: WebhookId + ): Promise { + try { + validateCacheName(id.cacheName); + validateWebhookName(id.webhookName); + } catch (err) { + return new RotateWebhookSecret.Error(normalizeSdkError(err as Error)); + } + + const request = new _RotateWebhookSecretRequest(); + const webhookId = new _WebhookId(); + webhookId.setWebhookName(id.webhookName); + webhookId.setCacheName(id.cacheName); + request.setWebhookId(webhookId); + this.logger.debug('issuing "RotateWebhookSecret" request'); + + return await new Promise(resolve => { + this.webhookClient.rotateWebhookSecret( + request, + this.clientMetadataProvider.createClientMetadata(), + (err, resp) => { + if (err || !resp) { + resolve( + new RotateWebhookSecret.Error(cacheServiceErrorMapper(err)) + ); + } else { + resolve( + new RotateWebhookSecret.Success({ + secret: resp.getSecretString(), + webhookName: id.webhookName, + cacheName: id.cacheName, + }) + ); + } + } + ); + }); + } } diff --git a/packages/common-integration-tests/package-lock.json b/packages/common-integration-tests/package-lock.json index e3ef83045..07eb34a90 100644 --- a/packages/common-integration-tests/package-lock.json +++ b/packages/common-integration-tests/package-lock.json @@ -36,6 +36,7 @@ } }, "../core": { + "name": "@gomomento/sdk-core", "version": "0.0.1", "license": "Apache-2.0", "dependencies": { diff --git a/packages/common-integration-tests/src/vector-data-plane.ts b/packages/common-integration-tests/src/vector-data-plane.ts index 8bd47104f..a89f69f56 100644 --- a/packages/common-integration-tests/src/vector-data-plane.ts +++ b/packages/common-integration-tests/src/vector-data-plane.ts @@ -8,6 +8,8 @@ import { SearchOptions, VectorSearchAndFetchVectors, VectorIndexItem, + VectorGetItemBatch, + VectorGetItemMetadataBatch, } from '@gomomento/sdk-core'; import { expectWithMessage, @@ -1012,4 +1014,154 @@ export function runVectorDataPlaneTest(vectorClient: IVectorIndexClient) { ); }); }); + + describe('getItemBatch and getItemMetadataBatch', () => { + /* + * In the following tests we test both search and searchAndFetchVectors with a common + * suite of tests. To do this we abstract away calling the search method, building the hits + * (which may or may not contain the vectors), and asserting the results. + * + * We have two helpers to do this: search and buildSearchHits. The search method calls the + * appropriate search method on the vector client. The buildSearchHits method takes the + * search hits and the search method name and returns the expected search hits. + */ + + async function get( + vectorClient: IVectorIndexClient, + getMethodName: string, + indexName: string, + ids: string[] + ): Promise< + VectorGetItemBatch.Response | VectorGetItemMetadataBatch.Response + > { + if (getMethodName === 'getItemBatch') { + return await vectorClient.getItemBatch(indexName, ids); + } else if (getMethodName === 'getItemMetadataBatch') { + return await vectorClient.getItemMetadataBatch(indexName, ids); + } else { + throw new Error(`unknown search method ${getMethodName}`); + } + } + + it.each([ + { + getMethodName: 'getItemBatch', + ids: [], + expectedResponse: VectorGetItemBatch.Success, + values: {}, + }, + { + getMethodName: 'getItemMetadataBatch', + ids: [], + expectedResponse: VectorGetItemMetadataBatch.Success, + values: {}, + }, + { + getMethodName: 'getItemBatch', + ids: ['test_item_1'], + expectedResponse: VectorGetItemBatch.Success, + values: { + test_item_1: { + id: 'test_item_1', + vector: [1.0, 2.0], + metadata: {key1: 'value1'}, + }, + }, + }, + { + getMethodName: 'getItemMetadataBatch', + ids: ['test_item_1'], + expectedResponse: VectorGetItemMetadataBatch.Success, + values: { + test_item_1: { + key1: 'value1', + }, + }, + }, + { + getMethodName: 'getItemBatch', + ids: ['missing_id'], + expectedResponse: VectorGetItemBatch.Success, + values: {}, + }, + { + getMethodName: 'getItemMetadataBatch', + ids: ['missing_id'], + expectedResponse: VectorGetItemMetadataBatch.Success, + values: {}, + }, + { + getMethodName: 'getItemBatch', + ids: ['test_item_1', 'missing_id_2', 'test_item_2'], + expectedResponse: VectorGetItemBatch.Success, + values: { + test_item_1: { + id: 'test_item_1', + vector: [1.0, 2.0], + metadata: {key1: 'value1'}, + }, + test_item_2: { + id: 'test_item_2', + vector: [3.0, 4.0], + metadata: {}, + }, + }, + }, + { + getMethodName: 'getItemMetadataBatch', + ids: ['test_item_1', 'missing_id_2', 'test_item_2'], + expectedResponse: VectorGetItemMetadataBatch.Success, + values: { + test_item_1: { + key1: 'value1', + }, + test_item_2: {}, + }, + }, + ])( + 'should get items and get item metadata', + async ({getMethodName, ids, expectedResponse, values}) => { + const indexName = testIndexName(); + await WithIndex( + vectorClient, + indexName, + 2, + VectorSimilarityMetric.INNER_PRODUCT, + async () => { + const upsertResponse = await vectorClient.upsertItemBatch( + indexName, + [ + { + id: 'test_item_1', + vector: [1.0, 2.0], + metadata: {key1: 'value1'}, + }, + {id: 'test_item_2', vector: [3.0, 4.0]}, + {id: 'test_item_3', vector: [5.0, 6.0]}, + ] + ); + expectWithMessage(() => { + expect(upsertResponse).toBeInstanceOf( + VectorUpsertItemBatch.Success + ); + }, `expected SUCCESS but got ${upsertResponse.toString()}}`); + + await sleep(2_000); + + const getResponse = await get( + vectorClient, + getMethodName, + indexName, + ids + ); + expectWithMessage(() => { + expect(getResponse).toBeInstanceOf(expectedResponse); + }, `expected SUCCESS but got ${getResponse.toString()}}`); + + expect(getResponse.values()).toEqual(values); + } + ); + } + ); + }); } diff --git a/packages/common-integration-tests/src/webhooks.ts b/packages/common-integration-tests/src/webhooks.ts index 08a4a2628..52169b9c4 100644 --- a/packages/common-integration-tests/src/webhooks.ts +++ b/packages/common-integration-tests/src/webhooks.ts @@ -3,6 +3,7 @@ import { ListWebhooks, GetWebhookSecret, TopicPublish, + RotateWebhookSecret, } from '@gomomento/sdk-core'; import { getWebhookRequestDetails, @@ -66,7 +67,7 @@ export function runWebhookTests( }); }); - describe('put list delete getWebhookSecret', () => { + describe('put list delete getWebhookSecret rotateWebhookSecret', () => { it('should create a new webhook, list it, and then delete it', async () => { const webhook = testWebhook(integrationTestCacheName); await WithWebhook(topicClient, webhook, async () => { @@ -132,5 +133,35 @@ export function runWebhookTests( expect(detes.invocationCount).toBe(1); }); }); + it('should rotate a webhook secret', async () => { + const webhook = testWebhook(integrationTestCacheName); + await WithWebhook(topicClient, webhook, async () => { + const getSecretResp = await topicClient.getWebhookSecret( + webhook.id.cacheName, + webhook.id.webhookName + ); + if (!(getSecretResp instanceof GetWebhookSecret.Success)) { + throw new Error( + `unknown error occured when making a 'getWebhookSecret' request: ${getSecretResp.toString()}` + ); + } + expect(getSecretResp.secret()).toBeTruthy(); + const rotateResp = await topicClient.rotateWebhookSecret( + webhook.id.cacheName, + webhook.id.webhookName + ); + if (!(rotateResp instanceof RotateWebhookSecret.Success)) { + throw new Error( + `unknown error occured when making a 'rotateWebhookSecret' request: ${rotateResp.toString()}` + ); + } + expect(rotateResp.secret()).toBeTruthy(); + expect(rotateResp.webhookName()).toEqual(getSecretResp.webhookName()); + expect(rotateResp.cacheName()).toEqual(getSecretResp.cacheName()); + + // make sure the secrets are in fact different + expect(rotateResp.secret() === getSecretResp.secret()).toBeFalsy(); + }); + }); }); } diff --git a/packages/core/src/clients/ITopicClient.ts b/packages/core/src/clients/ITopicClient.ts index 5e7427675..43deb773b 100644 --- a/packages/core/src/clients/ITopicClient.ts +++ b/packages/core/src/clients/ITopicClient.ts @@ -6,6 +6,7 @@ import { PutWebhook, DeleteWebhook, GetWebhookSecret, + RotateWebhookSecret, } from '../index'; import {PutWebhookCallOptions} from '../utils/webhook-call-options'; @@ -36,4 +37,8 @@ export interface ITopicClient { cacheName: string, webhookName: string ): Promise; + rotateWebhookSecret( + cacheName: string, + webhookName: string + ): Promise; } diff --git a/packages/core/src/clients/IVectorIndexClient.ts b/packages/core/src/clients/IVectorIndexClient.ts index 8f737a04e..6bf1ecd6a 100644 --- a/packages/core/src/clients/IVectorIndexClient.ts +++ b/packages/core/src/clients/IVectorIndexClient.ts @@ -4,6 +4,8 @@ import { VectorDeleteItemBatch, VectorSearch, VectorSearchAndFetchVectors, + VectorGetItemBatch, + VectorGetItemMetadataBatch, } from '../messages/responses/vector'; import {VectorIndexItem} from '../messages/vector-index'; @@ -57,4 +59,15 @@ export interface IVectorIndexClient extends IVectorIndexControlClient { indexName: string, ids: Array ): Promise; + + getItemBatch( + indexName: string, + ids: Array + ): Promise; + + getItemMetadataBatch( + indexName: string, + ids: Array, + metadataFields?: Array + ): Promise; } diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 9a7c6ee1b..9fdfcc346 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -68,7 +68,11 @@ import * as GenerateDisposableToken from './messages/responses/generate-disposab // VectorClient Response Types export * as vector from './messages/responses/vector'; export * from './messages/responses/vector'; -export {VectorIndexItem} from './messages/vector-index'; +export { + VectorIndexMetadata, + VectorIndexItem, + VectorIndexStoredItem, +} from './messages/vector-index'; // Leaderboard Response Types export * as leaderboard from './messages/responses/leaderboard'; diff --git a/packages/core/src/internal/clients/pubsub/AbstractTopicClient.ts b/packages/core/src/internal/clients/pubsub/AbstractTopicClient.ts index 6d2a593d4..4d4e8f231 100644 --- a/packages/core/src/internal/clients/pubsub/AbstractTopicClient.ts +++ b/packages/core/src/internal/clients/pubsub/AbstractTopicClient.ts @@ -9,6 +9,7 @@ import { DeleteWebhook, GetWebhookSecret, PostUrlWebhookDestination, + RotateWebhookSecret, } from '../../../index'; import {IPubsubClient} from './IPubsubClient'; import {IWebhookClient} from './IWebhookClient'; @@ -131,4 +132,23 @@ export abstract class AbstractTopicClient implements ITopicClient { ): Promise { return await this.webhookClient.getWebhookSecret({cacheName, webhookName}); } + + /** + * Rotates the signing secret for a webhook + * + * @param {string} cacheName - The name of the cache associated with the webhook + * @param {string} webhookName - The name of the webhook + * @returns {Promise} - + * {@link RotateWebhookSecret.Success} on success. + * {@link RotateWebhookSecret.Error} on failure. + */ + public async rotateWebhookSecret( + cacheName: string, + webhookName: string + ): Promise { + return await this.webhookClient.rotateWebhookSecret({ + cacheName, + webhookName, + }); + } } diff --git a/packages/core/src/internal/clients/pubsub/IWebhookClient.ts b/packages/core/src/internal/clients/pubsub/IWebhookClient.ts index 030b4be79..12ca8dc5f 100644 --- a/packages/core/src/internal/clients/pubsub/IWebhookClient.ts +++ b/packages/core/src/internal/clients/pubsub/IWebhookClient.ts @@ -5,6 +5,7 @@ import { Webhook, WebhookId, GetWebhookSecret, + RotateWebhookSecret, } from '../../../index'; export interface IWebhookClient { @@ -12,4 +13,5 @@ export interface IWebhookClient { putWebhook(webhook: Webhook): Promise; deleteWebhook(id: WebhookId): Promise; getWebhookSecret(id: WebhookId): Promise; + rotateWebhookSecret(id: WebhookId): Promise; } diff --git a/packages/core/src/internal/clients/vector/AbstractVectorIndexClient.ts b/packages/core/src/internal/clients/vector/AbstractVectorIndexClient.ts index 03976829f..5752b7cb1 100644 --- a/packages/core/src/internal/clients/vector/AbstractVectorIndexClient.ts +++ b/packages/core/src/internal/clients/vector/AbstractVectorIndexClient.ts @@ -6,6 +6,8 @@ import { VectorSearch, VectorSearchAndFetchVectors, VectorDeleteItemBatch, + VectorGetItemBatch, + VectorGetItemMetadataBatch, } from '../../..'; import { IVectorIndexClient, @@ -170,6 +172,8 @@ export abstract class AbstractVectorIndexClient * @param {string} indexName - Name of the index to delete the items from. * @param {Array} ids - The IDs of the items to be deleted from the index. * @returns {Promise} + * {@link VectorDeleteItemBatch.Success} on success. + * {@link VectorDeleteItemBatch.Error} on error. */ public async deleteItemBatch( indexName: string, @@ -177,4 +181,36 @@ export abstract class AbstractVectorIndexClient ): Promise { return await this.dataClient.deleteItemBatch(indexName, ids); } + + /** + * Gets a batch of items from a vector index by ID. + * + * @param indexName - Name of the index to get the items from. + * @param ids - The IDs of the items to be retrieved from the index. + * @returns {Promise} + * {@link VectorGetItemBatch.Success} on success, with the found items. + * {@link VectorGetItemBatch.Error} on error. + */ + public async getItemBatch( + indexName: string, + ids: string[] + ): Promise { + return await this.dataClient.getItemBatch(indexName, ids); + } + + /** + * Gets metadata for a batch of items from a vector index by ID. + * + * @param indexName - Name of the index to get the items from. + * @param ids - The IDs of the items to be retrieved from the index. + * @returns {Promise} + * {@link VectorGetItemMetadataBatch.Success} on success, with the found item metadata. + * {@link VectorGetItemMetadataBatch.Error} on error. + */ + public async getItemMetadataBatch( + indexName: string, + ids: string[] + ): Promise { + return await this.dataClient.getItemMetadataBatch(indexName, ids); + } } diff --git a/packages/core/src/internal/clients/vector/IVectorIndexDataClient.ts b/packages/core/src/internal/clients/vector/IVectorIndexDataClient.ts index af5ddbca0..e1dbaec2d 100644 --- a/packages/core/src/internal/clients/vector/IVectorIndexDataClient.ts +++ b/packages/core/src/internal/clients/vector/IVectorIndexDataClient.ts @@ -3,6 +3,8 @@ import { VectorDeleteItemBatch, VectorSearch, VectorSearchAndFetchVectors, + VectorGetItemBatch, + VectorGetItemMetadataBatch, } from '../../../messages/responses/vector'; import {VectorIndexItem} from '../../../messages/vector-index'; import {SearchOptions} from '../../../clients/IVectorIndexClient'; @@ -26,4 +28,12 @@ export interface IVectorIndexDataClient { indexName: string, ids: Array ): Promise; + getItemBatch( + indexName: string, + ids: Array + ): Promise; + getItemMetadataBatch( + indexName: string, + ids: Array + ): Promise; } diff --git a/packages/core/src/messages/responses/vector/index.ts b/packages/core/src/messages/responses/vector/index.ts index 286b4b489..fdf9c1c80 100644 --- a/packages/core/src/messages/responses/vector/index.ts +++ b/packages/core/src/messages/responses/vector/index.ts @@ -5,3 +5,5 @@ export * as VectorUpsertItemBatch from './vector-upsert-item-batch'; export * as VectorSearch from './vector-search'; export * as VectorSearchAndFetchVectors from './vector-search-and-fetch-vectors'; export * as VectorDeleteItemBatch from './vector-delete-item-batch'; +export * as VectorGetItemBatch from './vector-get-item-batch'; +export * as VectorGetItemMetadataBatch from './vector-get-item-metadata-batch'; diff --git a/packages/core/src/messages/responses/vector/vector-get-item-batch.ts b/packages/core/src/messages/responses/vector/vector-get-item-batch.ts new file mode 100644 index 000000000..2ce96883f --- /dev/null +++ b/packages/core/src/messages/responses/vector/vector-get-item-batch.ts @@ -0,0 +1,72 @@ +import {SdkError} from '../../../errors'; +import {VectorIndexStoredItem} from '../../vector-index'; +import {ResponseBase, ResponseError, ResponseSuccess} from '../response-base'; + +/** + * Parent response type for a VectorGetItemBatch request. The + * response object is resolved to a type-safe object of one of + * the following subtypes: + * + * - {Success} + * - {Error} + * + * `instanceof` type guards can be used to operate on the appropriate subtype. + * @example + * For example: + * ``` + * if (response instanceof VectorGetItemBatch.Error) { + * // Handle error as appropriate. The compiler will smart-cast `response` to type + * // `VectorGetItemBatch.Error` in this block, so you will have access to the properties + * // of the Error class; e.g. `response.errorCode()`. + * } + * ``` + */ +export abstract class Response extends ResponseBase { + values(): Record | undefined { + if (this instanceof Success) { + return this.values(); + } + return undefined; + } +} + +class _Success extends Response {} + +/** + * Indicates a Successful VectorGetItemBatch request. + */ +export class Success extends ResponseSuccess(_Success) { + private readonly _values: Record; + constructor(values: Record) { + super(); + this._values = values; + } + /** + * Returns the found items from the VectorGetItemBatch request. + * + * Items that were not found will not be included in the + * returned object. + * @returns {Record} The items that were found in the index. + */ + values(): Record { + return this._values; + } +} + +class _Error extends Response { + constructor(protected _innerException: SdkError) { + super(); + } +} + +/** + * Indicates that an error occurred during the VectorGetItemBatch request. + * + * This response object includes the following fields that you can use to determine + * how you would like to handle the error: + * + * - `errorCode()` - a unique Momento error code indicating the type of error that occurred. + * - `message()` - a human-readable description of the error + * - `innerException()` - the original error that caused the failure; can be re-thrown. + */ +export class Error extends ResponseError(_Error) {} diff --git a/packages/core/src/messages/responses/vector/vector-get-item-metadata-batch.ts b/packages/core/src/messages/responses/vector/vector-get-item-metadata-batch.ts new file mode 100644 index 000000000..ae5ab37bd --- /dev/null +++ b/packages/core/src/messages/responses/vector/vector-get-item-metadata-batch.ts @@ -0,0 +1,72 @@ +import {SdkError} from '../../../errors'; +import {VectorIndexMetadata} from '../../..'; +import {ResponseBase, ResponseError, ResponseSuccess} from '../response-base'; + +/** + * Parent response type for a VectorGetItemMetadataBatch request. The + * response object is resolved to a type-safe object of one of + * the following subtypes: + * + * - {Success} + * - {Error} + * + * `instanceof` type guards can be used to operate on the appropriate subtype. + * @example + * For example: + * ``` + * if (response instanceof VectorGetItemMetadataBatch.Error) { + * // Handle error as appropriate. The compiler will smart-cast `response` to type + * // `VectorGetItemMetadataBatch.Error` in this block, so you will have access to the properties + * // of the Error class; e.g. `response.errorCode()`. + * } + * ``` + */ +export abstract class Response extends ResponseBase { + values(): Record | undefined { + if (this instanceof Success) { + return this.values(); + } + return undefined; + } +} + +class _Success extends Response {} + +/** + * Indicates a Successful VectorGetItemMetadataBatch request. + */ +export class Success extends ResponseSuccess(_Success) { + private readonly _values: Record; + constructor(values: Record) { + super(); + this._values = values; + } + /** + * Returns the metadat for the found items from the VectorGetItemMetadataBatch request. + * + * Items that were not found will not be included in the + * returned object. + * @returns {Record} The metadata for items found in the index. + */ + values(): Record { + return this._values; + } +} + +class _Error extends Response { + constructor(protected _innerException: SdkError) { + super(); + } +} + +/** + * Indicates that an error occurred during the VectorGetItemMetadataBatch request. + * + * This response object includes the following fields that you can use to determine + * how you would like to handle the error: + * + * - `errorCode()` - a unique Momento error code indicating the type of error that occurred. + * - `message()` - a human-readable description of the error + * - `innerException()` - the original error that caused the failure; can be re-thrown. + */ +export class Error extends ResponseError(_Error) {} diff --git a/packages/core/src/messages/responses/webhook/index.ts b/packages/core/src/messages/responses/webhook/index.ts index c00e2963a..9c1bdf68c 100644 --- a/packages/core/src/messages/responses/webhook/index.ts +++ b/packages/core/src/messages/responses/webhook/index.ts @@ -2,3 +2,4 @@ export * as DeleteWebhook from './delete-webhook'; export * as ListWebhooks from './list-webhooks'; export * as PutWebhook from './put-webhook'; export * as GetWebhookSecret from './get-webhook-secret'; +export * as RotateWebhookSecret from './rotate-webhook-secret'; diff --git a/packages/core/src/messages/responses/webhook/rotate-webhook-secret.ts b/packages/core/src/messages/responses/webhook/rotate-webhook-secret.ts new file mode 100644 index 000000000..65ceee64b --- /dev/null +++ b/packages/core/src/messages/responses/webhook/rotate-webhook-secret.ts @@ -0,0 +1,76 @@ +import {SdkError} from '../../../errors'; +import {ResponseBase, ResponseError, ResponseSuccess} from '../response-base'; + +/** + * Parent response type for a RotateWebhookSecret request. The + * response object is resolved to a type-safe object of one of + * the following subtypes: + * + * - {Success} + * - {Error} + * + * `instanceof` type guards can be used to operate on the appropriate subtype. + * @example + * For example: + * ``` + * if (response instanceof RotateWebhookSecret.Error) { + * // Handle error as appropriate. The compiler will smart-cast `response` to type + * // `RotateWebhookSecret.Error` in this block, so you will have access to the properties + * // of the Error class; e.g. `response.errorCode()`. + * } + * ``` + */ +export abstract class Response extends ResponseBase {} + +type Props = { + secret: string; + cacheName: string; + webhookName: string; +}; + +class _Success extends Response { + private readonly _secret: string; + private readonly _webhookName: string; + private readonly _cacheName: string; + constructor(props: Props) { + super(); + this._secret = props.secret; + this._cacheName = props.cacheName; + this._webhookName = props.webhookName; + } + + secret(): string { + return this._secret; + } + + webhookName(): string { + return this._webhookName; + } + + cacheName(): string { + return this._cacheName; + } +} + +/** + * Indicates a Successful RotateWebhookSecret request. + */ +export class Success extends ResponseSuccess(_Success) {} + +class _Error extends Response { + constructor(protected _innerException: SdkError) { + super(); + } +} + +/** + * Indicates that an error occurred during the RotateWebhookSecret request. + * + * This response object includes the following fields that you can use to determine + * how you would like to handle the error: + * + * - `errorCode()` - a unique Momento error code indicating the type of error that occurred. + * - `message()` - a human-readable description of the error + * - `innerException()` - the original error that caused the failure; can be re-thrown. + */ +export class Error extends ResponseError(_Error) {} diff --git a/packages/core/src/messages/vector-index.ts b/packages/core/src/messages/vector-index.ts index 71b255c17..818bd04ac 100644 --- a/packages/core/src/messages/vector-index.ts +++ b/packages/core/src/messages/vector-index.ts @@ -1,5 +1,47 @@ +/** + * The metadata of an item stored in the vector index. + */ +export type VectorIndexMetadata = Record< + string, + string | number | boolean | Array +>; + +/** + * An item to upsert into the vector index. + */ export interface VectorIndexItem { + /** + * The ID of the item. + */ id: string; + /** + * The vector of the item. + */ vector: Array; - metadata?: Record>; + /** + * The metadata of the item, if any. + */ + metadata?: VectorIndexMetadata; +} + +/** + * An item stored in the vector index. + * + * @remarks Specifying metadata is optional when upserting with + * `VectorIndexItem` but it is always returned when fetching items. + * Ie we know with certainty that `metadata` is not undefined. + */ +export interface VectorIndexStoredItem { + /** + * The ID of the item. + */ + id: string; + /** + * The vector of the item. + */ + vector: Array; + /** + * The metadata of the item. + */ + metadata: VectorIndexMetadata; }