@upstash/redis 0.0.0-ci.babdc47f97e036e2863dfed16300cda2b97bf6ad-20240322001434 → 0.0.0-ci.bb93ac2803c2e927dc8bf1a1b3c5aa2a14034eb6-20240930061920
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +2 -0
- package/.github/workflows/release.yml +53 -0
- package/.github/workflows/tests.yaml +609 -0
- package/.gitignore +175 -0
- package/.husky/commit-msg +1 -0
- package/.husky/pre-commit +2 -0
- package/.husky/pre-push +1 -0
- package/.prettierignore +1 -0
- package/.vscode/extensions.json +3 -0
- package/.vscode/settings.json +20 -0
- package/README.md +1 -2
- package/bun.lockb +0 -0
- package/commitlint.config.js +46 -0
- package/dist/LICENSE +21 -0
- package/dist/README.md +136 -0
- package/dist/chunk-TEVCO3ZO.mjs +3797 -0
- package/dist/cloudflare.d.mts +55 -0
- package/dist/cloudflare.d.ts +55 -0
- package/dist/cloudflare.js +3907 -0
- package/dist/cloudflare.mjs +91 -0
- package/dist/fastly.d.mts +48 -0
- package/dist/fastly.d.ts +48 -0
- package/dist/fastly.js +3880 -0
- package/dist/fastly.mjs +64 -0
- package/dist/nodejs.d.mts +73 -0
- package/dist/nodejs.d.ts +73 -0
- package/dist/nodejs.js +3926 -0
- package/dist/nodejs.mjs +110 -0
- package/dist/package.json +1 -0
- package/{zmscore-5d82e632.d.ts → dist/zmscore-BhX8yEQc.d.mts} +249 -184
- package/dist/zmscore-BhX8yEQc.d.ts +3486 -0
- package/eslint.config.mjs +102 -0
- package/examples/auto-pipeline/.eslintrc.json +3 -0
- package/examples/auto-pipeline/README.md +77 -0
- package/examples/auto-pipeline/app/components/DataComponent.tsx +49 -0
- package/examples/auto-pipeline/app/data/getEvents.ts +18 -0
- package/examples/auto-pipeline/app/data/getUsers.ts +18 -0
- package/examples/auto-pipeline/app/data/redis.ts +12 -0
- package/examples/auto-pipeline/app/favicon.ico +0 -0
- package/examples/auto-pipeline/app/globals.css +0 -0
- package/examples/auto-pipeline/app/layout.tsx +22 -0
- package/examples/auto-pipeline/app/page.tsx +15 -0
- package/examples/auto-pipeline/next.config.mjs +4 -0
- package/examples/auto-pipeline/package.json +27 -0
- package/examples/auto-pipeline/postcss.config.mjs +8 -0
- package/examples/auto-pipeline/public/next.svg +1 -0
- package/examples/auto-pipeline/public/vercel.svg +1 -0
- package/examples/auto-pipeline/tailwind.config.ts +20 -0
- package/examples/auto-pipeline/tsconfig.json +26 -0
- package/examples/aws-cdk-python/README.md +36 -0
- package/examples/aws-cdk-python/cdk.json +72 -0
- package/examples/aws-cdk-python/jest.config.js +8 -0
- package/examples/aws-cdk-python/lib/api/index.py +10 -0
- package/examples/aws-cdk-python/lib/api/requirements.txt +1 -0
- package/examples/aws-cdk-python/package-lock.json +4470 -0
- package/examples/aws-cdk-python/package.json +27 -0
- package/examples/aws-cdk-python/tsconfig.json +31 -0
- package/examples/aws-cdk-typescript/README.md +36 -0
- package/examples/aws-cdk-typescript/cdk.json +72 -0
- package/examples/aws-cdk-typescript/jest.config.js +8 -0
- package/examples/aws-cdk-typescript/package-lock.json +4548 -0
- package/examples/aws-cdk-typescript/package.json +28 -0
- package/examples/aws-cdk-typescript/tsconfig.json +31 -0
- package/examples/aws-lambda/README.md +39 -0
- package/examples/aws-lambda/index.js +11 -0
- package/examples/aws-lambda/package-lock.json +27 -0
- package/examples/aws-lambda/package.json +6 -0
- package/examples/aws-sam/README.md +34 -0
- package/examples/aws-sam/__init__.py +0 -0
- package/examples/aws-sam/events/event.json +62 -0
- package/examples/aws-sam/hello_world/__init__.py +0 -0
- package/examples/aws-sam/hello_world/app.py +10 -0
- package/examples/aws-sam/hello_world/requirements.txt +2 -0
- package/examples/aws-sam/samconfig.toml +34 -0
- package/examples/aws-sam/template.yaml +52 -0
- package/examples/aws-sam/tests/__init__.py +0 -0
- package/examples/aws-sam/tests/integration/__init__.py +0 -0
- package/examples/aws-sam/tests/integration/test_api_gateway.py +45 -0
- package/examples/aws-sam/tests/requirements.txt +3 -0
- package/examples/aws-sam/tests/unit/__init__.py +0 -0
- package/examples/aws-sam/tests/unit/test_handler.py +72 -0
- package/examples/azure-functions/.funcignore +10 -0
- package/examples/azure-functions/.vscode/extensions.json +5 -0
- package/examples/azure-functions/README.md +67 -0
- package/examples/azure-functions/host.json +15 -0
- package/examples/azure-functions/package-lock.json +1019 -0
- package/examples/azure-functions/package.json +24 -0
- package/examples/azure-functions/src/functions/CounterFunction.ts +19 -0
- package/examples/azure-functions/tsconfig.json +10 -0
- package/examples/cloudflare-workers/README.md +26 -0
- package/examples/cloudflare-workers/bun.lockb +0 -0
- package/examples/cloudflare-workers/ci.test.ts +18 -0
- package/examples/cloudflare-workers/index.js +11 -0
- package/examples/cloudflare-workers/package.json +17 -0
- package/examples/cloudflare-workers/wrangler.toml +11 -0
- package/examples/cloudflare-workers-with-typescript/README.md +26 -0
- package/examples/cloudflare-workers-with-typescript/ci.test.ts +17 -0
- package/examples/cloudflare-workers-with-typescript/package.json +17 -0
- package/examples/cloudflare-workers-with-typescript/src/index.ts +16 -0
- package/examples/cloudflare-workers-with-typescript/tsconfig.json +105 -0
- package/examples/cloudflare-workers-with-typescript/wrangler.toml +9 -0
- package/examples/deno/main.test.ts +16 -0
- package/examples/deno/main.ts +9 -0
- package/examples/fastapi/README.md +23 -0
- package/examples/fastapi/main.py +12 -0
- package/examples/fastapi/requirements.txt +2 -0
- package/examples/fastly/README.md +7 -0
- package/examples/fastly/fastly.toml +12 -0
- package/examples/fastly/package.json +23 -0
- package/examples/fastly/src/index.js +19 -0
- package/examples/fastly/webpack.config.js +28 -0
- package/examples/google-cloud-functions/README.md +37 -0
- package/examples/google-cloud-functions/index.js +12 -0
- package/examples/google-cloud-functions/package.json +7 -0
- package/examples/ion/.env.example +2 -0
- package/examples/ion/.eslintrc.json +3 -0
- package/examples/ion/README.md +49 -0
- package/examples/ion/app/favicon.ico +0 -0
- package/examples/ion/app/globals.css +33 -0
- package/examples/ion/app/layout.tsx +22 -0
- package/examples/ion/app/page.tsx +12 -0
- package/examples/ion/next.config.mjs +4 -0
- package/examples/ion/package-lock.json +6709 -0
- package/examples/ion/package.json +28 -0
- package/examples/ion/postcss.config.mjs +8 -0
- package/examples/ion/public/next.svg +1 -0
- package/examples/ion/public/vercel.svg +1 -0
- package/examples/ion/sst-env.d.ts +12 -0
- package/examples/ion/sst.config.ts +19 -0
- package/examples/ion/tailwind.config.ts +20 -0
- package/examples/ion/tsconfig.json +26 -0
- package/examples/nextjs-app-router/.env.example +2 -0
- package/examples/nextjs-app-router/.eslintrc.json +3 -0
- package/examples/nextjs-app-router/README.md +26 -0
- package/examples/nextjs-app-router/app/globals.css +3 -0
- package/examples/nextjs-app-router/app/layout.tsx +22 -0
- package/examples/nextjs-app-router/app/page.tsx +12 -0
- package/examples/nextjs-app-router/next.config.mjs +4 -0
- package/examples/nextjs-app-router/package.json +27 -0
- package/examples/nextjs-app-router/postcss.config.mjs +8 -0
- package/examples/nextjs-app-router/tailwind.config.ts +20 -0
- package/examples/nextjs-app-router/tsconfig.json +26 -0
- package/examples/nextjs-pages-router/.env.example +2 -0
- package/examples/nextjs-pages-router/.eslintrc.json +3 -0
- package/examples/nextjs-pages-router/README.md +26 -0
- package/examples/nextjs-pages-router/next.config.mjs +6 -0
- package/examples/nextjs-pages-router/package.json +27 -0
- package/examples/nextjs-pages-router/pages/_app.tsx +6 -0
- package/examples/nextjs-pages-router/pages/_document.tsx +13 -0
- package/examples/nextjs-pages-router/pages/api/hello.ts +13 -0
- package/examples/nextjs-pages-router/pages/index.tsx +19 -0
- package/examples/nextjs-pages-router/postcss.config.mjs +8 -0
- package/examples/nextjs-pages-router/styles/globals.css +3 -0
- package/examples/nextjs-pages-router/tailwind.config.ts +20 -0
- package/examples/nextjs-pages-router/tsconfig.json +21 -0
- package/examples/nodejs/.env.example +2 -0
- package/examples/nodejs/README.md +24 -0
- package/examples/nodejs/index.js +10 -0
- package/examples/nodejs/package.json +10 -0
- package/examples/serverless-framework/counter/.env.example +2 -0
- package/examples/serverless-framework/counter/README.md +38 -0
- package/examples/serverless-framework/counter/handler.js +12 -0
- package/examples/serverless-framework/counter/package-lock.json +27 -0
- package/examples/serverless-framework/counter/package.json +6 -0
- package/examples/serverless-framework/counter/serverless.yml +16 -0
- package/examples/sst-v2/.vscode/launch.json +15 -0
- package/examples/sst-v2/.vscode/settings.json +5 -0
- package/examples/sst-v2/README.md +62 -0
- package/examples/sst-v2/package.json +27 -0
- package/examples/sst-v2/packages/core/package.json +14 -0
- package/examples/sst-v2/packages/core/sst-env.d.ts +1 -0
- package/examples/sst-v2/packages/core/tsconfig.json +7 -0
- package/examples/sst-v2/packages/functions/package.json +15 -0
- package/examples/sst-v2/packages/functions/sst-env.d.ts +1 -0
- package/examples/sst-v2/packages/functions/tsconfig.json +11 -0
- package/examples/sst-v2/packages/web/README.md +40 -0
- package/examples/sst-v2/packages/web/next.config.mjs +6 -0
- package/examples/sst-v2/packages/web/package.json +23 -0
- package/examples/sst-v2/packages/web/pages/_app.tsx +6 -0
- package/examples/sst-v2/packages/web/pages/_document.tsx +13 -0
- package/examples/sst-v2/packages/web/pages/api/hello.ts +16 -0
- package/examples/sst-v2/packages/web/pages/index.tsx +114 -0
- package/examples/sst-v2/packages/web/public/favicon.ico +0 -0
- package/examples/sst-v2/packages/web/public/next.svg +1 -0
- package/examples/sst-v2/packages/web/public/vercel.svg +1 -0
- package/examples/sst-v2/packages/web/sst-env.d.ts +1 -0
- package/examples/sst-v2/packages/web/styles/Home.module.css +229 -0
- package/examples/sst-v2/packages/web/styles/globals.css +107 -0
- package/examples/sst-v2/packages/web/tsconfig.json +36 -0
- package/examples/sst-v2/pnpm-workspace.yaml +2 -0
- package/examples/sst-v2/sst.config.ts +14 -0
- package/examples/sst-v2/stacks/Default.ts +13 -0
- package/examples/sst-v2/tsconfig.json +8 -0
- package/examples/terraform/README.md +38 -0
- package/examples/terraform/counter/counter.js +11 -0
- package/examples/terraform/counter/package.json +6 -0
- package/examples/terraform/main.tf +166 -0
- package/examples/terraform/outputs.tf +17 -0
- package/examples/terraform/terraform.tf +18 -0
- package/examples/terraform/variables.tf +6 -0
- package/examples/vercel-functions-app-router/.env.example +2 -0
- package/examples/vercel-functions-app-router/.eslintrc.json +3 -0
- package/examples/vercel-functions-app-router/README.md +26 -0
- package/examples/vercel-functions-app-router/app/api/hello/route.ts +11 -0
- package/examples/vercel-functions-app-router/app/globals.css +3 -0
- package/examples/vercel-functions-app-router/app/layout.tsx +22 -0
- package/examples/vercel-functions-app-router/ci.test.ts +14 -0
- package/examples/vercel-functions-app-router/next.config.mjs +4 -0
- package/examples/vercel-functions-app-router/package.json +27 -0
- package/examples/vercel-functions-app-router/postcss.config.mjs +8 -0
- package/examples/vercel-functions-app-router/tailwind.config.ts +20 -0
- package/examples/vercel-functions-app-router/tsconfig.json +26 -0
- package/examples/vercel-functions-pages-router/.env.example +2 -0
- package/examples/vercel-functions-pages-router/.eslintrc.json +3 -0
- package/examples/vercel-functions-pages-router/README.md +26 -0
- package/examples/vercel-functions-pages-router/ci.test.ts +14 -0
- package/examples/vercel-functions-pages-router/next.config.mjs +6 -0
- package/examples/vercel-functions-pages-router/package.json +27 -0
- package/examples/vercel-functions-pages-router/pages/_app.tsx +6 -0
- package/examples/vercel-functions-pages-router/pages/_document.tsx +13 -0
- package/examples/vercel-functions-pages-router/pages/api/hello.ts +12 -0
- package/examples/vercel-functions-pages-router/postcss.config.mjs +8 -0
- package/examples/vercel-functions-pages-router/styles/globals.css +3 -0
- package/examples/vercel-functions-pages-router/tailwind.config.ts +20 -0
- package/examples/vercel-functions-pages-router/tsconfig.json +21 -0
- package/examples/vercel-python-runtime-django/.env.example +2 -0
- package/examples/vercel-python-runtime-django/README.md +34 -0
- package/examples/vercel-python-runtime-django/api/__init__.py +0 -0
- package/examples/vercel-python-runtime-django/api/asgi.py +16 -0
- package/examples/vercel-python-runtime-django/api/settings.py +121 -0
- package/examples/vercel-python-runtime-django/api/urls.py +22 -0
- package/examples/vercel-python-runtime-django/api/wsgi.py +16 -0
- package/examples/vercel-python-runtime-django/example/__init__.py +0 -0
- package/examples/vercel-python-runtime-django/example/admin.py +3 -0
- package/examples/vercel-python-runtime-django/example/apps.py +6 -0
- package/examples/vercel-python-runtime-django/example/urls.py +9 -0
- package/examples/vercel-python-runtime-django/example/views.py +18 -0
- package/examples/vercel-python-runtime-django/manage.py +22 -0
- package/examples/vercel-python-runtime-django/package.json +5 -0
- package/examples/vercel-python-runtime-django/requirements.txt +2 -0
- package/examples/vercel-python-runtime-django/vercel.json +8 -0
- package/examples/with-sentry/index.ts +36 -0
- package/examples/with-sentry/package.json +17 -0
- package/package.json +1 -1
- package/pkg/auto-pipeline.test.ts +321 -0
- package/pkg/auto-pipeline.ts +107 -0
- package/pkg/commands/append.test.ts +28 -0
- package/pkg/commands/append.ts +11 -0
- package/pkg/commands/bitcount.test.ts +37 -0
- package/pkg/commands/bitcount.ts +29 -0
- package/pkg/commands/bitfield.test.ts +51 -0
- package/pkg/commands/bitfield.ts +50 -0
- package/pkg/commands/bitop.test.ts +45 -0
- package/pkg/commands/bitop.ts +22 -0
- package/pkg/commands/bitpos.test.ts +47 -0
- package/pkg/commands/bitpos.ts +14 -0
- package/pkg/commands/command.test.ts +22 -0
- package/pkg/commands/command.ts +98 -0
- package/pkg/commands/copy.test.ts +65 -0
- package/pkg/commands/copy.ts +22 -0
- package/pkg/commands/dbsize.test.ts +18 -0
- package/pkg/commands/dbsize.ts +11 -0
- package/pkg/commands/decr.test.ts +23 -0
- package/pkg/commands/decr.ts +11 -0
- package/pkg/commands/decrby.test.ts +24 -0
- package/pkg/commands/decrby.ts +11 -0
- package/pkg/commands/del.test.ts +38 -0
- package/pkg/commands/del.ts +11 -0
- package/pkg/commands/echo.test.ts +11 -0
- package/pkg/commands/echo.ts +11 -0
- package/pkg/commands/eval.test.ts +30 -0
- package/pkg/commands/eval.ts +14 -0
- package/pkg/commands/evalsha.test.ts +19 -0
- package/pkg/commands/evalsha.ts +14 -0
- package/pkg/commands/exists.test.ts +38 -0
- package/pkg/commands/exists.ts +11 -0
- package/pkg/commands/expire.test.ts +119 -0
- package/pkg/commands/expire.ts +12 -0
- package/pkg/commands/expireat.test.ts +25 -0
- package/pkg/commands/expireat.ts +11 -0
- package/pkg/commands/flushall.test.ts +18 -0
- package/pkg/commands/flushall.ts +14 -0
- package/pkg/commands/flushdb.test.ts +17 -0
- package/pkg/commands/flushdb.ts +14 -0
- package/pkg/commands/geo_add.test.ts +202 -0
- package/pkg/commands/geo_add.ts +54 -0
- package/pkg/commands/geo_dist.test.ts +79 -0
- package/pkg/commands/geo_dist.ts +19 -0
- package/pkg/commands/geo_hash.test.ts +49 -0
- package/pkg/commands/geo_hash.ts +23 -0
- package/pkg/commands/geo_pos.test.ts +60 -0
- package/pkg/commands/geo_pos.ts +39 -0
- package/pkg/commands/geo_search.test.ts +197 -0
- package/pkg/commands/geo_search.ts +139 -0
- package/pkg/commands/geo_search_store.test.ts +153 -0
- package/pkg/commands/geo_search_store.ts +69 -0
- package/pkg/commands/get.test.ts +35 -0
- package/pkg/commands/get.ts +11 -0
- package/pkg/commands/getbit.test.ts +17 -0
- package/pkg/commands/getbit.ts +11 -0
- package/pkg/commands/getdel.test.ts +39 -0
- package/pkg/commands/getdel.ts +11 -0
- package/pkg/commands/getrange.test.ts +25 -0
- package/pkg/commands/getrange.ts +14 -0
- package/pkg/commands/getset.test.ts +33 -0
- package/pkg/commands/getset.ts +14 -0
- package/pkg/commands/hdel.test.ts +45 -0
- package/pkg/commands/hdel.ts +11 -0
- package/pkg/commands/hexists.test.ts +36 -0
- package/pkg/commands/hexists.ts +11 -0
- package/pkg/commands/hget.test.ts +52 -0
- package/pkg/commands/hget.ts +14 -0
- package/pkg/commands/hgetall.test.ts +45 -0
- package/pkg/commands/hgetall.ts +37 -0
- package/pkg/commands/hincrby.test.ts +28 -0
- package/pkg/commands/hincrby.ts +14 -0
- package/pkg/commands/hincrbyfloat.test.ts +28 -0
- package/pkg/commands/hincrbyfloat.ts +14 -0
- package/pkg/commands/hkeys.test.ts +23 -0
- package/pkg/commands/hkeys.ts +11 -0
- package/pkg/commands/hlen.test.ts +25 -0
- package/pkg/commands/hlen.ts +11 -0
- package/pkg/commands/hmget.test.ts +44 -0
- package/pkg/commands/hmget.ts +46 -0
- package/pkg/commands/hmset.test.ts +23 -0
- package/pkg/commands/hmset.ts +14 -0
- package/pkg/commands/hrandfield.test.ts +59 -0
- package/pkg/commands/hrandfield.ts +50 -0
- package/pkg/commands/hscan.test.ts +44 -0
- package/pkg/commands/hscan.ts +30 -0
- package/pkg/commands/hset.test.ts +21 -0
- package/pkg/commands/hset.ts +14 -0
- package/pkg/commands/hsetnx.test.ts +37 -0
- package/pkg/commands/hsetnx.ts +14 -0
- package/pkg/commands/hstrlen.test.ts +24 -0
- package/pkg/commands/hstrlen.ts +11 -0
- package/pkg/commands/hvals.test.ts +24 -0
- package/pkg/commands/hvals.ts +11 -0
- package/pkg/commands/incr.test.ts +24 -0
- package/pkg/commands/incr.ts +11 -0
- package/pkg/commands/incrby.test.ts +24 -0
- package/pkg/commands/incrby.ts +11 -0
- package/pkg/commands/incrbyfloat.test.ts +25 -0
- package/pkg/commands/incrbyfloat.ts +11 -0
- package/pkg/commands/json_arrappend.test.ts +40 -0
- package/pkg/commands/json_arrappend.ts +17 -0
- package/pkg/commands/json_arrindex.test.ts +54 -0
- package/pkg/commands/json_arrindex.ts +14 -0
- package/pkg/commands/json_arrinsert.test.ts +49 -0
- package/pkg/commands/json_arrinsert.ts +17 -0
- package/pkg/commands/json_arrlen.test.ts +31 -0
- package/pkg/commands/json_arrlen.ts +14 -0
- package/pkg/commands/json_arrpop.test.ts +30 -0
- package/pkg/commands/json_arrpop.ts +14 -0
- package/pkg/commands/json_arrtrim.test.ts +31 -0
- package/pkg/commands/json_arrtrim.ts +18 -0
- package/pkg/commands/json_clear.test.ts +35 -0
- package/pkg/commands/json_clear.ts +11 -0
- package/pkg/commands/json_del.test.ts +29 -0
- package/pkg/commands/json_del.ts +11 -0
- package/pkg/commands/json_forget.test.ts +29 -0
- package/pkg/commands/json_forget.ts +11 -0
- package/pkg/commands/json_get.test.ts +28 -0
- package/pkg/commands/json_get.ts +44 -0
- package/pkg/commands/json_mget.test.ts +43 -0
- package/pkg/commands/json_mget.ts +11 -0
- package/pkg/commands/json_mset.test.ts +50 -0
- package/pkg/commands/json_mset.ts +26 -0
- package/pkg/commands/json_numincrby.test.ts +28 -0
- package/pkg/commands/json_numincrby.ts +14 -0
- package/pkg/commands/json_nummultby.test.ts +28 -0
- package/pkg/commands/json_nummultby.ts +14 -0
- package/pkg/commands/json_objkeys.test.ts +32 -0
- package/pkg/commands/json_objkeys.ts +14 -0
- package/pkg/commands/json_objlen.test.ts +26 -0
- package/pkg/commands/json_objlen.ts +14 -0
- package/pkg/commands/json_resp.test.ts +31 -0
- package/pkg/commands/json_resp.ts +11 -0
- package/pkg/commands/json_set.test.ts +48 -0
- package/pkg/commands/json_set.ts +34 -0
- package/pkg/commands/json_strappend.test.ts +34 -0
- package/pkg/commands/json_strappend.ts +14 -0
- package/pkg/commands/json_strlen.test.ts +27 -0
- package/pkg/commands/json_strlen.ts +14 -0
- package/pkg/commands/json_toggle.test.ts +26 -0
- package/pkg/commands/json_toggle.ts +11 -0
- package/pkg/commands/json_type.test.ts +29 -0
- package/pkg/commands/json_type.ts +11 -0
- package/pkg/commands/keys.test.ts +18 -0
- package/pkg/commands/keys.ts +11 -0
- package/pkg/commands/lindex.test.ts +33 -0
- package/pkg/commands/lindex.ts +11 -0
- package/pkg/commands/linsert.test.ts +24 -0
- package/pkg/commands/linsert.ts +10 -0
- package/pkg/commands/llen.test.ts +27 -0
- package/pkg/commands/llen.ts +11 -0
- package/pkg/commands/lmove.test.ts +48 -0
- package/pkg/commands/lmove.ts +19 -0
- package/pkg/commands/lmpop.test.ts +86 -0
- package/pkg/commands/lmpop.ts +19 -0
- package/pkg/commands/lpop.test.ts +40 -0
- package/pkg/commands/lpop.ts +14 -0
- package/pkg/commands/lpos.test.ts +56 -0
- package/pkg/commands/lpos.ts +25 -0
- package/pkg/commands/lpush.test.ts +18 -0
- package/pkg/commands/lpush.ts +11 -0
- package/pkg/commands/lpushx.test.ts +30 -0
- package/pkg/commands/lpushx.ts +11 -0
- package/pkg/commands/lrange.test.ts +21 -0
- package/pkg/commands/lrange.ts +11 -0
- package/pkg/commands/lrem.test.ts +19 -0
- package/pkg/commands/lrem.ts +10 -0
- package/pkg/commands/lset.test.ts +43 -0
- package/pkg/commands/lset.ts +8 -0
- package/pkg/commands/ltrim.test.ts +30 -0
- package/pkg/commands/ltrim.ts +8 -0
- package/pkg/commands/mget.test.ts +44 -0
- package/pkg/commands/mget.ts +11 -0
- package/pkg/commands/mod.ts +168 -0
- package/pkg/commands/mset.test.ts +24 -0
- package/pkg/commands/mset.ts +11 -0
- package/pkg/commands/msetnx.test.ts +46 -0
- package/pkg/commands/msetnx.ts +11 -0
- package/pkg/commands/persist.test.ts +22 -0
- package/pkg/commands/persist.ts +11 -0
- package/pkg/commands/pexpire.test.ts +24 -0
- package/pkg/commands/pexpire.ts +11 -0
- package/pkg/commands/pexpireat.test.ts +31 -0
- package/pkg/commands/pexpireat.ts +11 -0
- package/pkg/commands/pfadd.test.ts +80 -0
- package/pkg/commands/pfadd.ts +11 -0
- package/pkg/commands/pfcount.test.ts +55 -0
- package/pkg/commands/pfcount.ts +11 -0
- package/pkg/commands/pfmerge.test.ts +67 -0
- package/pkg/commands/pfmerge.ts +11 -0
- package/pkg/commands/ping.test.ts +19 -0
- package/pkg/commands/ping.ts +14 -0
- package/pkg/commands/psetex.test.ts +23 -0
- package/pkg/commands/psetex.ts +14 -0
- package/pkg/commands/pttl.test.ts +18 -0
- package/pkg/commands/pttl.ts +11 -0
- package/pkg/commands/publish.test.ts +12 -0
- package/pkg/commands/publish.ts +11 -0
- package/pkg/commands/randomkey.test.ts +16 -0
- package/pkg/commands/randomkey.ts +11 -0
- package/pkg/commands/rename.test.ts +19 -0
- package/pkg/commands/rename.ts +11 -0
- package/pkg/commands/renamenx.test.ts +33 -0
- package/pkg/commands/renamenx.ts +11 -0
- package/pkg/commands/rpop.test.ts +40 -0
- package/pkg/commands/rpop.ts +17 -0
- package/pkg/commands/rpush.test.ts +17 -0
- package/pkg/commands/rpush.ts +11 -0
- package/pkg/commands/rpushx.test.ts +30 -0
- package/pkg/commands/rpushx.ts +11 -0
- package/pkg/commands/sadd.test.ts +22 -0
- package/pkg/commands/sadd.ts +14 -0
- package/pkg/commands/scan.test.ts +91 -0
- package/pkg/commands/scan.ts +33 -0
- package/pkg/commands/scard.test.ts +16 -0
- package/pkg/commands/scard.ts +10 -0
- package/pkg/commands/script_exists.test.ts +34 -0
- package/pkg/commands/script_exists.ts +14 -0
- package/pkg/commands/script_flush.ts +21 -0
- package/pkg/commands/script_load.test.ts +11 -0
- package/pkg/commands/script_load.ts +11 -0
- package/pkg/commands/sdiff.test.ts +20 -0
- package/pkg/commands/sdiff.ts +10 -0
- package/pkg/commands/sdiffstore.test.ts +22 -0
- package/pkg/commands/sdiffstore.ts +13 -0
- package/pkg/commands/set.test.ts +168 -0
- package/pkg/commands/set.ts +51 -0
- package/pkg/commands/setbit.test.ts +17 -0
- package/pkg/commands/setbit.ts +14 -0
- package/pkg/commands/setex.test.ts +22 -0
- package/pkg/commands/setex.ts +11 -0
- package/pkg/commands/setnx.test.ts +27 -0
- package/pkg/commands/setnx.ts +11 -0
- package/pkg/commands/setrange.test.ts +25 -0
- package/pkg/commands/setrange.ts +14 -0
- package/pkg/commands/sinter.test.ts +37 -0
- package/pkg/commands/sinter.ts +10 -0
- package/pkg/commands/sinterstore.test.ts +22 -0
- package/pkg/commands/sinterstore.ts +13 -0
- package/pkg/commands/sismember.test.ts +31 -0
- package/pkg/commands/sismember.ts +10 -0
- package/pkg/commands/smembers.test.ts +22 -0
- package/pkg/commands/smembers.ts +11 -0
- package/pkg/commands/smismember.test.ts +22 -0
- package/pkg/commands/smismember.ts +16 -0
- package/pkg/commands/smove.test.ts +18 -0
- package/pkg/commands/smove.ts +13 -0
- package/pkg/commands/spop.test.ts +36 -0
- package/pkg/commands/spop.ts +17 -0
- package/pkg/commands/srandmember.test.ts +31 -0
- package/pkg/commands/srandmember.ts +17 -0
- package/pkg/commands/srem.test.ts +19 -0
- package/pkg/commands/srem.ts +10 -0
- package/pkg/commands/sscan.test.ts +48 -0
- package/pkg/commands/sscan.ts +30 -0
- package/pkg/commands/strlen.test.ts +17 -0
- package/pkg/commands/strlen.ts +11 -0
- package/pkg/commands/sunion.test.ts +22 -0
- package/pkg/commands/sunion.ts +11 -0
- package/pkg/commands/sunionstore.test.ts +30 -0
- package/pkg/commands/sunionstore.ts +14 -0
- package/pkg/commands/time.test.ts +12 -0
- package/pkg/commands/time.ts +10 -0
- package/pkg/commands/touch.test.ts +21 -0
- package/pkg/commands/touch.ts +11 -0
- package/pkg/commands/ttl.test.ts +17 -0
- package/pkg/commands/ttl.ts +11 -0
- package/pkg/commands/type.test.ts +72 -0
- package/pkg/commands/type.ts +12 -0
- package/pkg/commands/types.ts +150 -0
- package/pkg/commands/unlink.test.ts +22 -0
- package/pkg/commands/unlink.ts +11 -0
- package/pkg/commands/xack.test.ts +53 -0
- package/pkg/commands/xack.ts +15 -0
- package/pkg/commands/xadd.test.ts +128 -0
- package/pkg/commands/xadd.ts +64 -0
- package/pkg/commands/xautoclaim.test.ts +105 -0
- package/pkg/commands/xautoclaim.ts +30 -0
- package/pkg/commands/xclaim.test.ts +70 -0
- package/pkg/commands/xclaim.ts +55 -0
- package/pkg/commands/xdel.test.ts +50 -0
- package/pkg/commands/xdel.ts +15 -0
- package/pkg/commands/xgroup.test.ts +202 -0
- package/pkg/commands/xgroup.ts +100 -0
- package/pkg/commands/xinfo.test.ts +82 -0
- package/pkg/commands/xinfo.ts +27 -0
- package/pkg/commands/xlen.test.ts +29 -0
- package/pkg/commands/xlen.ts +11 -0
- package/pkg/commands/xpending.test.ts +94 -0
- package/pkg/commands/xpending.ts +43 -0
- package/pkg/commands/xrange.test.ts +69 -0
- package/pkg/commands/xrange.ts +48 -0
- package/pkg/commands/xread.test.ts +117 -0
- package/pkg/commands/xread.ts +51 -0
- package/pkg/commands/xreadgroup.test.ts +166 -0
- package/pkg/commands/xreadgroup.ts +66 -0
- package/pkg/commands/xrevrange.test.ts +48 -0
- package/pkg/commands/xrevrange.ts +47 -0
- package/pkg/commands/xtrim.test.ts +65 -0
- package/pkg/commands/xtrim.ts +24 -0
- package/pkg/commands/zadd.test.ts +242 -0
- package/pkg/commands/zadd.ts +53 -0
- package/pkg/commands/zcard.test.ts +16 -0
- package/pkg/commands/zcard.ts +11 -0
- package/pkg/commands/zcount.test.ts +16 -0
- package/pkg/commands/zcount.ts +13 -0
- package/pkg/commands/zdiffstore.test.ts +42 -0
- package/pkg/commands/zdiffstore.ts +14 -0
- package/pkg/commands/zincrby.test.ts +19 -0
- package/pkg/commands/zincrby.ts +13 -0
- package/pkg/commands/zinterstore.test.ts +297 -0
- package/pkg/commands/zinterstore.ts +51 -0
- package/pkg/commands/zlexcount.test.ts +23 -0
- package/pkg/commands/zlexcount.ts +10 -0
- package/pkg/commands/zmscore.test.ts +39 -0
- package/pkg/commands/zmscore.ts +15 -0
- package/pkg/commands/zpopmax.test.ts +46 -0
- package/pkg/commands/zpopmax.ts +17 -0
- package/pkg/commands/zpopmin.test.ts +50 -0
- package/pkg/commands/zpopmin.ts +17 -0
- package/pkg/commands/zrange.test.ts +188 -0
- package/pkg/commands/zrange.ts +68 -0
- package/pkg/commands/zrank.test.ts +23 -0
- package/pkg/commands/zrank.ts +14 -0
- package/pkg/commands/zrem.test.ts +21 -0
- package/pkg/commands/zrem.ts +10 -0
- package/pkg/commands/zremrangebylex.test.ts +24 -0
- package/pkg/commands/zremrangebylex.ts +10 -0
- package/pkg/commands/zremrangebyrank.test.ts +27 -0
- package/pkg/commands/zremrangebyrank.ts +13 -0
- package/pkg/commands/zremrangebyscore.test.ts +24 -0
- package/pkg/commands/zremrangebyscore.ts +10 -0
- package/pkg/commands/zrevrank.test.ts +23 -0
- package/pkg/commands/zrevrank.ts +14 -0
- package/pkg/commands/zscan.test.ts +48 -0
- package/pkg/commands/zscan.ts +30 -0
- package/pkg/commands/zscore.test.ts +18 -0
- package/pkg/commands/zscore.ts +14 -0
- package/pkg/commands/zunion.test.ts +251 -0
- package/pkg/commands/zunion.ts +54 -0
- package/pkg/commands/zunionstore.test.ts +274 -0
- package/pkg/commands/zunionstore.ts +51 -0
- package/pkg/error.ts +18 -0
- package/pkg/http.ts +349 -0
- package/pkg/index.ts +1 -0
- package/pkg/pipeline.test.ts +254 -0
- package/pkg/pipeline.ts +1401 -0
- package/pkg/read-your-writes.test.ts +115 -0
- package/pkg/redis.test.ts +250 -0
- package/pkg/redis.ts +1367 -0
- package/pkg/script.test.ts +58 -0
- package/pkg/script.ts +67 -0
- package/pkg/test-utils.test.ts +17 -0
- package/pkg/test-utils.ts +72 -0
- package/pkg/types.ts +35 -0
- package/pkg/util.ts +42 -0
- package/platforms/cloudflare.ts +144 -0
- package/platforms/fastly.ts +100 -0
- package/platforms/nodejs.ts +196 -0
- package/prettier.config.mjs +13 -0
- package/tsconfig.json +21 -0
- package/tsup.config.ts +8 -0
- package/version.ts +1 -0
- package/chunk-JD7AT2OK.js +0 -1
- package/chunk-XCPX3L6C.mjs +0 -1
- package/cloudflare.d.mts +0 -50
- package/cloudflare.d.ts +0 -50
- package/cloudflare.js +0 -1
- package/cloudflare.mjs +0 -1
- package/fastly.d.mts +0 -43
- package/fastly.d.ts +0 -43
- package/fastly.js +0 -1
- package/fastly.mjs +0 -1
- package/nodejs.d.mts +0 -85
- package/nodejs.d.ts +0 -85
- package/nodejs.js +0 -1
- package/nodejs.mjs +0 -1
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
import { Redis } from "../platforms/nodejs";
|
|
2
|
+
import { keygen, newHttpClient } from "./test-utils";
|
|
3
|
+
|
|
4
|
+
import { afterEach, describe, expect, test } from "bun:test";
|
|
5
|
+
import { ScriptLoadCommand } from "./commands/script_load";
|
|
6
|
+
|
|
7
|
+
const client = newHttpClient();
|
|
8
|
+
|
|
9
|
+
const { newKey, cleanup } = keygen();
|
|
10
|
+
afterEach(cleanup);
|
|
11
|
+
|
|
12
|
+
describe("Auto pipeline", () => {
|
|
13
|
+
test("should execute all commands inside a Promise.all in a single pipeline", async () => {
|
|
14
|
+
const persistentKey = newKey();
|
|
15
|
+
const persistentKey2 = newKey();
|
|
16
|
+
const persistentKey3 = newKey();
|
|
17
|
+
const scriptHash = await new ScriptLoadCommand(["return 1"]).exec(client);
|
|
18
|
+
|
|
19
|
+
const redis = Redis.fromEnv({
|
|
20
|
+
latencyLogging: false,
|
|
21
|
+
enableAutoPipelining: true,
|
|
22
|
+
});
|
|
23
|
+
// @ts-expect-error pipelineCounter is not in type but accessible
|
|
24
|
+
expect(redis.pipelineCounter).toBe(0);
|
|
25
|
+
|
|
26
|
+
// all the following commands are in a single pipeline call
|
|
27
|
+
const result = await Promise.all([
|
|
28
|
+
redis.append(newKey(), "hello"),
|
|
29
|
+
redis.bitcount(newKey(), 0, 1),
|
|
30
|
+
redis.bitop("and", newKey(), newKey()),
|
|
31
|
+
redis.bitpos(newKey(), 1, 0),
|
|
32
|
+
redis.dbsize(),
|
|
33
|
+
redis.decr(newKey()),
|
|
34
|
+
redis.decrby(newKey(), 1),
|
|
35
|
+
redis.del(newKey()),
|
|
36
|
+
redis.echo("hello"),
|
|
37
|
+
redis.eval("return ARGV[1]", [], ["Hello"]),
|
|
38
|
+
redis.evalsha(scriptHash, [], ["Hello"]),
|
|
39
|
+
redis.exists(newKey()),
|
|
40
|
+
redis.expire(newKey(), 5),
|
|
41
|
+
redis.expireat(newKey(), Math.floor(Date.now() / 1000) + 60),
|
|
42
|
+
redis.flushall(),
|
|
43
|
+
redis.flushdb(),
|
|
44
|
+
redis.get(newKey()),
|
|
45
|
+
redis.getbit(newKey(), 0),
|
|
46
|
+
redis.getdel(newKey()),
|
|
47
|
+
redis.getset(newKey(), "hello"),
|
|
48
|
+
redis.hdel(newKey(), "field"),
|
|
49
|
+
redis.hexists(newKey(), "field"),
|
|
50
|
+
redis.hget(newKey(), "field"),
|
|
51
|
+
redis.hgetall(newKey()),
|
|
52
|
+
redis.hincrby(newKey(), "field", 1),
|
|
53
|
+
redis.hincrbyfloat(newKey(), "field", 1.5),
|
|
54
|
+
redis.hkeys(newKey()),
|
|
55
|
+
redis.hlen(newKey()),
|
|
56
|
+
redis.hmget(newKey(), newKey()),
|
|
57
|
+
redis.hmset(newKey(), { field: "field", value: "value" }),
|
|
58
|
+
redis.hscan(newKey(), 0),
|
|
59
|
+
redis.hset(newKey(), { field: "value" }),
|
|
60
|
+
redis.hsetnx(newKey(), "field", "value"),
|
|
61
|
+
redis.hstrlen(newKey(), "field"),
|
|
62
|
+
redis.hvals(newKey()),
|
|
63
|
+
redis.incr(newKey()),
|
|
64
|
+
redis.incrby(newKey(), 1),
|
|
65
|
+
redis.incrbyfloat(newKey(), 1.5),
|
|
66
|
+
redis.keys("*"),
|
|
67
|
+
redis.lindex(newKey(), 0),
|
|
68
|
+
redis.linsert(newKey(), "before", "pivot", "value"),
|
|
69
|
+
redis.llen(newKey()),
|
|
70
|
+
redis.lmove(newKey(), newKey(), "left", "right"),
|
|
71
|
+
redis.lpop(newKey()),
|
|
72
|
+
redis.lpos(newKey(), "value"),
|
|
73
|
+
redis.lpush(persistentKey, "element"),
|
|
74
|
+
redis.lpushx(newKey(), "element1", "element2"),
|
|
75
|
+
redis.lrange(newKey(), 0, 1),
|
|
76
|
+
redis.lrem(newKey(), 1, "value"),
|
|
77
|
+
redis.lset(persistentKey, 0, "value"),
|
|
78
|
+
redis.ltrim(newKey(), 0, 1),
|
|
79
|
+
redis.hrandfield(newKey()),
|
|
80
|
+
redis.hrandfield(newKey(), 2),
|
|
81
|
+
redis.hrandfield(newKey(), 3, true),
|
|
82
|
+
redis.mget<[string, string]>(newKey(), newKey()),
|
|
83
|
+
redis.mset({ key1: "value", key2: "value" }),
|
|
84
|
+
redis.msetnx({ key3: "value", key4: "value" }),
|
|
85
|
+
redis.persist(newKey()),
|
|
86
|
+
redis.pexpire(newKey(), 1000),
|
|
87
|
+
redis.pexpireat(newKey(), Date.now() + 1000),
|
|
88
|
+
redis.ping(),
|
|
89
|
+
redis.psetex(newKey(), 1, "value"),
|
|
90
|
+
redis.pttl(newKey()),
|
|
91
|
+
redis.publish("test", "hello"),
|
|
92
|
+
redis.randomkey(),
|
|
93
|
+
redis.rename(persistentKey, persistentKey2),
|
|
94
|
+
redis.renamenx(persistentKey2, newKey()),
|
|
95
|
+
redis.rpop(newKey()),
|
|
96
|
+
redis.rpush(newKey(), "element1", "element2"),
|
|
97
|
+
redis.rpushx(newKey(), "element1", "element2"),
|
|
98
|
+
redis.sadd(newKey(), "memeber1", "member2"),
|
|
99
|
+
redis.scan(0),
|
|
100
|
+
redis.scard(newKey()),
|
|
101
|
+
redis.sdiff(newKey()),
|
|
102
|
+
redis.sdiffstore(newKey(), newKey()),
|
|
103
|
+
redis.set(newKey(), "value"),
|
|
104
|
+
redis.setbit(newKey(), 1, 1),
|
|
105
|
+
redis.setex(newKey(), 1, "value"),
|
|
106
|
+
redis.setnx(newKey(), "value"),
|
|
107
|
+
redis.setrange(newKey(), 1, "value"),
|
|
108
|
+
redis.sinter(newKey(), newKey()),
|
|
109
|
+
redis.sinterstore(newKey(), newKey()),
|
|
110
|
+
redis.sismember(newKey(), "member"),
|
|
111
|
+
redis.smembers(newKey()),
|
|
112
|
+
redis.smove(newKey(), newKey(), "member"),
|
|
113
|
+
redis.spop(newKey()),
|
|
114
|
+
redis.srandmember(newKey()),
|
|
115
|
+
redis.srem(newKey(), "member"),
|
|
116
|
+
redis.sscan(newKey(), 0),
|
|
117
|
+
redis.strlen(newKey()),
|
|
118
|
+
redis.sunion(newKey()),
|
|
119
|
+
redis.sunionstore(newKey(), newKey()),
|
|
120
|
+
redis.time(),
|
|
121
|
+
redis.touch(newKey()),
|
|
122
|
+
redis.ttl(newKey()),
|
|
123
|
+
redis.type(newKey()),
|
|
124
|
+
redis.unlink(newKey()),
|
|
125
|
+
redis.zadd(newKey(), { score: 0, member: "member" }),
|
|
126
|
+
redis.zcard(newKey()),
|
|
127
|
+
redis.scriptExists(scriptHash),
|
|
128
|
+
redis.scriptFlush({ async: true }),
|
|
129
|
+
redis.scriptLoad("return 1"),
|
|
130
|
+
redis.zcount(newKey(), 0, 1),
|
|
131
|
+
redis.zincrby(newKey(), 1, "member"),
|
|
132
|
+
redis.zinterstore(newKey(), 1, [newKey()]),
|
|
133
|
+
redis.zlexcount(newKey(), "-", "+"),
|
|
134
|
+
redis.zpopmax(newKey()),
|
|
135
|
+
redis.zpopmin(newKey()),
|
|
136
|
+
redis.zrange(newKey(), 0, 1),
|
|
137
|
+
redis.zrank(newKey(), "member"),
|
|
138
|
+
redis.zrem(newKey(), "member"),
|
|
139
|
+
redis.zremrangebylex(newKey(), "-", "+"),
|
|
140
|
+
redis.zremrangebyrank(newKey(), 0, 1),
|
|
141
|
+
redis.zremrangebyscore(newKey(), 0, 1),
|
|
142
|
+
redis.zrevrank(newKey(), "member"),
|
|
143
|
+
redis.zscan(newKey(), 0),
|
|
144
|
+
redis.zscore(newKey(), "member"),
|
|
145
|
+
redis.zunionstore(newKey(), 1, [newKey()]),
|
|
146
|
+
redis.zunion(1, [newKey()]),
|
|
147
|
+
redis.json.set(persistentKey3, "$", { log: ["one", "two"] }),
|
|
148
|
+
redis.json.arrappend(persistentKey3, "$.log", '"three"'),
|
|
149
|
+
]);
|
|
150
|
+
expect(result).toBeTruthy();
|
|
151
|
+
expect(result.length).toBe(121); // returns
|
|
152
|
+
// @ts-expect-error pipelineCounter is not in type but accessible120 results
|
|
153
|
+
expect(redis.pipelineCounter).toBe(1);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
test("should group async requests with sync requests", async () => {
|
|
157
|
+
const redis = Redis.fromEnv({
|
|
158
|
+
latencyLogging: false,
|
|
159
|
+
enableAutoPipelining: true,
|
|
160
|
+
});
|
|
161
|
+
// @ts-expect-error pipelineCounter is not in type but accessible
|
|
162
|
+
expect(redis.pipelineCounter).toBe(0);
|
|
163
|
+
|
|
164
|
+
// following five commands are added to the pipeline
|
|
165
|
+
void redis.flushdb();
|
|
166
|
+
void redis.incr("baz");
|
|
167
|
+
void redis.incr("baz");
|
|
168
|
+
void redis.set("foo", "bar");
|
|
169
|
+
void redis.incr("baz");
|
|
170
|
+
|
|
171
|
+
// two get calls are added to the pipeline and pipeline
|
|
172
|
+
// is executed since we called await
|
|
173
|
+
const [fooValue, bazValue] = await Promise.all([redis.get("foo"), redis.get("baz")]);
|
|
174
|
+
|
|
175
|
+
expect(fooValue).toBe("bar");
|
|
176
|
+
expect(bazValue).toBe(3);
|
|
177
|
+
// @ts-expect-error pipelineCounter is not in type but accessible
|
|
178
|
+
expect(redis.pipelineCounter).toBe(1);
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
test("should execute a pipeline for each consecutive awaited command", async () => {
|
|
182
|
+
const redis = Redis.fromEnv({
|
|
183
|
+
latencyLogging: false,
|
|
184
|
+
enableAutoPipelining: true,
|
|
185
|
+
});
|
|
186
|
+
// @ts-expect-error pipelineCounter is not in type but accessible
|
|
187
|
+
expect(redis.pipelineCounter).toBe(0);
|
|
188
|
+
|
|
189
|
+
void redis.flushdb();
|
|
190
|
+
|
|
191
|
+
const res1 = await redis.incr("baz");
|
|
192
|
+
// @ts-expect-error pipelineCounter is not in type but accessible
|
|
193
|
+
expect(redis.pipelineCounter).toBe(1);
|
|
194
|
+
|
|
195
|
+
const res2 = await redis.incr("baz");
|
|
196
|
+
// @ts-expect-error pipelineCounter is not in type but accessible
|
|
197
|
+
expect(redis.pipelineCounter).toBe(2);
|
|
198
|
+
|
|
199
|
+
const res3 = await redis.set("foo", "bar");
|
|
200
|
+
// @ts-expect-error pipelineCounter is not in type but accessible
|
|
201
|
+
expect(redis.pipelineCounter).toBe(3);
|
|
202
|
+
|
|
203
|
+
expect([res1, res2, res3]).toEqual([1, 2, "OK"]);
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
test("should execute a single pipeline for several commands inside Promise.all", async () => {
|
|
207
|
+
const redis = Redis.fromEnv({
|
|
208
|
+
latencyLogging: false,
|
|
209
|
+
enableAutoPipelining: true,
|
|
210
|
+
});
|
|
211
|
+
// @ts-expect-error pipelineCounter is not in type but accessible
|
|
212
|
+
expect(redis.pipelineCounter).toBe(0);
|
|
213
|
+
|
|
214
|
+
const resArray = await Promise.all([
|
|
215
|
+
redis.flushdb(),
|
|
216
|
+
redis.incr("baz"),
|
|
217
|
+
redis.incr("baz"),
|
|
218
|
+
redis.set("foo", "bar"),
|
|
219
|
+
redis.get("foo"),
|
|
220
|
+
]);
|
|
221
|
+
// @ts-expect-error pipelineCounter is not in type but accessible
|
|
222
|
+
expect(redis.pipelineCounter).toBe(1);
|
|
223
|
+
expect(resArray).toEqual(["OK", 1, 2, "OK", "bar"]);
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
test("should be able to utilize only redis functions 'use' like usual", async () => {
|
|
227
|
+
const redis = Redis.fromEnv({
|
|
228
|
+
latencyLogging: false,
|
|
229
|
+
enableAutoPipelining: true,
|
|
230
|
+
});
|
|
231
|
+
// @ts-expect-error pipelineCounter is not in type but accessible
|
|
232
|
+
expect(redis.pipelineCounter).toBe(0);
|
|
233
|
+
|
|
234
|
+
let state = false;
|
|
235
|
+
redis.use(async (req, next) => {
|
|
236
|
+
state = true;
|
|
237
|
+
return await next(req);
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
// @ts-expect-error pipelineCounter is not in type but accessible
|
|
241
|
+
expect(redis.pipelineCounter).toBe(0);
|
|
242
|
+
|
|
243
|
+
const a = await redis.incr("aeroplane");
|
|
244
|
+
expect(a).toEqual(1);
|
|
245
|
+
expect(state).toEqual(true);
|
|
246
|
+
|
|
247
|
+
// @ts-expect-error pipelineCounter is not in type but accessible
|
|
248
|
+
expect(redis.pipelineCounter).toBe(1);
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
test("should be able to utilize only redis functions 'multi' and 'pipeline' like usual", async () => {
|
|
252
|
+
const redis = Redis.fromEnv({
|
|
253
|
+
latencyLogging: false,
|
|
254
|
+
enableAutoPipelining: true,
|
|
255
|
+
});
|
|
256
|
+
// @ts-expect-error pipelineCounter is not in type but accessible
|
|
257
|
+
expect(redis.pipelineCounter).toBe(0);
|
|
258
|
+
|
|
259
|
+
const pipe = redis.pipeline();
|
|
260
|
+
pipe.incr("voila");
|
|
261
|
+
pipe.incr("voila");
|
|
262
|
+
const result = await pipe.exec();
|
|
263
|
+
expect(result).toEqual([1, 2]);
|
|
264
|
+
|
|
265
|
+
// @ts-expect-error pipelineCounter is not in type but accessible
|
|
266
|
+
expect(redis.pipelineCounter).toBe(0);
|
|
267
|
+
|
|
268
|
+
const transaction = redis.multi();
|
|
269
|
+
transaction.incr("et voila");
|
|
270
|
+
transaction.incr("et voila");
|
|
271
|
+
const result_2 = await transaction.exec();
|
|
272
|
+
expect(result_2).toEqual([1, 2]);
|
|
273
|
+
|
|
274
|
+
// @ts-expect-error pipelineCounter is not in type but accessible
|
|
275
|
+
expect(redis.pipelineCounter).toBe(0);
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
test("should be able to utilize only redis functions 'createScript' like usual", async () => {
|
|
279
|
+
const redis = Redis.fromEnv({
|
|
280
|
+
latencyLogging: false,
|
|
281
|
+
enableAutoPipelining: true,
|
|
282
|
+
});
|
|
283
|
+
// @ts-expect-error pipelineCounter is not in type but accessible
|
|
284
|
+
expect(redis.pipelineCounter).toBe(0);
|
|
285
|
+
|
|
286
|
+
const script = redis.createScript("return ARGV[1];");
|
|
287
|
+
|
|
288
|
+
// @ts-expect-error pipelineCounter is not in type but accessible
|
|
289
|
+
expect(redis.pipelineCounter).toBe(0);
|
|
290
|
+
|
|
291
|
+
const res = await script.eval([], ["Hello World"]);
|
|
292
|
+
expect(res).toEqual("Hello World");
|
|
293
|
+
|
|
294
|
+
// @ts-expect-error pipelineCounter is not in type but accessible
|
|
295
|
+
expect(redis.pipelineCounter).toBe(1);
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
test("should handle JSON commands correctly", async () => {
|
|
299
|
+
const redis = Redis.fromEnv({
|
|
300
|
+
latencyLogging: false,
|
|
301
|
+
enableAutoPipelining: true,
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
// @ts-expect-error pipelineCounter is not in type but accessible
|
|
305
|
+
expect(redis.pipelineCounter).toBe(0);
|
|
306
|
+
|
|
307
|
+
const res = await Promise.all([
|
|
308
|
+
redis.set("foo1", "bar"),
|
|
309
|
+
redis.json.set("baz1", "$", { hello: "world" }),
|
|
310
|
+
redis.get("foo1"),
|
|
311
|
+
redis.json.get("baz1"),
|
|
312
|
+
redis.json.del("baz1"),
|
|
313
|
+
redis.json.get("baz1"),
|
|
314
|
+
]);
|
|
315
|
+
|
|
316
|
+
// @ts-expect-error pipelineCounter is not in type but accessible
|
|
317
|
+
expect(redis.pipelineCounter).toBe(1);
|
|
318
|
+
|
|
319
|
+
expect(res).toEqual(["OK", "OK", "bar", { hello: "world" }, 1, null]);
|
|
320
|
+
});
|
|
321
|
+
});
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import type { Command } from "./commands/command";
|
|
2
|
+
import type { Pipeline } from "./pipeline";
|
|
3
|
+
import type { Redis } from "./redis";
|
|
4
|
+
import type { CommandArgs } from "./types";
|
|
5
|
+
|
|
6
|
+
// properties which are only available in redis
|
|
7
|
+
type redisOnly = Exclude<keyof Redis, keyof Pipeline>;
|
|
8
|
+
|
|
9
|
+
export function createAutoPipelineProxy(_redis: Redis, json?: boolean): Redis {
|
|
10
|
+
const redis = _redis as Redis & {
|
|
11
|
+
autoPipelineExecutor: AutoPipelineExecutor;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
if (!redis.autoPipelineExecutor) {
|
|
15
|
+
redis.autoPipelineExecutor = new AutoPipelineExecutor(redis);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return new Proxy(redis, {
|
|
19
|
+
get: (redis, command: "pipelineCounter" | keyof Pipeline | redisOnly) => {
|
|
20
|
+
// return pipelineCounter of autoPipelineExecutor
|
|
21
|
+
if (command === "pipelineCounter") {
|
|
22
|
+
return redis.autoPipelineExecutor.pipelineCounter;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (command === "json") {
|
|
26
|
+
return createAutoPipelineProxy(redis, true);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const commandInRedisButNotPipeline =
|
|
30
|
+
command in redis && !(command in redis.autoPipelineExecutor.pipeline);
|
|
31
|
+
|
|
32
|
+
if (commandInRedisButNotPipeline) {
|
|
33
|
+
return redis[command as redisOnly];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// If the method is a function on the pipeline, wrap it with the executor logic
|
|
37
|
+
const isFunction = json
|
|
38
|
+
? typeof redis.autoPipelineExecutor.pipeline.json[command as keyof Pipeline["json"]] ===
|
|
39
|
+
"function"
|
|
40
|
+
: typeof redis.autoPipelineExecutor.pipeline[command as keyof Pipeline] === "function";
|
|
41
|
+
if (isFunction) {
|
|
42
|
+
return (...args: CommandArgs<typeof Command>) => {
|
|
43
|
+
// pass the function as a callback
|
|
44
|
+
return redis.autoPipelineExecutor.withAutoPipeline((pipeline) => {
|
|
45
|
+
if (json) {
|
|
46
|
+
(pipeline.json[command as keyof Pipeline["json"]] as (...args: any) => unknown)(
|
|
47
|
+
...args
|
|
48
|
+
);
|
|
49
|
+
} else {
|
|
50
|
+
(pipeline[command as keyof Pipeline] as (...args: any) => unknown)(...args);
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// if the property is not a function, a property of redis or "pipelineCounter"
|
|
57
|
+
// simply return it from pipeline
|
|
58
|
+
return redis.autoPipelineExecutor.pipeline[command as keyof Pipeline];
|
|
59
|
+
},
|
|
60
|
+
}) as Redis;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
class AutoPipelineExecutor {
|
|
64
|
+
private pipelinePromises = new WeakMap<Pipeline, Promise<unknown[]>>();
|
|
65
|
+
private activePipeline: Pipeline | null = null;
|
|
66
|
+
private indexInCurrentPipeline = 0;
|
|
67
|
+
private redis: Redis;
|
|
68
|
+
pipeline: Pipeline; // only to make sure that proxy can work
|
|
69
|
+
pipelineCounter = 0; // to keep track of how many times a pipeline was executed
|
|
70
|
+
|
|
71
|
+
constructor(redis: Redis) {
|
|
72
|
+
this.redis = redis;
|
|
73
|
+
this.pipeline = redis.pipeline();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async withAutoPipeline<T>(executeWithPipeline: (pipeline: Pipeline) => unknown): Promise<T> {
|
|
77
|
+
const pipeline = this.activePipeline ?? this.redis.pipeline();
|
|
78
|
+
|
|
79
|
+
if (!this.activePipeline) {
|
|
80
|
+
this.activePipeline = pipeline;
|
|
81
|
+
this.indexInCurrentPipeline = 0;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const index = this.indexInCurrentPipeline++;
|
|
85
|
+
executeWithPipeline(pipeline);
|
|
86
|
+
|
|
87
|
+
const pipelineDone = this.deferExecution().then(() => {
|
|
88
|
+
if (!this.pipelinePromises.has(pipeline)) {
|
|
89
|
+
const pipelinePromise = pipeline.exec();
|
|
90
|
+
this.pipelineCounter += 1;
|
|
91
|
+
|
|
92
|
+
this.pipelinePromises.set(pipeline, pipelinePromise);
|
|
93
|
+
this.activePipeline = null;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return this.pipelinePromises.get(pipeline)!;
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
const results = await pipelineDone;
|
|
100
|
+
return results[index] as T;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
private async deferExecution() {
|
|
104
|
+
await Promise.resolve();
|
|
105
|
+
await Promise.resolve();
|
|
106
|
+
}
|
|
107
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { keygen, newHttpClient, randomID } from "../test-utils";
|
|
2
|
+
import { AppendCommand } from "./append";
|
|
3
|
+
|
|
4
|
+
import { afterAll, describe, expect, test } from "bun:test";
|
|
5
|
+
const client = newHttpClient();
|
|
6
|
+
|
|
7
|
+
const { newKey, cleanup } = keygen();
|
|
8
|
+
afterAll(cleanup);
|
|
9
|
+
|
|
10
|
+
describe("when key is not set", () => {
|
|
11
|
+
test("appends to empty value", async () => {
|
|
12
|
+
const key = newKey();
|
|
13
|
+
const value = randomID();
|
|
14
|
+
const res = await new AppendCommand([key, value]).exec(client);
|
|
15
|
+
expect(res).toEqual(value.length);
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
describe("when key is set", () => {
|
|
20
|
+
test("appends to existing value", async () => {
|
|
21
|
+
const key = newKey();
|
|
22
|
+
const value = randomID();
|
|
23
|
+
const res = await new AppendCommand([key, value]).exec(client);
|
|
24
|
+
expect(res).toEqual(value.length);
|
|
25
|
+
const res2 = await new AppendCommand([key, "_"]).exec(client);
|
|
26
|
+
expect(res2).toEqual(value.length + 1);
|
|
27
|
+
});
|
|
28
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { CommandOptions } from "./command";
|
|
2
|
+
import { Command } from "./command";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @see https://redis.io/commands/append
|
|
6
|
+
*/
|
|
7
|
+
export class AppendCommand extends Command<number, number> {
|
|
8
|
+
constructor(cmd: [key: string, value: string], opts?: CommandOptions<number, number>) {
|
|
9
|
+
super(["append", ...cmd], opts);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { afterAll, describe, expect, test } from "bun:test";
|
|
2
|
+
import { keygen, newHttpClient } from "../test-utils";
|
|
3
|
+
import { BitCountCommand } from "./bitcount";
|
|
4
|
+
|
|
5
|
+
import { SetCommand } from "./set";
|
|
6
|
+
const client = newHttpClient();
|
|
7
|
+
|
|
8
|
+
const { newKey, cleanup } = keygen();
|
|
9
|
+
afterAll(cleanup);
|
|
10
|
+
|
|
11
|
+
describe("when key is not set", () => {
|
|
12
|
+
test("returns 0", async () => {
|
|
13
|
+
const key = newKey();
|
|
14
|
+
const res = await new BitCountCommand([key]).exec(client);
|
|
15
|
+
expect(res).toEqual(0);
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
describe("when key is set", () => {
|
|
20
|
+
test("returns bitcount", async () => {
|
|
21
|
+
const key = newKey();
|
|
22
|
+
const value = "Hello World";
|
|
23
|
+
await new SetCommand([key, value]).exec(client);
|
|
24
|
+
const res = await new BitCountCommand([key]).exec(client);
|
|
25
|
+
expect(res).toEqual(43);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test("with start and end", () => {
|
|
29
|
+
test("returns bitcount", async () => {
|
|
30
|
+
const key = newKey();
|
|
31
|
+
const value = "Hello World";
|
|
32
|
+
await new SetCommand([key, value]).exec(client);
|
|
33
|
+
const res = await new BitCountCommand([key, 4, 8]).exec(client);
|
|
34
|
+
expect(res).toEqual(22);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { CommandOptions } from "./command";
|
|
2
|
+
import { Command } from "./command";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @see https://redis.io/commands/bitcount
|
|
6
|
+
*/
|
|
7
|
+
export class BitCountCommand extends Command<number, number> {
|
|
8
|
+
constructor(
|
|
9
|
+
cmd: [key: string, start?: never, end?: never],
|
|
10
|
+
opts?: CommandOptions<number, number>
|
|
11
|
+
);
|
|
12
|
+
constructor(
|
|
13
|
+
cmd: [key: string, start: number, end: number],
|
|
14
|
+
opts?: CommandOptions<number, number>
|
|
15
|
+
);
|
|
16
|
+
constructor(
|
|
17
|
+
[key, start, end]: [key: string, start?: number, end?: number],
|
|
18
|
+
opts?: CommandOptions<number, number>
|
|
19
|
+
) {
|
|
20
|
+
const command: unknown[] = ["bitcount", key];
|
|
21
|
+
if (typeof start === "number") {
|
|
22
|
+
command.push(start);
|
|
23
|
+
}
|
|
24
|
+
if (typeof end === "number") {
|
|
25
|
+
command.push(end);
|
|
26
|
+
}
|
|
27
|
+
super(command, opts);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { afterAll, describe, expect, test } from "bun:test";
|
|
2
|
+
import { keygen, newHttpClient } from "../test-utils";
|
|
3
|
+
import { BitFieldCommand } from "./bitfield";
|
|
4
|
+
|
|
5
|
+
const client = newHttpClient();
|
|
6
|
+
|
|
7
|
+
const { newKey, cleanup } = keygen();
|
|
8
|
+
afterAll(cleanup);
|
|
9
|
+
|
|
10
|
+
describe("when key is not set", () => {
|
|
11
|
+
test("returns 0", async () => {
|
|
12
|
+
const key = newKey();
|
|
13
|
+
const res = await new BitFieldCommand([key], client).get("u4", "#0").exec();
|
|
14
|
+
expect(res).toEqual([0]);
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
describe("when key is set", () => {
|
|
19
|
+
test("sets / gets value", async () => {
|
|
20
|
+
const key = newKey();
|
|
21
|
+
const value = 42;
|
|
22
|
+
const res = await new BitFieldCommand([key], client)
|
|
23
|
+
.set("u8", "#0", value)
|
|
24
|
+
.get("u8", "#0")
|
|
25
|
+
.exec();
|
|
26
|
+
expect(res).toEqual([0, value]);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test("increments value", async () => {
|
|
30
|
+
const key = newKey();
|
|
31
|
+
const value = 42;
|
|
32
|
+
const increment = 10;
|
|
33
|
+
const res = await new BitFieldCommand([key], client)
|
|
34
|
+
.set("u8", "#0", value)
|
|
35
|
+
.incrby("u8", "#0", increment)
|
|
36
|
+
.exec();
|
|
37
|
+
expect(res).toEqual([0, value + increment]);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test("overflows", async () => {
|
|
41
|
+
const key = newKey();
|
|
42
|
+
const value = 255;
|
|
43
|
+
const bitWidth = 8;
|
|
44
|
+
const res = await new BitFieldCommand([key], client)
|
|
45
|
+
.set(`u${bitWidth}`, "#0", value)
|
|
46
|
+
.incrby(`u${bitWidth}`, "#0", 10)
|
|
47
|
+
.overflow("WRAP")
|
|
48
|
+
.exec();
|
|
49
|
+
expect(res).toEqual([0, (value + 10) % 2 ** bitWidth]);
|
|
50
|
+
});
|
|
51
|
+
});
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { type Requester } from "../http";
|
|
2
|
+
import { Command, type CommandOptions } from "./command";
|
|
3
|
+
|
|
4
|
+
type SubCommandArgs<TRest extends unknown[] = []> = [
|
|
5
|
+
encoding: string, // u1 - u63 | i1 - i64
|
|
6
|
+
offset: number | string, // <int> | #<int>
|
|
7
|
+
...rest: TRest,
|
|
8
|
+
];
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @see https://redis.io/commands/bitfield
|
|
12
|
+
*/
|
|
13
|
+
export class BitFieldCommand<T = Promise<number[]>> {
|
|
14
|
+
private command: (string | number)[];
|
|
15
|
+
|
|
16
|
+
constructor(
|
|
17
|
+
args: [key: string],
|
|
18
|
+
private client: Requester,
|
|
19
|
+
private opts?: CommandOptions<number[], number[]>,
|
|
20
|
+
private execOperation = (command: Command<number[], number[]>) => command.exec(this.client) as T
|
|
21
|
+
) {
|
|
22
|
+
this.command = ["bitfield", ...args];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
private chain(...args: typeof this.command) {
|
|
26
|
+
this.command.push(...args);
|
|
27
|
+
return this;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
get(...args: SubCommandArgs) {
|
|
31
|
+
return this.chain("get", ...args);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
set(...args: SubCommandArgs<[value: number]>) {
|
|
35
|
+
return this.chain("set", ...args);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
incrby(...args: SubCommandArgs<[increment: number]>) {
|
|
39
|
+
return this.chain("incrby", ...args);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
overflow(overflow: "WRAP" | "SAT" | "FAIL") {
|
|
43
|
+
return this.chain("overflow", overflow);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
exec() {
|
|
47
|
+
const command = new Command(this.command, this.opts);
|
|
48
|
+
return this.execOperation(command);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { BitOpCommand } from "./bitop";
|
|
2
|
+
|
|
3
|
+
import { afterAll, describe, expect, test } from "bun:test";
|
|
4
|
+
import { keygen, newHttpClient } from "../test-utils";
|
|
5
|
+
import { SetCommand } from "./set";
|
|
6
|
+
const client = newHttpClient();
|
|
7
|
+
|
|
8
|
+
const { newKey, cleanup } = keygen();
|
|
9
|
+
afterAll(cleanup);
|
|
10
|
+
|
|
11
|
+
describe("when key is not set", () => {
|
|
12
|
+
test("returns 0", async () => {
|
|
13
|
+
const source = newKey();
|
|
14
|
+
const dest = newKey();
|
|
15
|
+
const res = await new BitOpCommand(["and", dest, source]).exec(client);
|
|
16
|
+
expect(res).toEqual(0);
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
describe("when key is set", () => {
|
|
21
|
+
describe("not", () => {
|
|
22
|
+
test("inverts all bits", async () => {
|
|
23
|
+
const source = newKey();
|
|
24
|
+
const sourcevalue = "Hello World";
|
|
25
|
+
const dest = newKey();
|
|
26
|
+
const destValue = "foo: bar";
|
|
27
|
+
await new SetCommand([source, sourcevalue]).exec(client);
|
|
28
|
+
await new SetCommand([dest, destValue]).exec(client);
|
|
29
|
+
const res = await new BitOpCommand(["not", dest, source]).exec(client);
|
|
30
|
+
expect(res).toEqual(11);
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
describe("and", () => {
|
|
34
|
+
test("works", async () => {
|
|
35
|
+
const source = newKey();
|
|
36
|
+
const sourcevalue = "Hello World";
|
|
37
|
+
const dest = newKey();
|
|
38
|
+
const destValue = "foo: bar";
|
|
39
|
+
await new SetCommand([source, sourcevalue]).exec(client);
|
|
40
|
+
await new SetCommand([dest, destValue]).exec(client);
|
|
41
|
+
const res = await new BitOpCommand(["and", dest, source]).exec(client);
|
|
42
|
+
expect(res).toEqual(11);
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
});
|