From ebca66d6f6afb88bab6dc2fae6d38e9fff89bc07 Mon Sep 17 00:00:00 2001 From: Leibale Date: Wed, 1 Nov 2023 14:09:58 -0400 Subject: [PATCH] WIP --- package-lock.json | 567 +++++++--- package.json | 11 +- packages/bloom/lib/commands/bloom/RESERVE.ts | 1 - packages/bloom/lib/commands/cuckoo/DEL.ts | 2 +- packages/bloom/lib/commands/cuckoo/EXISTS.ts | 2 +- packages/bloom/package.json | 2 +- packages/client/lib/RESP/types.ts | 5 - packages/client/lib/client/legacy-mode.ts | 2 +- packages/client/lib/client/multi-command.ts | 2 +- packages/client/lib/cluster/cluster-slots.ts | 8 +- packages/client/lib/cluster/multi-command.ts | 2 +- .../lib/commands/CLIENT_TRACKINGINFO.spec.ts | 1 - packages/client/lib/commands/FCALL.ts | 2 +- packages/client/lib/commands/FCALL_RO.ts | 2 +- packages/client/lib/commands/FUNCTION_LIST.ts | 2 +- .../lib/commands/GEORADIUSBYMEMBER_WITH.ts | 2 +- packages/client/lib/commands/MEMORY_STATS.ts | 2 +- packages/client/lib/commands/MODULE_LOAD.ts | 1 - packages/client/lib/commands/UNWATCH.ts | 2 +- packages/client/lib/commands/ZINCRBY.ts | 2 +- packages/client/lib/commands/ZSCAN.ts | 2 +- .../lib/commands/generic-transformers.ts | 2 +- packages/client/package.json | 2 +- packages/graph/lib/graph.ts | 4 +- packages/graph/package.json | 2 +- packages/json/lib/commands/DEBUG_MEMORY.ts | 2 +- packages/json/package.json | 2 +- .../search/lib/commands/AGGREGATE.spec.ts | 970 +++++++++--------- packages/search/lib/commands/AGGREGATE.ts | 499 +++++---- .../lib/commands/AGGREGATE_WITHCURSOR.spec.ts | 68 +- .../lib/commands/AGGREGATE_WITHCURSOR.ts | 99 +- packages/search/lib/commands/CREATE.ts | 7 +- packages/search/lib/commands/SEARCH.spec.ts | 613 +++++------ packages/search/lib/commands/SEARCH.ts | 247 +++-- .../lib/commands/SEARCH_NOCONTENT.spec.ts | 65 +- .../search/lib/commands/SEARCH_NOCONTENT.ts | 41 +- packages/search/lib/commands/index.ts | 558 +--------- packages/search/package.json | 2 +- packages/test-utils/lib/dockers.ts | 2 +- packages/time-series/lib/index.ts | 10 +- packages/time-series/package.json | 2 +- tsconfig.base.json | 16 +- 42 files changed, 1825 insertions(+), 2010 deletions(-) diff --git a/package-lock.json b/package-lock.json index 724dae3bce..f28500f157 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,15 +10,14 @@ ], "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.2", - "@tsconfig/node18": "^18.2.2", "@types/mocha": "^10.0.3", + "@types/node": "^20.8.9", "@typescript-eslint/eslint-plugin": "^6.9.0", "@typescript-eslint/parser": "^6.9.0", "gh-pages": "^6.0.0", "mocha": "^10.2.0", "nyc": "^15.1.0", - "source-map-support": "^0.5.21", - "ts-node": "^10.9.1", + "tsx": "^3.14.0", "typedoc": "^0.25.2", "typescript": "^5.2.2" } @@ -509,26 +508,356 @@ "node": ">=6.9.0" } }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "node_modules/@esbuild/android-arm": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", + "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", + "cpu": [ + "arm" + ], "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" - }, + "optional": true, + "os": [ + "android" + ], "engines": { "node": ">=12" } }, - "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "node_modules/@esbuild/android-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", + "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", + "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", + "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", + "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", + "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", + "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", + "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", + "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", + "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", + "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", + "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", + "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", + "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", + "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", + "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", + "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", + "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", + "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", + "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", + "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", + "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" } }, "node_modules/@eslint-community/eslint-utils": { @@ -903,36 +1232,6 @@ "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==", "dev": true }, - "node_modules/@tsconfig/node10": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", - "dev": true - }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true - }, - "node_modules/@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true - }, - "node_modules/@tsconfig/node16": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "dev": true - }, - "node_modules/@tsconfig/node18": { - "version": "18.2.2", - "resolved": "https://registry.npmjs.org/@tsconfig/node18/-/node18-18.2.2.tgz", - "integrity": "sha512-d6McJeGsuoRlwWZmVIeE8CUA27lu6jLjvv1JzqmpsytOYYbVi1tHZEnwCNVOXnj4pyLvneZlFlpXUK+X9wBWyw==", - "dev": true - }, "node_modules/@types/json-schema": { "version": "7.0.14", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.14.tgz", @@ -946,13 +1245,12 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.8.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.6.tgz", - "integrity": "sha512-eWO4K2Ji70QzKUqRy6oyJWUeB7+g2cRagT3T/nxYibYcT4y2BDL8lqolRXjTHmkZCdJfIPaY73KbJAZmcryxTQ==", + "version": "20.8.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.9.tgz", + "integrity": "sha512-UzykFsT3FhHb1h7yD4CA4YhBHq545JC0YnEz41xkipN88eKQtL6rSgocL5tbAP6Ola9Izm/Aw4Ora8He4x0BHg==", "dev": true, - "peer": true, "dependencies": { - "undici-types": "~5.25.1" + "undici-types": "~5.26.4" } }, "node_modules/@types/semver": { @@ -1185,6 +1483,7 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", "dev": true, + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -1202,15 +1501,6 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/aggregate-error": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", @@ -1311,12 +1601,6 @@ "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==", "dev": true }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true - }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -1610,12 +1894,6 @@ "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", "dev": true }, - "node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true - }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -1736,6 +2014,43 @@ "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", "dev": true }, + "node_modules/esbuild": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", + "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.18.20", + "@esbuild/android-arm64": "0.18.20", + "@esbuild/android-x64": "0.18.20", + "@esbuild/darwin-arm64": "0.18.20", + "@esbuild/darwin-x64": "0.18.20", + "@esbuild/freebsd-arm64": "0.18.20", + "@esbuild/freebsd-x64": "0.18.20", + "@esbuild/linux-arm": "0.18.20", + "@esbuild/linux-arm64": "0.18.20", + "@esbuild/linux-ia32": "0.18.20", + "@esbuild/linux-loong64": "0.18.20", + "@esbuild/linux-mips64el": "0.18.20", + "@esbuild/linux-ppc64": "0.18.20", + "@esbuild/linux-riscv64": "0.18.20", + "@esbuild/linux-s390x": "0.18.20", + "@esbuild/linux-x64": "0.18.20", + "@esbuild/netbsd-x64": "0.18.20", + "@esbuild/openbsd-x64": "0.18.20", + "@esbuild/sunos-x64": "0.18.20", + "@esbuild/win32-arm64": "0.18.20", + "@esbuild/win32-ia32": "0.18.20", + "@esbuild/win32-x64": "0.18.20" + } + }, "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -2193,6 +2508,18 @@ "node": ">=8.0.0" } }, + "node_modules/get-tsconfig": { + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.2.tgz", + "integrity": "sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==", + "dev": true, + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, "node_modules/gh-pages": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-6.0.0.tgz", @@ -2872,12 +3199,6 @@ "semver": "bin/semver.js" } }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, "node_modules/marked": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", @@ -3633,6 +3954,15 @@ "node": ">=4" } }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -4021,56 +4351,21 @@ "typescript": ">=4.2.0" } }, - "node_modules/ts-node": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "node_modules/tsx": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-3.14.0.tgz", + "integrity": "sha512-xHtFaKtHxM9LOklMmJdI3BEnQq/D5F73Of2E1GDrITi9sgoVkvIsrQUTY1G8FlmGtA+awCI4EBlTRRYxkL2sRg==", "dev": true, "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" + "esbuild": "~0.18.20", + "get-tsconfig": "^4.7.2", + "source-map-support": "^0.5.21" }, "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" + "tsx": "dist/cli.mjs" }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } - } - }, - "node_modules/ts-node/node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "engines": { - "node": ">=0.3.1" + "optionalDependencies": { + "fsevents": "~2.3.3" } }, "node_modules/type-check": { @@ -4176,11 +4471,10 @@ } }, "node_modules/undici-types": { - "version": "5.25.3", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.25.3.tgz", - "integrity": "sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==", - "dev": true, - "peer": true + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true }, "node_modules/universalify": { "version": "2.0.0", @@ -4240,12 +4534,6 @@ "uuid": "dist/bin/uuid" } }, - "node_modules/v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true - }, "node_modules/vscode-oniguruma": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", @@ -4401,15 +4689,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/package.json b/package.json index 9bd08c7401..a3f3d3a8c4 100644 --- a/package.json +++ b/package.json @@ -12,16 +12,15 @@ }, "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.2", - "@tsconfig/node18": "^18.2.2", "@types/mocha": "^10.0.3", - "@typescript-eslint/eslint-plugin": "^6.9.0", - "@typescript-eslint/parser": "^6.9.0", + "@types/node": "^20.8.10", + "@typescript-eslint/eslint-plugin": "^6.9.1", + "@typescript-eslint/parser": "^6.9.1", "gh-pages": "^6.0.0", "mocha": "^10.2.0", "nyc": "^15.1.0", - "source-map-support": "^0.5.21", - "ts-node": "^10.9.1", - "typedoc": "^0.25.2", + "tsx": "^3.14.0", + "typedoc": "^0.25.3", "typescript": "^5.2.2" } } diff --git a/packages/bloom/lib/commands/bloom/RESERVE.ts b/packages/bloom/lib/commands/bloom/RESERVE.ts index c460253523..6bccb1d1d1 100644 --- a/packages/bloom/lib/commands/bloom/RESERVE.ts +++ b/packages/bloom/lib/commands/bloom/RESERVE.ts @@ -1,5 +1,4 @@ import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types'; -import { RedisVariadicArgument, pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers'; export interface BfReserveOptions { EXPANSION?: number; diff --git a/packages/bloom/lib/commands/cuckoo/DEL.ts b/packages/bloom/lib/commands/cuckoo/DEL.ts index 55cefb4a05..0af8ebc851 100644 --- a/packages/bloom/lib/commands/cuckoo/DEL.ts +++ b/packages/bloom/lib/commands/cuckoo/DEL.ts @@ -1,4 +1,4 @@ -import { RedisArgument, NumberReply, Command } from '@redis/client/dist/lib/RESP/types'; +import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types'; import { transformBooleanReply } from '@redis/client/dist/lib/commands/generic-transformers'; export default { diff --git a/packages/bloom/lib/commands/cuckoo/EXISTS.ts b/packages/bloom/lib/commands/cuckoo/EXISTS.ts index 1cb6b4df8f..8fd74ca47c 100644 --- a/packages/bloom/lib/commands/cuckoo/EXISTS.ts +++ b/packages/bloom/lib/commands/cuckoo/EXISTS.ts @@ -1,4 +1,4 @@ -import { RedisArgument, NumberReply, Command } from '@redis/client/dist/lib/RESP/types'; +import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types'; import { transformBooleanReply } from '@redis/client/dist/lib/commands/generic-transformers'; export default { diff --git a/packages/bloom/package.json b/packages/bloom/package.json index f87525225b..f76224f201 100644 --- a/packages/bloom/package.json +++ b/packages/bloom/package.json @@ -9,7 +9,7 @@ "!dist/tsconfig.tsbuildinfo" ], "scripts": { - "test": "nyc -r text-summary -r lcov mocha -r source-map-support/register -r ts-node/register './lib/**/*.spec.ts'" + "test": "nyc -r text-summary -r lcov mocha -r tsx './lib/**/*.spec.ts'" }, "peerDependencies": { "@redis/client": "*" diff --git a/packages/client/lib/RESP/types.ts b/packages/client/lib/RESP/types.ts index c4ad18e1a1..9f0e921734 100644 --- a/packages/client/lib/RESP/types.ts +++ b/packages/client/lib/RESP/types.ts @@ -210,11 +210,6 @@ export type ReplyWithTypeMapping< ) ); -type a = ReplyWithTypeMapping< - ArrayReply>, - {} ->; - export type TransformReply = (this: void, reply: any, preserve?: any) => any; // TODO; export type RedisArgument = string | Buffer; diff --git a/packages/client/lib/client/legacy-mode.ts b/packages/client/lib/client/legacy-mode.ts index 532c23fafb..555c4eaae5 100644 --- a/packages/client/lib/client/legacy-mode.ts +++ b/packages/client/lib/client/legacy-mode.ts @@ -1,4 +1,4 @@ -import { RedisModules, RedisFunctions, RedisScripts, RespVersions, TypeMapping, Command, CommandArguments, ReplyUnion } from '../RESP/types'; +import { RedisModules, RedisFunctions, RedisScripts, RespVersions, Command, CommandArguments, ReplyUnion } from '../RESP/types'; import { RedisClientType } from '.'; import { getTransformReply } from '../commander'; import { ErrorReply } from '../errors'; diff --git a/packages/client/lib/client/multi-command.ts b/packages/client/lib/client/multi-command.ts index 267444ad31..c078193f64 100644 --- a/packages/client/lib/client/multi-command.ts +++ b/packages/client/lib/client/multi-command.ts @@ -1,6 +1,6 @@ import COMMANDS from '../commands'; import RedisMultiCommand, { MULTI_REPLY, MultiReply, MultiReplyType } from '../multi-command'; -import { ReplyWithTypeMapping, CommandReply, Command, CommandArguments, CommanderConfig, RedisFunctions, RedisModules, RedisScripts, RespVersions, TransformReply, RedisScript, RedisFunction, TypeMapping, ReplyUnion } from '../RESP/types'; +import { ReplyWithTypeMapping, CommandReply, Command, CommandArguments, CommanderConfig, RedisFunctions, RedisModules, RedisScripts, RespVersions, TransformReply, RedisScript, RedisFunction, TypeMapping } from '../RESP/types'; import { attachConfig, functionArgumentsPrefix, getTransformReply } from '../commander'; import { RedisClientType } from '.'; diff --git a/packages/client/lib/cluster/cluster-slots.ts b/packages/client/lib/cluster/cluster-slots.ts index 79fd2e2aeb..6fc0af8c91 100644 --- a/packages/client/lib/cluster/cluster-slots.ts +++ b/packages/client/lib/cluster/cluster-slots.ts @@ -1,16 +1,10 @@ import { RedisClusterClientOptions, RedisClusterOptions } from '.'; import { RootNodesUnavailableError } from '../errors'; import RedisClient, { RedisClientOptions, RedisClientType } from '../client'; -import { types } from 'node:util'; import { EventEmitter } from 'node:stream'; import { ChannelListeners, PubSubType, PubSubTypeListeners } from '../client/pub-sub'; import { RedisArgument, RedisFunctions, RedisModules, RedisScripts, RespVersions, TypeMapping } from '../RESP/types'; - -// TODO: ?! -// We need to use 'require', because it's not possible with Typescript to import -// function that are exported as 'module.exports = function`, without esModuleInterop -// set to true. -const calculateSlot = require('cluster-key-slot'); +import calculateSlot from 'cluster-key-slot'; interface NodeAddress { host: string; diff --git a/packages/client/lib/cluster/multi-command.ts b/packages/client/lib/cluster/multi-command.ts index a0292356da..d036256247 100644 --- a/packages/client/lib/cluster/multi-command.ts +++ b/packages/client/lib/cluster/multi-command.ts @@ -1,6 +1,6 @@ import COMMANDS from '../commands'; import RedisMultiCommand, { MULTI_REPLY, MultiReply, MultiReplyType } from '../multi-command'; -import { ReplyWithTypeMapping, CommandReply, Command, CommandArguments, CommanderConfig, RedisFunctions, RedisModules, RedisScripts, RespVersions, TransformReply, RedisScript, RedisFunction, TypeMapping, ReplyUnion, RedisArgument } from '../RESP/types'; +import { ReplyWithTypeMapping, CommandReply, Command, CommandArguments, CommanderConfig, RedisFunctions, RedisModules, RedisScripts, RespVersions, TransformReply, RedisScript, RedisFunction, TypeMapping, RedisArgument } from '../RESP/types'; import { attachConfig, functionArgumentsPrefix, getTransformReply } from '../commander'; import RedisCluster, { RedisClusterType } from '.'; diff --git a/packages/client/lib/commands/CLIENT_TRACKINGINFO.spec.ts b/packages/client/lib/commands/CLIENT_TRACKINGINFO.spec.ts index 0921a9141f..1cefbd27d5 100644 --- a/packages/client/lib/commands/CLIENT_TRACKINGINFO.spec.ts +++ b/packages/client/lib/commands/CLIENT_TRACKINGINFO.spec.ts @@ -1,7 +1,6 @@ import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import CLIENT_TRACKINGINFO from './CLIENT_TRACKINGINFO'; -import { RESP_TYPES } from '../RESP/decoder'; describe('CLIENT TRACKINGINFO', () => { testUtils.isVersionGreaterThanHook([6, 2]); diff --git a/packages/client/lib/commands/FCALL.ts b/packages/client/lib/commands/FCALL.ts index 57b9f65231..ba371a81b1 100644 --- a/packages/client/lib/commands/FCALL.ts +++ b/packages/client/lib/commands/FCALL.ts @@ -1,5 +1,5 @@ import { Command } from '../RESP/types'; -import EVAL, { EvalOptions, transformEvalArguments } from './EVAL'; +import EVAL, { transformEvalArguments } from './EVAL'; export default { FIRST_KEY_INDEX: EVAL.FIRST_KEY_INDEX, diff --git a/packages/client/lib/commands/FCALL_RO.ts b/packages/client/lib/commands/FCALL_RO.ts index 700b25e5f7..ec002a79f8 100644 --- a/packages/client/lib/commands/FCALL_RO.ts +++ b/packages/client/lib/commands/FCALL_RO.ts @@ -1,5 +1,5 @@ import { Command } from '../RESP/types'; -import EVAL, { EvalOptions, transformEvalArguments } from './EVAL'; +import EVAL, { transformEvalArguments } from './EVAL'; export default { FIRST_KEY_INDEX: EVAL.FIRST_KEY_INDEX, diff --git a/packages/client/lib/commands/FUNCTION_LIST.ts b/packages/client/lib/commands/FUNCTION_LIST.ts index 8993496ca2..07c1ff2a00 100644 --- a/packages/client/lib/commands/FUNCTION_LIST.ts +++ b/packages/client/lib/commands/FUNCTION_LIST.ts @@ -1,4 +1,4 @@ -import { RedisArgument, TuplesToMapReply, BlobStringReply, ArrayReply, NullReply, SetReply, UnwrapReply, Resp2Reply, CommandArguments, Command, ReplyWithTypeMapping } from '../RESP/types'; +import { RedisArgument, TuplesToMapReply, BlobStringReply, ArrayReply, NullReply, SetReply, UnwrapReply, Resp2Reply, CommandArguments, Command } from '../RESP/types'; export interface FunctionListOptions { LIBRARYNAME?: RedisArgument; diff --git a/packages/client/lib/commands/GEORADIUSBYMEMBER_WITH.ts b/packages/client/lib/commands/GEORADIUSBYMEMBER_WITH.ts index 31480430b5..be9472a438 100644 --- a/packages/client/lib/commands/GEORADIUSBYMEMBER_WITH.ts +++ b/packages/client/lib/commands/GEORADIUSBYMEMBER_WITH.ts @@ -1,4 +1,4 @@ -import { RedisArgument, CommandArguments, ArrayReply, BlobStringReply, Command } from '../RESP/types'; +import { RedisArgument, CommandArguments, Command } from '../RESP/types'; import GEORADIUSBYMEMBER from './GEORADIUSBYMEMBER'; import { GeoSearchOptions, GeoUnits, pushGeoSearchOptions } from './GEOSEARCH'; import GEOSEARCH_WITH, { GeoReplyWith } from './GEOSEARCH_WITH'; diff --git a/packages/client/lib/commands/MEMORY_STATS.ts b/packages/client/lib/commands/MEMORY_STATS.ts index 38deae9013..2192d619ee 100644 --- a/packages/client/lib/commands/MEMORY_STATS.ts +++ b/packages/client/lib/commands/MEMORY_STATS.ts @@ -1,4 +1,4 @@ -import { TuplesToMapReply, BlobStringReply, NumberReply, DoubleReply, ArrayReply, UnwrapReply, Resp2Reply, Command } from '../RESP/types'; +import { TuplesToMapReply, BlobStringReply, NumberReply, DoubleReply, ArrayReply, UnwrapReply, Command } from '../RESP/types'; export type MemoryStatsReply = TuplesToMapReply<[ [BlobStringReply<'peak.allocated'>, NumberReply], diff --git a/packages/client/lib/commands/MODULE_LOAD.ts b/packages/client/lib/commands/MODULE_LOAD.ts index 293a18a03c..82c5b81a90 100644 --- a/packages/client/lib/commands/MODULE_LOAD.ts +++ b/packages/client/lib/commands/MODULE_LOAD.ts @@ -1,5 +1,4 @@ import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; -import { pushVariadicArguments } from './generic-transformers'; export default { FIRST_KEY_INDEX: undefined, diff --git a/packages/client/lib/commands/UNWATCH.ts b/packages/client/lib/commands/UNWATCH.ts index 9dd83b9aee..d12e9c2b94 100644 --- a/packages/client/lib/commands/UNWATCH.ts +++ b/packages/client/lib/commands/UNWATCH.ts @@ -1,4 +1,4 @@ -import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; +import { SimpleStringReply, Command } from '../RESP/types'; export default { FIRST_KEY_INDEX: undefined, diff --git a/packages/client/lib/commands/ZINCRBY.ts b/packages/client/lib/commands/ZINCRBY.ts index 3bb987d5f1..d9e4384501 100644 --- a/packages/client/lib/commands/ZINCRBY.ts +++ b/packages/client/lib/commands/ZINCRBY.ts @@ -1,4 +1,4 @@ -import { RedisArgument, DoubleReply, Command } from '../RESP/types'; +import { RedisArgument, Command } from '../RESP/types'; import { transformDoubleArgument, transformDoubleReply } from './generic-transformers'; export default { diff --git a/packages/client/lib/commands/ZSCAN.ts b/packages/client/lib/commands/ZSCAN.ts index 68186afc0e..853cdf098f 100644 --- a/packages/client/lib/commands/ZSCAN.ts +++ b/packages/client/lib/commands/ZSCAN.ts @@ -1,6 +1,6 @@ import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types'; import { ScanCommonOptions, pushScanArguments } from './SCAN'; -import { SortedSetMember, transformDoubleReply, transformSortedSetReply } from './generic-transformers'; +import { transformSortedSetReply } from './generic-transformers'; export interface HScanEntry { field: BlobStringReply; diff --git a/packages/client/lib/commands/generic-transformers.ts b/packages/client/lib/commands/generic-transformers.ts index 5b8aa12d7e..a96e79a9c5 100644 --- a/packages/client/lib/commands/generic-transformers.ts +++ b/packages/client/lib/commands/generic-transformers.ts @@ -1,4 +1,4 @@ -import { UnwrapReply, ArrayReply, BlobStringReply, BooleanReply, CommandArguments, DoubleReply, MapReply, NullReply, NumberReply, RedisArgument, TuplesReply, RespType } from '../RESP/types'; +import { UnwrapReply, ArrayReply, BlobStringReply, BooleanReply, CommandArguments, DoubleReply, NullReply, NumberReply, RedisArgument, TuplesReply } from '../RESP/types'; export function isNullReply(reply: unknown): reply is NullReply { return reply === null; diff --git a/packages/client/package.json b/packages/client/package.json index ed2e312842..5bea1dd5ff 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -9,7 +9,7 @@ "!dist/tsconfig.tsbuildinfo" ], "scripts": { - "test": "nyc -r text-summary -r lcov mocha -r source-map-support/register -r ts-node/register './lib/**/*.spec.ts'" + "test": "nyc -r text-summary -r lcov mocha -r tsx './lib/**/*.spec.ts'" }, "dependencies": { "cluster-key-slot": "1.1.2", diff --git a/packages/graph/lib/graph.ts b/packages/graph/lib/graph.ts index 8866052bda..72242d502b 100644 --- a/packages/graph/lib/graph.ts +++ b/packages/graph/lib/graph.ts @@ -1,4 +1,4 @@ -import { RedisClientType } from '@redis/client/dist/lib/client/index'; +import { RedisClientType } from '@redis/client'; import { RedisArgument, RedisFunctions, RedisScripts } from '@redis/client/dist/lib/RESP/types'; import QUERY, { QueryOptions } from './commands/QUERY'; @@ -132,7 +132,7 @@ type GraphReply = { type GraphClientType = RedisClientType<{ graph: { query: typeof QUERY, - roQuery: typeof import('./commands/RO_QUERY').default + roQuery: typeof import('./commands/RO_QUERY.js').default } }, RedisFunctions, RedisScripts>; diff --git a/packages/graph/package.json b/packages/graph/package.json index dd5533f1bc..c0851e5734 100644 --- a/packages/graph/package.json +++ b/packages/graph/package.json @@ -9,7 +9,7 @@ "!dist/tsconfig.tsbuildinfo" ], "scripts": { - "test": "nyc -r text-summary -r lcov mocha -r source-map-support/register -r ts-node/register './lib/**/*.spec.ts'" + "test": "nyc -r text-summary -r lcov mocha -r tsx './lib/**/*.spec.ts'" }, "peerDependencies": { "@redis/client": "*" diff --git a/packages/json/lib/commands/DEBUG_MEMORY.ts b/packages/json/lib/commands/DEBUG_MEMORY.ts index a96f05b806..c2e730b9dc 100644 --- a/packages/json/lib/commands/DEBUG_MEMORY.ts +++ b/packages/json/lib/commands/DEBUG_MEMORY.ts @@ -1,4 +1,4 @@ -import { RedisArgument, NumberReply, ArrayReply, Command } from '@redis/client/dist/lib/RESP/types'; +import { RedisArgument, NumberReply, Command } from '@redis/client/dist/lib/RESP/types'; export interface JsonDebugMemoryOptions { path?: RedisArgument; diff --git a/packages/json/package.json b/packages/json/package.json index 7acbfc3d8d..e52d12c9a9 100644 --- a/packages/json/package.json +++ b/packages/json/package.json @@ -8,7 +8,7 @@ "dist/" ], "scripts": { - "test": "nyc -r text-summary -r lcov mocha -r source-map-support/register -r ts-node/register './lib/**/*.spec.ts'" + "test": "nyc -r text-summary -r lcov mocha -r tsx './lib/**/*.spec.ts'" }, "peerDependencies": { "@redis/client": "*" diff --git a/packages/search/lib/commands/AGGREGATE.spec.ts b/packages/search/lib/commands/AGGREGATE.spec.ts index 08e8a87f23..c0b34997c6 100644 --- a/packages/search/lib/commands/AGGREGATE.spec.ts +++ b/packages/search/lib/commands/AGGREGATE.spec.ts @@ -1,509 +1,515 @@ import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { AggregateGroupByReducers, AggregateSteps, transformArguments } from './AGGREGATE'; -import { SchemaFieldTypes } from '.'; +import AGGREGATE from './AGGREGATE'; +// import { SchemaFieldTypes } from '.'; describe('AGGREGATE', () => { - describe('transformArguments', () => { - it('without options', () => { + describe('transformArguments', () => { + it('without options', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*'), + ['FT.AGGREGATE', 'index', '*'] + ); + }); + + it('with VERBATIM', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + VERBATIM: true + }), + ['FT.AGGREGATE', 'index', '*', 'VERBATIM'] + ); + }); + + describe('with LOAD', () => { + describe('single', () => { + describe('without alias', () => { + it('string', () => { assert.deepEqual( - transformArguments('index', '*'), - ['FT.AGGREGATE', 'index', '*'] + AGGREGATE.transformArguments('index', '*', { + LOAD: '@property' + }), + ['FT.AGGREGATE', 'index', '*', 'LOAD', '1', '@property'] ); + }); + + it('{ identifier: string }', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + LOAD: { + identifier: '@property' + } + }), + ['FT.AGGREGATE', 'index', '*', 'LOAD', '1', '@property'] + ); + }); }); - it('with VERBATIM', () => { - assert.deepEqual( - transformArguments('index', '*', { VERBATIM: true }), - ['FT.AGGREGATE', 'index', '*', 'VERBATIM'] - ); + it('with alias', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + LOAD: { + identifier: '@property', + AS: 'alias' + } + }), + ['FT.AGGREGATE', 'index', '*', 'LOAD', '3', '@property', 'AS', 'alias'] + ); }); + }); - describe('with LOAD', () => { - describe('single', () => { - describe('without alias', () => { - it('string', () => { - assert.deepEqual( - transformArguments('index', '*', { LOAD: '@property' }), - ['FT.AGGREGATE', 'index', '*', 'LOAD', '1', '@property'] - ); - }); + it('multiple', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + LOAD: ['@1', '@2'] + }), + ['FT.AGGREGATE', 'index', '*', 'LOAD', '2', '@1', '@2'] + ); + }); + }); - it('{ identifier: string }', () => { - assert.deepEqual( - transformArguments('index', '*', { - LOAD: { - identifier: '@property' - } - }), - ['FT.AGGREGATE', 'index', '*', 'LOAD', '1', '@property'] - ); - }); - }); + describe('with STEPS', () => { + describe('GROUPBY', () => { + describe('COUNT', () => { + describe('without properties', () => { + it('without alias', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'GROUPBY', + REDUCE: { + type: 'COUNT' + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'COUNT', '0'] + ); + }); - it('with alias', () => { - assert.deepEqual( - transformArguments('index', '*', { - LOAD: { - identifier: '@property', - AS: 'alias' - } - }), - ['FT.AGGREGATE', 'index', '*', 'LOAD', '3', '@property', 'AS', 'alias'] - ); - }); + it('with alias', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'GROUPBY', + REDUCE: { + type: 'COUNT', + AS: 'count' + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'COUNT', '0', 'AS', 'count'] + ); + }); + }); + + describe('with properties', () => { + it('single', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'GROUPBY', + properties: '@property', + REDUCE: { + type: 'COUNT' + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '1', '@property', 'REDUCE', 'COUNT', '0'] + ); }); it('multiple', () => { - assert.deepEqual( - transformArguments('index', '*', { LOAD: ['@1', '@2'] }), - ['FT.AGGREGATE', 'index', '*', 'LOAD', '2', '@1', '@2'] - ); - }); - }); - - describe('with STEPS', () => { - describe('GROUPBY', () => { - describe('COUNT', () => { - describe('without properties', () => { - it('without alias', () => { - assert.deepEqual( - transformArguments('index', '*', { - STEPS: [{ - type: AggregateSteps.GROUPBY, - REDUCE: { - type: AggregateGroupByReducers.COUNT - } - }] - }), - ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'COUNT', '0'] - ); - }); - - it('with alias', () => { - assert.deepEqual( - transformArguments('index', '*', { - STEPS: [{ - type: AggregateSteps.GROUPBY, - REDUCE: { - type: AggregateGroupByReducers.COUNT, - AS: 'count' - } - }] - }), - ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'COUNT', '0', 'AS', 'count'] - ); - }); - }); - - describe('with properties', () => { - it('single', () => { - assert.deepEqual( - transformArguments('index', '*', { - STEPS: [{ - type: AggregateSteps.GROUPBY, - properties: '@property', - REDUCE: { - type: AggregateGroupByReducers.COUNT - } - }] - }), - ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '1', '@property', 'REDUCE', 'COUNT', '0'] - ); - }); - - it('multiple', () => { - assert.deepEqual( - transformArguments('index', '*', { - STEPS: [{ - type: AggregateSteps.GROUPBY, - properties: ['@1', '@2'], - REDUCE: { - type: AggregateGroupByReducers.COUNT - } - }] - }), - ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '2', '@1', '@2', 'REDUCE', 'COUNT', '0'] - ); - }); - }); - }); - - it('COUNT_DISTINCT', () => { - assert.deepEqual( - transformArguments('index', '*', { - STEPS: [{ - type: AggregateSteps.GROUPBY, - REDUCE: { - type: AggregateGroupByReducers.COUNT_DISTINCT, - property: '@property' - } - }] - }), - ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'COUNT_DISTINCT', '1', '@property'] - ); - }); - - it('COUNT_DISTINCTISH', () => { - assert.deepEqual( - transformArguments('index', '*', { - STEPS: [{ - type: AggregateSteps.GROUPBY, - REDUCE: { - type: AggregateGroupByReducers.COUNT_DISTINCTISH, - property: '@property' - } - }] - }), - ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'COUNT_DISTINCTISH', '1', '@property'] - ); - }); - - it('SUM', () => { - assert.deepEqual( - transformArguments('index', '*', { - STEPS: [{ - type: AggregateSteps.GROUPBY, - REDUCE: { - type: AggregateGroupByReducers.SUM, - property: '@property' - } - }] - }), - ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'SUM', '1', '@property'] - ); - }); - - it('MIN', () => { - assert.deepEqual( - transformArguments('index', '*', { - STEPS: [{ - type: AggregateSteps.GROUPBY, - REDUCE: { - type: AggregateGroupByReducers.MIN, - property: '@property' - } - }] - }), - ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'MIN', '1', '@property'] - ); - }); - - it('MAX', () => { - assert.deepEqual( - transformArguments('index', '*', { - STEPS: [{ - type: AggregateSteps.GROUPBY, - REDUCE: { - type: AggregateGroupByReducers.MAX, - property: '@property' - } - }] - }), - ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'MAX', '1', '@property'] - ); - }); - - it('AVG', () => { - assert.deepEqual( - transformArguments('index', '*', { - STEPS: [{ - type: AggregateSteps.GROUPBY, - REDUCE: { - type: AggregateGroupByReducers.AVG, - property: '@property' - } - }] - }), - ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'AVG', '1', '@property'] - ); - }); - - it('STDDEV', () => { - assert.deepEqual( - transformArguments('index', '*', { - STEPS: [{ - type: AggregateSteps.GROUPBY, - REDUCE: { - type: AggregateGroupByReducers.STDDEV, - property: '@property' - } - }] - }), - ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'STDDEV', '1', '@property'] - ); - }); - - it('QUANTILE', () => { - assert.deepEqual( - transformArguments('index', '*', { - STEPS: [{ - type: AggregateSteps.GROUPBY, - REDUCE: { - type: AggregateGroupByReducers.QUANTILE, - property: '@property', - quantile: 0.5 - } - }] - }), - ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'QUANTILE', '2', '@property', '0.5'] - ); - }); - - it('TO_LIST', () => { - assert.deepEqual( - transformArguments('index', '*', { - STEPS: [{ - type: AggregateSteps.GROUPBY, - REDUCE: { - type: AggregateGroupByReducers.TO_LIST, - property: '@property' - } - }] - }), - ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'TOLIST', '1', '@property'] - ); - }); - - describe('FIRST_VALUE', () => { - it('simple', () => { - assert.deepEqual( - transformArguments('index', '*', { - STEPS: [{ - type: AggregateSteps.GROUPBY, - REDUCE: { - type: AggregateGroupByReducers.FIRST_VALUE, - property: '@property' - } - }] - }), - ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'FIRST_VALUE', '1', '@property'] - ); - }); - - describe('with BY', () => { - describe('without direction', () => { - it('string', () => { - assert.deepEqual( - transformArguments('index', '*', { - STEPS: [{ - type: AggregateSteps.GROUPBY, - REDUCE: { - type: AggregateGroupByReducers.FIRST_VALUE, - property: '@property', - BY: '@by' - } - }] - }), - ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'FIRST_VALUE', '3', '@property', 'BY', '@by'] - ); - }); - - - it('{ property: string }', () => { - assert.deepEqual( - transformArguments('index', '*', { - STEPS: [{ - type: AggregateSteps.GROUPBY, - REDUCE: { - type: AggregateGroupByReducers.FIRST_VALUE, - property: '@property', - BY: { - property: '@by' - } - } - }] - }), - ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'FIRST_VALUE', '3', '@property', 'BY', '@by'] - ); - }); - }); - - it('with direction', () => { - assert.deepEqual( - transformArguments('index', '*', { - STEPS: [{ - type: AggregateSteps.GROUPBY, - REDUCE: { - type: AggregateGroupByReducers.FIRST_VALUE, - property: '@property', - BY: { - property: '@by', - direction: 'ASC' - } - } - }] - }), - ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'FIRST_VALUE', '4', '@property', 'BY', '@by', 'ASC'] - ); - }); - }); - }); - - it('RANDOM_SAMPLE', () => { - assert.deepEqual( - transformArguments('index', '*', { - STEPS: [{ - type: AggregateSteps.GROUPBY, - REDUCE: { - type: AggregateGroupByReducers.RANDOM_SAMPLE, - property: '@property', - sampleSize: 1 - } - }] - }), - ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'RANDOM_SAMPLE', '2', '@property', '1'] - ); - }); - }); - - describe('SORTBY', () => { - it('string', () => { - assert.deepEqual( - transformArguments('index', '*', { - STEPS: [{ - type: AggregateSteps.SORTBY, - BY: '@by' - }] - }), - ['FT.AGGREGATE', 'index', '*', 'SORTBY', '1', '@by'] - ); - }); - - it('Array', () => { - assert.deepEqual( - transformArguments('index', '*', { - STEPS: [{ - type: AggregateSteps.SORTBY, - BY: ['@1', '@2'] - }] - }), - ['FT.AGGREGATE', 'index', '*', 'SORTBY', '2', '@1', '@2'] - ); - }); - - it('with MAX', () => { - assert.deepEqual( - transformArguments('index', '*', { - STEPS: [{ - type: AggregateSteps.SORTBY, - BY: '@by', - MAX: 1 - }] - }), - ['FT.AGGREGATE', 'index', '*', 'SORTBY', '1', '@by', 'MAX', '1'] - ); - }); - }); - - describe('APPLY', () => { - assert.deepEqual( - transformArguments('index', '*', { - STEPS: [{ - type: AggregateSteps.APPLY, - expression: '@field + 1', - AS: 'as' - }] - }), - ['FT.AGGREGATE', 'index', '*', 'APPLY', '@field + 1', 'AS', 'as'] - ); - }); - - describe('LIMIT', () => { - assert.deepEqual( - transformArguments('index', '*', { - STEPS: [{ - type: AggregateSteps.LIMIT, - from: 0, - size: 1 - }] - }), - ['FT.AGGREGATE', 'index', '*', 'LIMIT', '0', '1'] - ); - }); - - describe('FILTER', () => { - assert.deepEqual( - transformArguments('index', '*', { - STEPS: [{ - type: AggregateSteps.FILTER, - expression: '@field != ""' - }] - }), - ['FT.AGGREGATE', 'index', '*', 'FILTER', '@field != ""'] - ); - }); - }); - - it('with PARAMS', () => { - assert.deepEqual( - transformArguments('index', '*', { - PARAMS: { - param: 'value' + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'GROUPBY', + properties: ['@1', '@2'], + REDUCE: { + type: 'COUNT' } + }] }), - ['FT.AGGREGATE', 'index', '*', 'PARAMS', '2', 'param', 'value'] - ); + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '2', '@1', '@2', 'REDUCE', 'COUNT', '0'] + ); + }); + }); }); - it('with DIALECT', () => { - assert.deepEqual( - transformArguments('index', '*', { - DIALECT: 1 - }), - ['FT.AGGREGATE', 'index', '*', 'DIALECT', '1'] - ); + it('COUNT_DISTINCT', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'GROUPBY', + REDUCE: { + type: 'COUNT_DISTINCT', + property: '@property' + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'COUNT_DISTINCT', '1', '@property'] + ); }); - it('with TIMEOUT', () => { - assert.deepEqual( - transformArguments('index', '*', { TIMEOUT: 10 }), - ['FT.AGGREGATE', 'index', '*', 'TIMEOUT', '10'] - ); + it('COUNT_DISTINCTISH', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'GROUPBY', + REDUCE: { + type: 'COUNT_DISTINCTISH', + property: '@property' + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'COUNT_DISTINCTISH', '1', '@property'] + ); }); + + it('SUM', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'GROUPBY', + REDUCE: { + type: 'SUM', + property: '@property' + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'SUM', '1', '@property'] + ); + }); + + it('MIN', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'GROUPBY', + REDUCE: { + type: 'MIN', + property: '@property' + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'MIN', '1', '@property'] + ); + }); + + it('MAX', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'GROUPBY', + REDUCE: { + type: 'MAX', + property: '@property' + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'MAX', '1', '@property'] + ); + }); + + it('AVG', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'GROUPBY', + REDUCE: { + type: 'AVG', + property: '@property' + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'AVG', '1', '@property'] + ); + }); + + it('STDDEV', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'GROUPBY', + REDUCE: { + type: 'STDDEV', + property: '@property' + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'STDDEV', '1', '@property'] + ); + }); + + it('QUANTILE', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'GROUPBY', + REDUCE: { + type: 'QUANTILE', + property: '@property', + quantile: 0.5 + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'QUANTILE', '2', '@property', '0.5'] + ); + }); + + it('TOLIST', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'GROUPBY', + REDUCE: { + type: 'TOLIST', + property: '@property' + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'TOLIST', '1', '@property'] + ); + }); + + describe('FIRST_VALUE', () => { + it('simple', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'GROUPBY', + REDUCE: { + type: 'FIRST_VALUE', + property: '@property' + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'FIRST_VALUE', '1', '@property'] + ); + }); + + describe('with BY', () => { + describe('without direction', () => { + it('string', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'GROUPBY', + REDUCE: { + type: 'FIRST_VALUE', + property: '@property', + BY: '@by' + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'FIRST_VALUE', '3', '@property', 'BY', '@by'] + ); + }); + + + it('{ property: string }', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'GROUPBY', + REDUCE: { + type: 'FIRST_VALUE', + property: '@property', + BY: { + property: '@by' + } + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'FIRST_VALUE', '3', '@property', 'BY', '@by'] + ); + }); + }); + + it('with direction', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'GROUPBY', + REDUCE: { + type: 'FIRST_VALUE', + property: '@property', + BY: { + property: '@by', + direction: 'ASC' + } + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'FIRST_VALUE', '4', '@property', 'BY', '@by', 'ASC'] + ); + }); + }); + }); + + it('RANDOM_SAMPLE', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'GROUPBY', + REDUCE: { + type: 'RANDOM_SAMPLE', + property: '@property', + sampleSize: 1 + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'RANDOM_SAMPLE', '2', '@property', '1'] + ); + }); + }); + + describe('SORTBY', () => { + it('string', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'SORTBY', + BY: '@by' + }] + }), + ['FT.AGGREGATE', 'index', '*', 'SORTBY', '1', '@by'] + ); + }); + + it('Array', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'SORTBY', + BY: ['@1', '@2'] + }] + }), + ['FT.AGGREGATE', 'index', '*', 'SORTBY', '2', '@1', '@2'] + ); + }); + + it('with MAX', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'SORTBY', + BY: '@by', + MAX: 1 + }] + }), + ['FT.AGGREGATE', 'index', '*', 'SORTBY', '1', '@by', 'MAX', '1'] + ); + }); + }); + + describe('APPLY', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'APPLY', + expression: '@field + 1', + AS: 'as' + }] + }), + ['FT.AGGREGATE', 'index', '*', 'APPLY', '@field + 1', 'AS', 'as'] + ); + }); + + describe('LIMIT', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'LIMIT', + from: 0, + size: 1 + }] + }), + ['FT.AGGREGATE', 'index', '*', 'LIMIT', '0', '1'] + ); + }); + + describe('FILTER', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'FILTER', + expression: '@field != ""' + }] + }), + ['FT.AGGREGATE', 'index', '*', 'FILTER', '@field != ""'] + ); + }); }); - testUtils.testWithClient('client.ft.aggregate', async client => { - await Promise.all([ - client.ft.create('index', { - field: SchemaFieldTypes.NUMERIC - }), - client.hSet('1', 'field', '1'), - client.hSet('2', 'field', '2') - ]); + it('with PARAMS', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + PARAMS: { + param: 'value' + } + }), + ['FT.AGGREGATE', 'index', '*', 'PARAMS', '2', 'param', 'value'] + ); + }); - assert.deepEqual( - await client.ft.aggregate('index', '*', { - STEPS: [{ - type: AggregateSteps.GROUPBY, - REDUCE: [{ - type: AggregateGroupByReducers.SUM, - property: '@field', - AS: 'sum' - }, { - type: AggregateGroupByReducers.AVG, - property: '@field', - AS: 'avg' - }] - }] - }), - { - total: 1, - results: [ - Object.create(null, { - sum: { - value: '3', - configurable: true, - enumerable: true - }, - avg: { - value: '1.5', - configurable: true, - enumerable: true - } - }) - ] + it('with DIALECT', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + DIALECT: 1 + }), + ['FT.AGGREGATE', 'index', '*', 'DIALECT', '1'] + ); + }); + + it('with TIMEOUT', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { TIMEOUT: 10 }), + ['FT.AGGREGATE', 'index', '*', 'TIMEOUT', '10'] + ); + }); + }); + + testUtils.testWithClient('client.ft.aggregate', async client => { + await Promise.all([ + client.ft.create('index', { + field: 'NUMERIC' + }), + client.hSet('1', 'field', '1'), + client.hSet('2', 'field', '2') + ]); + + assert.deepEqual( + await client.ft.aggregate('index', '*', { + STEPS: [{ + type: 'GROUPBY', + REDUCE: [{ + type: 'SUM', + property: '@field', + AS: 'sum' + }, { + type: 'AVG', + property: '@field', + AS: 'avg' + }] + }] + }), + { + total: 1, + results: [ + Object.create(null, { + sum: { + value: '3', + configurable: true, + enumerable: true + }, + avg: { + value: '1.5', + configurable: true, + enumerable: true } - ); - }, GLOBAL.SERVERS.OPEN); + }) + ] + } + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/search/lib/commands/AGGREGATE.ts b/packages/search/lib/commands/AGGREGATE.ts index 6739581538..c21f1ce2a5 100644 --- a/packages/search/lib/commands/AGGREGATE.ts +++ b/packages/search/lib/commands/AGGREGATE.ts @@ -1,311 +1,294 @@ -import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; -import { pushVariadicArgument, transformTuplesReply } from '@redis/client/dist/lib/commands/generic-transformers'; -import { Params, PropertyName, pushArgumentsWithLength, pushParamsArgs, pushSortByArguments, SortByProperty } from '.'; +import { Command, RedisArgument } from '@redis/client/dist/lib/RESP/types'; +import { RediSearchProperty } from './CREATE'; +import { FtSearchParams, pushParamsArgument } from './SEARCH'; +import { pushVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers'; -export enum AggregateSteps { - GROUPBY = 'GROUPBY', - SORTBY = 'SORTBY', - APPLY = 'APPLY', - LIMIT = 'LIMIT', - FILTER = 'FILTER' +type LoadField = RediSearchProperty | { + identifier: RediSearchProperty; + AS?: RedisArgument; } -interface AggregateStep { - type: T; +export const FT_AGGREGATE_STEPS = { + GROUPBY: 'GROUPBY', + SORTBY: 'SORTBY', + APPLY: 'APPLY', + LIMIT: 'LIMIT', + FILTER: 'FILTER' +} as const; + +type FT_AGGREGATE_STEPS = typeof FT_AGGREGATE_STEPS; + +export type FtAggregateStep = FT_AGGREGATE_STEPS[keyof FT_AGGREGATE_STEPS]; + +interface AggregateStep { + type: T; } -export enum AggregateGroupByReducers { - COUNT = 'COUNT', - COUNT_DISTINCT = 'COUNT_DISTINCT', - COUNT_DISTINCTISH = 'COUNT_DISTINCTISH', - SUM = 'SUM', - MIN = 'MIN', - MAX = 'MAX', - AVG = 'AVG', - STDDEV = 'STDDEV', - QUANTILE = 'QUANTILE', - TOLIST = 'TOLIST', - TO_LIST = 'TOLIST', - FIRST_VALUE = 'FIRST_VALUE', - RANDOM_SAMPLE = 'RANDOM_SAMPLE' +export const FT_AGGREGATE_GROUP_BY_REDUCERS = { + COUNT: 'COUNT', + COUNT_DISTINCT: 'COUNT_DISTINCT', + COUNT_DISTINCTISH: 'COUNT_DISTINCTISH', + SUM: 'SUM', + MIN: 'MIN', + MAX: 'MAX', + AVG: 'AVG', + STDDEV: 'STDDEV', + QUANTILE: 'QUANTILE', + TOLIST: 'TOLIST', + FIRST_VALUE: 'FIRST_VALUE', + RANDOM_SAMPLE: 'RANDOM_SAMPLE' +} as const; + +type FT_AGGREGATE_GROUP_BY_REDUCERS = typeof FT_AGGREGATE_GROUP_BY_REDUCERS; + +export type FtAggregateGroupByReducer = FT_AGGREGATE_GROUP_BY_REDUCERS[keyof FT_AGGREGATE_GROUP_BY_REDUCERS]; + +interface GroupByReducer { + type: T; + AS?: RedisArgument; } -interface GroupByReducer { - type: T; - AS?: string; +interface GroupByReducerWithProperty extends GroupByReducer { + property: RediSearchProperty; } -type CountReducer = GroupByReducer; +type CountReducer = GroupByReducer; -interface CountDistinctReducer extends GroupByReducer { - property: PropertyName; +type CountDistinctReducer = GroupByReducerWithProperty; + +type CountDistinctishReducer = GroupByReducerWithProperty; + +type SumReducer = GroupByReducerWithProperty; + +type MinReducer = GroupByReducerWithProperty; + +type MaxReducer = GroupByReducerWithProperty; + +type AvgReducer = GroupByReducerWithProperty; + +type StdDevReducer = GroupByReducerWithProperty; + +interface QuantileReducer extends GroupByReducerWithProperty { + quantile: number; } -interface CountDistinctishReducer extends GroupByReducer { - property: PropertyName; +type ToListReducer = GroupByReducerWithProperty; + +interface FirstValueReducer extends GroupByReducerWithProperty { + BY?: RediSearchProperty | { + property: RediSearchProperty; + direction?: 'ASC' | 'DESC'; + }; } -interface SumReducer extends GroupByReducer { - property: PropertyName; -} - -interface MinReducer extends GroupByReducer { - property: PropertyName; -} - -interface MaxReducer extends GroupByReducer { - property: PropertyName; -} - -interface AvgReducer extends GroupByReducer { - property: PropertyName; -} - -interface StdDevReducer extends GroupByReducer { - property: PropertyName; -} - -interface QuantileReducer extends GroupByReducer { - property: PropertyName; - quantile: number; -} - -interface ToListReducer extends GroupByReducer { - property: PropertyName; -} - -interface FirstValueReducer extends GroupByReducer { - property: PropertyName; - BY?: PropertyName | { - property: PropertyName; - direction?: 'ASC' | 'DESC'; - }; -} - -interface RandomSampleReducer extends GroupByReducer { - property: PropertyName; - sampleSize: number; +interface RandomSampleReducer extends GroupByReducerWithProperty { + sampleSize: number; } type GroupByReducers = CountReducer | CountDistinctReducer | CountDistinctishReducer | SumReducer | MinReducer | MaxReducer | AvgReducer | StdDevReducer | QuantileReducer | ToListReducer | FirstValueReducer | RandomSampleReducer; -interface GroupByStep extends AggregateStep { - properties?: PropertyName | Array; - REDUCE: GroupByReducers | Array; +interface GroupByStep extends AggregateStep { + properties?: RediSearchProperty | Array; + REDUCE: GroupByReducers | Array; } -interface SortStep extends AggregateStep { - BY: SortByProperty | Array; - MAX?: number; +type SortByProperty = RedisArgument | { + BY: RediSearchProperty; + DIRECTION?: 'ASC' | 'DESC'; +}; + +interface SortStep extends AggregateStep { + BY: SortByProperty | Array; + MAX?: number; } -interface ApplyStep extends AggregateStep { - expression: string; - AS: string; +interface ApplyStep extends AggregateStep { + expression: RedisArgument; + AS: RedisArgument; } -interface LimitStep extends AggregateStep { - from: number; - size: number; +interface LimitStep extends AggregateStep { + from: number; + size: number; } -interface FilterStep extends AggregateStep { - expression: string; +interface FilterStep extends AggregateStep { + expression: RedisArgument; } -type LoadField = PropertyName | { - identifier: PropertyName; - AS?: string; +export interface FtAggregateOptions { + VERBATIM?: boolean; + LOAD?: LoadField | Array; + TIMEOUT?: number; + STEPS?: Array; + PARAMS?: FtSearchParams; + DIALECT?: number; } -export interface AggregateOptions { - VERBATIM?: true; - LOAD?: LoadField | Array; - STEPS?: Array; - PARAMS?: Params; - DIALECT?: number; - TIMEOUT?: number; -} +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: false, + transformArguments(index: RedisArgument, query: RedisArgument, options?: FtAggregateOptions) { + const args = ['FT.AGGREGATE', index, query]; -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments( - index: string, - query: string, - options?: AggregateOptions -): RedisCommandArguments { - return pushAggregatehOptions( - ['FT.AGGREGATE', index, query], - options - ); -} - -export function pushAggregatehOptions( - args: RedisCommandArguments, - options?: AggregateOptions -): RedisCommandArguments { if (options?.VERBATIM) { - args.push('VERBATIM'); + args.push('VERBATIM'); } if (options?.LOAD) { - args.push('LOAD'); - pushArgumentsWithLength(args, () => { - if (Array.isArray(options.LOAD)) { - for (const load of options.LOAD) { - pushLoadField(args, load); - } - } else { - pushLoadField(args, options.LOAD!); - } - }); - } + const length = args.push('LOAD', ''); - if (options?.STEPS) { - for (const step of options.STEPS) { - switch (step.type) { - case AggregateSteps.GROUPBY: - args.push('GROUPBY'); - if (!step.properties) { - args.push('0'); - } else { - pushVariadicArgument(args, step.properties); - } - - if (Array.isArray(step.REDUCE)) { - for (const reducer of step.REDUCE) { - pushGroupByReducer(args, reducer); - } - } else { - pushGroupByReducer(args, step.REDUCE); - } - - break; - - case AggregateSteps.SORTBY: - pushSortByArguments(args, 'SORTBY', step.BY); - - if (step.MAX) { - args.push('MAX', step.MAX.toString()); - } - - break; - - case AggregateSteps.APPLY: - args.push('APPLY', step.expression, 'AS', step.AS); - break; - - case AggregateSteps.LIMIT: - args.push('LIMIT', step.from.toString(), step.size.toString()); - break; - - case AggregateSteps.FILTER: - args.push('FILTER', step.expression); - break; - } + if (Array.isArray(options.LOAD)) { + for (const load of options.LOAD) { + pushLoadField(args, load); } - } + } else { + pushLoadField(args, options.LOAD); + } - pushParamsArgs(args, options?.PARAMS); - - if (options?.DIALECT) { - args.push('DIALECT', options.DIALECT.toString()); + args[length - 1] = (args.length - length).toString(); } if (options?.TIMEOUT !== undefined) { - args.push('TIMEOUT', options.TIMEOUT.toString()); + args.push('TIMEOUT', options.TIMEOUT.toString()); + } + + if (options?.STEPS) { + for (const step of options.STEPS) { + args.push(step.type); + switch (step.type) { + case FT_AGGREGATE_STEPS.GROUPBY: + if (!step.properties) { + args.push('0'); + } else { + pushVariadicArgument(args, step.properties); + } + + if (Array.isArray(step.REDUCE)) { + for (const reducer of step.REDUCE) { + pushGroupByReducer(args, reducer); + } + } else { + pushGroupByReducer(args, step.REDUCE); + } + + break; + + case FT_AGGREGATE_STEPS.SORTBY: + const length = args.push(''); + + if (Array.isArray(step.BY)) { + for (const by of step.BY) { + pushSortByProperty(args, by); + } + } else { + pushSortByProperty(args, step.BY); + } + + if (step.MAX) { + args.push('MAX', step.MAX.toString()); + } + + args[length - 1] = (args.length - length).toString(); + + break; + + case FT_AGGREGATE_STEPS.APPLY: + args.push('APPLY', step.expression, 'AS', step.AS); + break; + + case FT_AGGREGATE_STEPS.LIMIT: + args.push('LIMIT', step.from.toString(), step.size.toString()); + break; + + case FT_AGGREGATE_STEPS.FILTER: + args.push('FILTER', step.expression); + break; + } + } + } + + pushParamsArgument(args, options?.PARAMS); + + if (options?.DIALECT !== undefined) { + args.push('DIALECT', options.DIALECT.toString()); } return args; + }, + transformReply: undefined as unknown as () => any +} as const satisfies Command; + +function pushLoadField(args: Array, toLoad: LoadField) { + if (typeof toLoad === 'string' || toLoad instanceof Buffer) { + args.push(toLoad); + } else { + args.push(toLoad.identifier); + + if (toLoad.AS) { + args.push('AS', toLoad.AS); + } + } } -function pushLoadField(args: RedisCommandArguments, toLoad: LoadField): void { - if (typeof toLoad === 'string') { - args.push(toLoad); - } else { - args.push(toLoad.identifier); +function pushGroupByReducer(args: Array, reducer: GroupByReducers) { + args.push('REDUCE', reducer.type); - if (toLoad.AS) { - args.push('AS', toLoad.AS); + switch (reducer.type) { + case FT_AGGREGATE_GROUP_BY_REDUCERS.COUNT: + args.push('0'); + break; + + case FT_AGGREGATE_GROUP_BY_REDUCERS.COUNT_DISTINCT: + case FT_AGGREGATE_GROUP_BY_REDUCERS.COUNT_DISTINCTISH: + case FT_AGGREGATE_GROUP_BY_REDUCERS.SUM: + case FT_AGGREGATE_GROUP_BY_REDUCERS.MIN: + case FT_AGGREGATE_GROUP_BY_REDUCERS.MAX: + case FT_AGGREGATE_GROUP_BY_REDUCERS.AVG: + case FT_AGGREGATE_GROUP_BY_REDUCERS.STDDEV: + case FT_AGGREGATE_GROUP_BY_REDUCERS.TOLIST: + args.push('1', reducer.property); + break; + + case FT_AGGREGATE_GROUP_BY_REDUCERS.QUANTILE: + args.push('2', reducer.property, reducer.quantile.toString()); + break; + + case FT_AGGREGATE_GROUP_BY_REDUCERS.FIRST_VALUE: { + const length = args.push('', reducer.property) - 1; + if (reducer.BY) { + args.push('BY'); + if (typeof reducer.BY === 'string' || reducer.BY instanceof Buffer) { + args.push(reducer.BY); + } else { + args.push(reducer.BY.property); + if (reducer.BY.direction) { + args.push(reducer.BY.direction); + } } + } + + args[length - 1] = (args.length - length).toString(); + break; } + + case FT_AGGREGATE_GROUP_BY_REDUCERS.RANDOM_SAMPLE: + args.push('2', reducer.property, reducer.sampleSize.toString()); + break; + } + + if (reducer.AS) { + args.push('AS', reducer.AS); + } } -function pushGroupByReducer(args: RedisCommandArguments, reducer: GroupByReducers): void { - args.push('REDUCE', reducer.type); - - switch (reducer.type) { - case AggregateGroupByReducers.COUNT: - args.push('0'); - break; - - case AggregateGroupByReducers.COUNT_DISTINCT: - case AggregateGroupByReducers.COUNT_DISTINCTISH: - case AggregateGroupByReducers.SUM: - case AggregateGroupByReducers.MIN: - case AggregateGroupByReducers.MAX: - case AggregateGroupByReducers.AVG: - case AggregateGroupByReducers.STDDEV: - case AggregateGroupByReducers.TOLIST: - args.push('1', reducer.property); - break; - - case AggregateGroupByReducers.QUANTILE: - args.push('2', reducer.property, reducer.quantile.toString()); - break; - - case AggregateGroupByReducers.FIRST_VALUE: { - pushArgumentsWithLength(args, () => { - args.push(reducer.property); - - if (reducer.BY) { - args.push('BY'); - if (typeof reducer.BY === 'string') { - args.push(reducer.BY); - } else { - args.push(reducer.BY.property); - - if (reducer.BY.direction) { - args.push(reducer.BY.direction); - } - } - } - }); - break; - } - - case AggregateGroupByReducers.RANDOM_SAMPLE: - args.push('2', reducer.property, reducer.sampleSize.toString()); - break; - } - - if (reducer.AS) { - args.push('AS', reducer.AS); +function pushSortByProperty(args: Array, sortBy: SortByProperty) { + if (typeof sortBy === 'string' || sortBy instanceof Buffer) { + args.push(sortBy); + } else { + args.push(sortBy.BY); + if (sortBy.DIRECTION) { + args.push(sortBy.DIRECTION); } + } } - -export type AggregateRawReply = [ - total: number, - ...results: Array> -]; - -export interface AggregateReply { - total: number; - results: Array>; -} - -export function transformReply(rawReply: AggregateRawReply): AggregateReply { - const results: Array> = []; - for (let i = 1; i < rawReply.length; i++) { - results.push( - transformTuplesReply(rawReply[i] as Array) - ); - } - - return { - total: rawReply[0], - results - }; -} \ No newline at end of file diff --git a/packages/search/lib/commands/AGGREGATE_WITHCURSOR.spec.ts b/packages/search/lib/commands/AGGREGATE_WITHCURSOR.spec.ts index bd60965e7d..9db3d945f9 100644 --- a/packages/search/lib/commands/AGGREGATE_WITHCURSOR.spec.ts +++ b/packages/search/lib/commands/AGGREGATE_WITHCURSOR.spec.ts @@ -1,37 +1,47 @@ import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './AGGREGATE_WITHCURSOR'; -import { SchemaFieldTypes } from '.'; +import AGGREGATE_WITHCURSOR from './AGGREGATE_WITHCURSOR'; describe('AGGREGATE WITHCURSOR', () => { - describe('transformArguments', () => { - it('without options', () => { - assert.deepEqual( - transformArguments('index', '*'), - ['FT.AGGREGATE', 'index', '*', 'WITHCURSOR'] - ); - }); - - it('with COUNT', () => { - assert.deepEqual( - transformArguments('index', '*', { COUNT: 1 }), - ['FT.AGGREGATE', 'index', '*', 'WITHCURSOR', 'COUNT', '1'] - ); - }); + describe('transformArguments', () => { + it('without options', () => { + assert.deepEqual( + AGGREGATE_WITHCURSOR.transformArguments('index', '*'), + ['FT.AGGREGATE', 'index', '*', 'WITHCURSOR'] + ); }); - testUtils.testWithClient('client.ft.aggregateWithCursor', async client => { - await client.ft.create('index', { - field: SchemaFieldTypes.NUMERIC - }); + it('with COUNT', () => { + assert.deepEqual( + AGGREGATE_WITHCURSOR.transformArguments('index', '*', { + COUNT: 1 + }), + ['FT.AGGREGATE', 'index', '*', 'WITHCURSOR', 'COUNT', '1'] + ); + }); - assert.deepEqual( - await client.ft.aggregateWithCursor('index', '*'), - { - total: 0, - results: [], - cursor: 0 - } - ); - }, GLOBAL.SERVERS.OPEN); + it('with MAXIDLE', () => { + assert.deepEqual( + AGGREGATE_WITHCURSOR.transformArguments('index', '*', { + MAXIDLE: 1 + }), + ['FT.AGGREGATE', 'index', '*', 'WITHCURSOR', 'MAXIDLE', '1'] + ); + }); + }); + + testUtils.testWithClient('client.ft.aggregateWithCursor', async client => { + await client.ft.create('index', { + field: 'NUMERIC' + }); + + assert.deepEqual( + await client.ft.aggregateWithCursor('index', '*'), + { + total: 0, + results: [], + cursor: 0 + } + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/search/lib/commands/AGGREGATE_WITHCURSOR.ts b/packages/search/lib/commands/AGGREGATE_WITHCURSOR.ts index 63f6ee8f18..6591d4620f 100644 --- a/packages/search/lib/commands/AGGREGATE_WITHCURSOR.ts +++ b/packages/search/lib/commands/AGGREGATE_WITHCURSOR.ts @@ -1,44 +1,73 @@ -import { - AggregateOptions, - AggregateRawReply, - AggregateReply, - transformArguments as transformAggregateArguments, - transformReply as transformAggregateReply -} from './AGGREGATE'; +// import { +// AggregateOptions, +// AggregateRawReply, +// AggregateReply, +// transformArguments as transformAggregateArguments, +// transformReply as transformAggregateReply +// } from './AGGREGATE'; -export { FIRST_KEY_INDEX, IS_READ_ONLY } from './AGGREGATE'; +// export { FIRST_KEY_INDEX, IS_READ_ONLY } from './AGGREGATE'; -interface AggregateWithCursorOptions extends AggregateOptions { - COUNT?: number; +// interface AggregateWithCursorOptions extends AggregateOptions { +// COUNT?: number; +// } + +// export function transformArguments( +// index: string, +// query: string, +// options?: AggregateWithCursorOptions +// ) { +// const args = transformAggregateArguments(index, query, options); + +// args.push('WITHCURSOR'); +// if (options?.COUNT) { +// args.push('COUNT', options.COUNT.toString()); +// } + +// return args; +// } + +// type AggregateWithCursorRawReply = [ +// result: AggregateRawReply, +// cursor: number +// ]; + +// interface AggregateWithCursorReply extends AggregateReply { +// cursor: number; +// } + +// export function transformReply(reply: AggregateWithCursorRawReply): AggregateWithCursorReply { +// return { +// ...transformAggregateReply(reply[0]), +// cursor: reply[1] +// }; +// } + +import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types'; +import AGGREGATE, { FtAggregateOptions } from './AGGREGATE'; + +export interface FtAggregateWithCursorOptions extends FtAggregateOptions { + COUNT?: number; + MAXIDLE?: number; } -export function transformArguments( - index: string, - query: string, - options?: AggregateWithCursorOptions -) { - const args = transformAggregateArguments(index, query, options); - +export default { + FIRST_KEY_INDEX: AGGREGATE.FIRST_KEY_INDEX, + IS_READ_ONLY: AGGREGATE.IS_READ_ONLY, + transformArguments(index: RedisArgument, query: RedisArgument, options?: FtAggregateWithCursorOptions) { + const args = AGGREGATE.transformArguments(index, query, options); args.push('WITHCURSOR'); - if (options?.COUNT) { - args.push('COUNT', options.COUNT.toString()); + + if (options?.COUNT !== undefined) { + args.push('COUNT', options.COUNT.toString()); + } + + if(options?.MAXIDLE !== undefined) { + args.push('MAXIDLE', options.MAXIDLE.toString()); } return args; -} + }, + transformReply: undefined as unknown as () => any +} as const satisfies Command; -type AggregateWithCursorRawReply = [ - result: AggregateRawReply, - cursor: number -]; - -interface AggregateWithCursorReply extends AggregateReply { - cursor: number; -} - -export function transformReply(reply: AggregateWithCursorRawReply): AggregateWithCursorReply { - return { - ...transformAggregateReply(reply[0]), - cursor: reply[1] - }; -} diff --git a/packages/search/lib/commands/CREATE.ts b/packages/search/lib/commands/CREATE.ts index ea63873be4..f6b66085f2 100644 --- a/packages/search/lib/commands/CREATE.ts +++ b/packages/search/lib/commands/CREATE.ts @@ -1,6 +1,5 @@ import { RedisArgument, SimpleStringReply, Command, CommandArguments } from '@redis/client/dist/lib/RESP/types'; import { RedisVariadicArgument, pushOptionalVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers'; -import { PropertyName } from '.'; export const SCHEMA_FIELD_TYPE = { TEXT: 'TEXT', @@ -257,14 +256,16 @@ export const REDISEARCH_LANGUAGE = { export type RediSearchLanguage = typeof REDISEARCH_LANGUAGE[keyof typeof REDISEARCH_LANGUAGE]; +export type RediSearchProperty = `${'@' | '$.'}${string}`; + export interface CreateOptions { ON?: 'HASH' | 'JSON'; PREFIX?: RedisVariadicArgument; FILTER?: RedisArgument; LANGUAGE?: RediSearchLanguage; - LANGUAGE_FIELD?: PropertyName; + LANGUAGE_FIELD?: RediSearchProperty; SCORE?: number; - SCORE_FIELD?: PropertyName; + SCORE_FIELD?: RediSearchProperty; // PAYLOAD_FIELD?: string; MAXTEXTFIELDS?: boolean; TEMPORARY?: number; diff --git a/packages/search/lib/commands/SEARCH.spec.ts b/packages/search/lib/commands/SEARCH.spec.ts index d3d9bf9ae3..257dbb7951 100644 --- a/packages/search/lib/commands/SEARCH.spec.ts +++ b/packages/search/lib/commands/SEARCH.spec.ts @@ -1,300 +1,327 @@ import { strict as assert } from 'node:assert'; -import { RedisSearchLanguages, SchemaFieldTypes } from '.'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './SEARCH'; +import SEARCH from './SEARCH'; -describe('SEARCH', () => { - describe('transformArguments', () => { - it('without options', () => { - assert.deepEqual( - transformArguments('index', 'query'), - ['FT.SEARCH', 'index', 'query'] - ); - }); - - it('with VERBATIM', () => { - assert.deepEqual( - transformArguments('index', 'query', { VERBATIM: true }), - ['FT.SEARCH', 'index', 'query', 'VERBATIM'] - ); - }); - - it('with NOSTOPWORDS', () => { - assert.deepEqual( - transformArguments('index', 'query', { NOSTOPWORDS: true }), - ['FT.SEARCH', 'index', 'query', 'NOSTOPWORDS'] - ); - }); - - it('with INKEYS', () => { - assert.deepEqual( - transformArguments('index', 'query', { INKEYS: 'key' }), - ['FT.SEARCH', 'index', 'query', 'INKEYS', '1', 'key'] - ); - }); - - it('with INFIELDS', () => { - assert.deepEqual( - transformArguments('index', 'query', { INFIELDS: 'field' }), - ['FT.SEARCH', 'index', 'query', 'INFIELDS', '1', 'field'] - ); - }); - - it('with RETURN', () => { - assert.deepEqual( - transformArguments('index', 'query', { RETURN: 'return' }), - ['FT.SEARCH', 'index', 'query', 'RETURN', '1', 'return'] - ); - }); - - describe('with SUMMARIZE', () => { - it('true', () => { - assert.deepEqual( - transformArguments('index', 'query', { SUMMARIZE: true }), - ['FT.SEARCH', 'index', 'query', 'SUMMARIZE'] - ); - }); - - describe('with FIELDS', () => { - it('string', () => { - assert.deepEqual( - transformArguments('index', 'query', { - SUMMARIZE: { - FIELDS: ['@field'] - } - }), - ['FT.SEARCH', 'index', 'query', 'SUMMARIZE', 'FIELDS', '1', '@field'] - ); - }); - - it('Array', () => { - assert.deepEqual( - transformArguments('index', 'query', { - SUMMARIZE: { - FIELDS: ['@1', '@2'] - } - }), - ['FT.SEARCH', 'index', 'query', 'SUMMARIZE', 'FIELDS', '2', '@1', '@2'] - ); - }); - }); - - it('with FRAGS', () => { - assert.deepEqual( - transformArguments('index', 'query', { - SUMMARIZE: { - FRAGS: 1 - } - }), - ['FT.SEARCH', 'index', 'query', 'SUMMARIZE', 'FRAGS', '1'] - ); - }); - - it('with LEN', () => { - assert.deepEqual( - transformArguments('index', 'query', { - SUMMARIZE: { - LEN: 1 - } - }), - ['FT.SEARCH', 'index', 'query', 'SUMMARIZE', 'LEN', '1'] - ); - }); - - it('with SEPARATOR', () => { - assert.deepEqual( - transformArguments('index', 'query', { - SUMMARIZE: { - SEPARATOR: 'separator' - } - }), - ['FT.SEARCH', 'index', 'query', 'SUMMARIZE', 'SEPARATOR', 'separator'] - ); - }); - }); - - describe('with HIGHLIGHT', () => { - it('true', () => { - assert.deepEqual( - transformArguments('index', 'query', { HIGHLIGHT: true }), - ['FT.SEARCH', 'index', 'query', 'HIGHLIGHT'] - ); - }); - - describe('with FIELDS', () => { - it('string', () => { - assert.deepEqual( - transformArguments('index', 'query', { - HIGHLIGHT: { - FIELDS: ['@field'] - } - }), - ['FT.SEARCH', 'index', 'query', 'HIGHLIGHT', 'FIELDS', '1', '@field'] - ); - }); - - it('Array', () => { - assert.deepEqual( - transformArguments('index', 'query', { - HIGHLIGHT: { - FIELDS: ['@1', '@2'] - } - }), - ['FT.SEARCH', 'index', 'query', 'HIGHLIGHT', 'FIELDS', '2', '@1', '@2'] - ); - }); - }); - - it('with TAGS', () => { - assert.deepEqual( - transformArguments('index', 'query', { - HIGHLIGHT: { - TAGS: { - open: 'open', - close: 'close' - } - } - }), - ['FT.SEARCH', 'index', 'query', 'HIGHLIGHT', 'TAGS', 'open', 'close'] - ); - }); - }); - - it('with SLOP', () => { - assert.deepEqual( - transformArguments('index', 'query', { SLOP: 1 }), - ['FT.SEARCH', 'index', 'query', 'SLOP', '1'] - ); - }); - - it('with INORDER', () => { - assert.deepEqual( - transformArguments('index', 'query', { INORDER: true }), - ['FT.SEARCH', 'index', 'query', 'INORDER'] - ); - }); - - it('with LANGUAGE', () => { - assert.deepEqual( - transformArguments('index', 'query', { LANGUAGE: RedisSearchLanguages.ARABIC }), - ['FT.SEARCH', 'index', 'query', 'LANGUAGE', RedisSearchLanguages.ARABIC] - ); - }); - - it('with EXPANDER', () => { - assert.deepEqual( - transformArguments('index', 'query', { EXPANDER: 'expender' }), - ['FT.SEARCH', 'index', 'query', 'EXPANDER', 'expender'] - ); - }); - - it('with SCORER', () => { - assert.deepEqual( - transformArguments('index', 'query', { SCORER: 'scorer' }), - ['FT.SEARCH', 'index', 'query', 'SCORER', 'scorer'] - ); - }); - - it('with SORTBY', () => { - assert.deepEqual( - transformArguments('index', 'query', { SORTBY: '@by' }), - ['FT.SEARCH', 'index', 'query', 'SORTBY', '@by'] - ); - }); - - it('with LIMIT', () => { - assert.deepEqual( - transformArguments('index', 'query', { - LIMIT: { - from: 0, - size: 1 - } - }), - ['FT.SEARCH', 'index', 'query', 'LIMIT', '0', '1'] - ); - }); - - it('with PARAMS', () => { - assert.deepEqual( - transformArguments('index', 'query', { - PARAMS: { - param: 'value' - } - }), - ['FT.SEARCH', 'index', 'query', 'PARAMS', '2', 'param', 'value'] - ); - }); - - it('with DIALECT', () => { - assert.deepEqual( - transformArguments('index', 'query', { - DIALECT: 1 - }), - ['FT.SEARCH', 'index', 'query', 'DIALECT', '1'] - ); - }); - - it('with TIMEOUT', () => { - assert.deepEqual( - transformArguments('index', 'query', { - TIMEOUT: 5 - }), - ['FT.SEARCH', 'index', 'query', 'TIMEOUT', '5'] - ); - }); +describe('FT.SEARCH', () => { + describe('transformArguments', () => { + it('without options', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query'), + ['FT.SEARCH', 'index', 'query'] + ); }); - describe('client.ft.search', () => { - testUtils.testWithClient('without optional options', async client => { - await Promise.all([ - client.ft.create('index', { - field: SchemaFieldTypes.NUMERIC - }), - client.hSet('1', 'field', '1') - ]); - - assert.deepEqual( - await client.ft.search('index', '*'), - { - total: 1, - documents: [{ - id: '1', - value: Object.create(null, { - field: { - value: '1', - configurable: true, - enumerable: true - } - }) - }] - } - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithClient('RETURN []', async client => { - await Promise.all([ - client.ft.create('index', { - field: SchemaFieldTypes.NUMERIC - }), - client.hSet('1', 'field', '1'), - client.hSet('2', 'field', '2') - ]); - - assert.deepEqual( - await client.ft.search('index', '*', { - RETURN: [] - }), - { - total: 2, - documents: [{ - id: '1', - value: Object.create(null) - }, { - id: '2', - value: Object.create(null) - }] - } - ); - }, GLOBAL.SERVERS.OPEN); + it('with VERBATIM', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + VERBATIM: true + }), + ['FT.SEARCH', 'index', 'query', 'VERBATIM'] + ); }); + + it('with NOSTOPWORDS', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + NOSTOPWORDS: true + }), + ['FT.SEARCH', 'index', 'query', 'NOSTOPWORDS'] + ); + }); + + it('with INKEYS', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + INKEYS: 'key' + }), + ['FT.SEARCH', 'index', 'query', 'INKEYS', '1', 'key'] + ); + }); + + it('with INFIELDS', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + INFIELDS: 'field' + }), + ['FT.SEARCH', 'index', 'query', 'INFIELDS', '1', 'field'] + ); + }); + + it('with RETURN', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + RETURN: 'return' + }), + ['FT.SEARCH', 'index', 'query', 'RETURN', '1', 'return'] + ); + }); + + describe('with SUMMARIZE', () => { + it('true', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + SUMMARIZE: true + }), + ['FT.SEARCH', 'index', 'query', 'SUMMARIZE'] + ); + }); + + describe('with FIELDS', () => { + it('string', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + SUMMARIZE: { + FIELDS: '@field' + } + }), + ['FT.SEARCH', 'index', 'query', 'SUMMARIZE', 'FIELDS', '1', '@field'] + ); + }); + + it('Array', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + SUMMARIZE: { + FIELDS: ['@1', '@2'] + } + }), + ['FT.SEARCH', 'index', 'query', 'SUMMARIZE', 'FIELDS', '2', '@1', '@2'] + ); + }); + }); + + it('with FRAGS', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + SUMMARIZE: { + FRAGS: 1 + } + }), + ['FT.SEARCH', 'index', 'query', 'SUMMARIZE', 'FRAGS', '1'] + ); + }); + + it('with LEN', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + SUMMARIZE: { + LEN: 1 + } + }), + ['FT.SEARCH', 'index', 'query', 'SUMMARIZE', 'LEN', '1'] + ); + }); + + it('with SEPARATOR', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + SUMMARIZE: { + SEPARATOR: 'separator' + } + }), + ['FT.SEARCH', 'index', 'query', 'SUMMARIZE', 'SEPARATOR', 'separator'] + ); + }); + }); + + describe('with HIGHLIGHT', () => { + it('true', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + HIGHLIGHT: true + }), + ['FT.SEARCH', 'index', 'query', 'HIGHLIGHT'] + ); + }); + + describe('with FIELDS', () => { + it('string', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + HIGHLIGHT: { + FIELDS: ['@field'] + } + }), + ['FT.SEARCH', 'index', 'query', 'HIGHLIGHT', 'FIELDS', '1', '@field'] + ); + }); + + it('Array', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + HIGHLIGHT: { + FIELDS: ['@1', '@2'] + } + }), + ['FT.SEARCH', 'index', 'query', 'HIGHLIGHT', 'FIELDS', '2', '@1', '@2'] + ); + }); + }); + + it('with TAGS', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + HIGHLIGHT: { + TAGS: { + open: 'open', + close: 'close' + } + } + }), + ['FT.SEARCH', 'index', 'query', 'HIGHLIGHT', 'TAGS', 'open', 'close'] + ); + }); + }); + + it('with SLOP', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + SLOP: 1 + }), + ['FT.SEARCH', 'index', 'query', 'SLOP', '1'] + ); + }); + + it('with TIMEOUT', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + TIMEOUT: 1 + }), + ['FT.SEARCH', 'index', 'query', 'TIMEOUT', '1'] + ); + }); + + it('with INORDER', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + INORDER: true + }), + ['FT.SEARCH', 'index', 'query', 'INORDER'] + ); + }); + + it('with LANGUAGE', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + LANGUAGE: 'Arabic' + }), + ['FT.SEARCH', 'index', 'query', 'LANGUAGE', 'Arabic'] + ); + }); + + it('with EXPANDER', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + EXPANDER: 'expender' + }), + ['FT.SEARCH', 'index', 'query', 'EXPANDER', 'expender'] + ); + }); + + it('with SCORER', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + SCORER: 'scorer' + }), + ['FT.SEARCH', 'index', 'query', 'SCORER', 'scorer'] + ); + }); + + it('with SORTBY', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + SORTBY: '@by' + }), + ['FT.SEARCH', 'index', 'query', 'SORTBY', '@by'] + ); + }); + + it('with LIMIT', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + LIMIT: { + from: 0, + size: 1 + } + }), + ['FT.SEARCH', 'index', 'query', 'LIMIT', '0', '1'] + ); + }); + + it('with PARAMS', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + PARAMS: { + string: 'string', + buffer: Buffer.from('buffer'), + number: 1 + } + }), + ['FT.SEARCH', 'index', 'query', 'PARAMS', '6', 'string', 'string', 'buffer', Buffer.from('buffer'), 'number', '1'] + ); + }); + + it('with DIALECT', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + DIALECT: 1 + }), + ['FT.SEARCH', 'index', 'query', 'DIALECT', '1'] + ); + }); + }); + + describe('client.ft.search', () => { + testUtils.testWithClient('without optional options', async client => { + await Promise.all([ + client.ft.create('index', { + field: 'TEXT' + }), + client.hSet('1', 'field', '1') + ]); + + assert.deepEqual( + await client.ft.search('index', '*'), + { + total: 1, + documents: [{ + id: '1', + value: Object.create(null, { + field: { + value: '1', + configurable: true, + enumerable: true + } + }) + }] + } + ); + }, GLOBAL.SERVERS.OPEN); + + testUtils.testWithClient('RETURN []', async client => { + await Promise.all([ + client.ft.create('index', { + field: 'TEXT' + }), + client.hSet('1', 'field', '1'), + client.hSet('2', 'field', '2') + ]); + + assert.deepEqual( + await client.ft.search('index', '*', { + RETURN: [] + }), + { + total: 2, + documents: [{ + id: '1', + value: Object.create(null) + }, { + id: '2', + value: Object.create(null) + }] + } + ); + }, GLOBAL.SERVERS.OPEN); + }); }); diff --git a/packages/search/lib/commands/SEARCH.ts b/packages/search/lib/commands/SEARCH.ts index ff7ab7e201..91946c8bec 100644 --- a/packages/search/lib/commands/SEARCH.ts +++ b/packages/search/lib/commands/SEARCH.ts @@ -1,109 +1,162 @@ -import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; -import { pushSearchOptions, RedisSearchLanguages, Params, PropertyName, SortByProperty, SearchReply } from '.'; +import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types'; +import { RedisVariadicArgument, pushOptionalVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers'; +import { RediSearchProperty, RediSearchLanguage } from './CREATE'; -export const FIRST_KEY_INDEX = 1; +export type FtSearchParams = Record; -export const IS_READ_ONLY = true; +export function pushParamsArgument(args: Array, params?: FtSearchParams) { + if (params) { + const length = args.push('PARAMS', ''); + for (const key in params) { + if (!Object.hasOwn(params, key)) continue; -export interface SearchOptions { - VERBATIM?: true; - NOSTOPWORDS?: true; - // WITHSCORES?: true; - // WITHPAYLOADS?: true; - WITHSORTKEYS?: true; - // FILTER?: { - // field: string; - // min: number | string; - // max: number | string; - // }; - // GEOFILTER?: { - // field: string; - // lon: number; - // lat: number; - // radius: number; - // unit: 'm' | 'km' | 'mi' | 'ft'; - // }; - INKEYS?: string | Array; - INFIELDS?: string | Array; - RETURN?: string | Array; - SUMMARIZE?: true | { - FIELDS?: PropertyName | Array; - FRAGS?: number; - LEN?: number; - SEPARATOR?: string; - }; - HIGHLIGHT?: true | { - FIELDS?: PropertyName | Array; - TAGS?: { - open: string; - close: string; - }; - }; - SLOP?: number; - INORDER?: true; - LANGUAGE?: RedisSearchLanguages; - EXPANDER?: string; - SCORER?: string; - // EXPLAINSCORE?: true; // TODO: WITHSCORES - // PAYLOAD?: ; - SORTBY?: SortByProperty; - // MSORTBY?: SortByProperty | Array; - LIMIT?: { - from: number | string; - size: number | string; - }; - PARAMS?: Params; - DIALECT?: number; - TIMEOUT?: number; -} - -export function transformArguments( - index: string, - query: string, - options?: SearchOptions -): RedisCommandArguments { - return pushSearchOptions( - ['FT.SEARCH', index, query], - options - ); -} - -export type SearchRawReply = Array; - -export function transformReply(reply: SearchRawReply, withoutDocuments: boolean): SearchReply { - const documents = []; - let i = 1; - while (i < reply.length) { - documents.push({ - id: reply[i++], - value: withoutDocuments ? Object.create(null) : documentValue(reply[i++]) - }); + const value = params[key]; + args.push( + key, + typeof value === 'number' ? value.toString() : value + ); } - return { - total: reply[0], - documents - }; + args[length - 1] = (args.length - length).toString(); + } } -function documentValue(tuples: any) { - const message = Object.create(null); +export interface FtSearchOptions { + VERBATIM?: boolean; + NOSTOPWORDS?: boolean; + INKEYS?: RedisVariadicArgument; + INFIELDS?: RedisVariadicArgument; + RETURN?: RedisVariadicArgument; + SUMMARIZE?: boolean | { + FIELDS?: RediSearchProperty | Array; + FRAGS?: number; + LEN?: number; + SEPARATOR?: RedisArgument; + }; + HIGHLIGHT?: boolean | { + FIELDS?: RediSearchProperty | Array; + TAGS?: { + open: RedisArgument; + close: RedisArgument; + }; + }; + SLOP?: number; + TIMEOUT?: number; + INORDER?: boolean; + LANGUAGE?: RediSearchLanguage; + EXPANDER?: RedisArgument; + SCORER?: RedisArgument; + SORTBY?: RedisArgument | { + BY: RediSearchProperty; + DIRECTION?: 'ASC' | 'DESC'; + }; + LIMIT?: { + from: number | RedisArgument; + size: number | RedisArgument; + }; + PARAMS?: FtSearchParams; + DIALECT?: number; +} - let i = 0; - while (i < tuples.length) { - const key = tuples[i++], - value = tuples[i++]; - if (key === '$') { // might be a JSON reply - try { - Object.assign(message, JSON.parse(value)); - continue; - } catch { - // set as a regular property if not a valid JSON - } +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments(index: RedisArgument, query: RedisArgument, options?: FtSearchOptions) { + const args = ['FT.SEARCH', index, query]; + + if (options?.VERBATIM) { + args.push('VERBATIM'); + } + + if (options?.NOSTOPWORDS) { + args.push('NOSTOPWORDS'); + } + + pushOptionalVariadicArgument(args, 'INKEYS', options?.INKEYS); + pushOptionalVariadicArgument(args, 'INFIELDS', options?.INFIELDS); + pushOptionalVariadicArgument(args, 'RETURN', options?.RETURN); + + if (options?.SUMMARIZE) { + args.push('SUMMARIZE'); + + if (typeof options.SUMMARIZE === 'object') { + pushOptionalVariadicArgument(args, 'FIELDS', options.SUMMARIZE.FIELDS); + + if (options.SUMMARIZE.FRAGS !== undefined) { + args.push('FRAGS', options.SUMMARIZE.FRAGS.toString()); } - message[key] = value; + if (options.SUMMARIZE.LEN !== undefined) { + args.push('LEN', options.SUMMARIZE.LEN.toString()); + } + + if (options.SUMMARIZE.SEPARATOR !== undefined) { + args.push('SEPARATOR', options.SUMMARIZE.SEPARATOR); + } + } } - return message; -} + if (options?.HIGHLIGHT) { + args.push('HIGHLIGHT'); + + if (typeof options.HIGHLIGHT === 'object') { + pushOptionalVariadicArgument(args, 'FIELDS', options.HIGHLIGHT.FIELDS); + + if (options.HIGHLIGHT.TAGS) { + args.push('TAGS', options.HIGHLIGHT.TAGS.open, options.HIGHLIGHT.TAGS.close); + } + } + } + + if (options?.SLOP !== undefined) { + args.push('SLOP', options.SLOP.toString()); + } + + if (options?.TIMEOUT !== undefined) { + args.push('TIMEOUT', options.TIMEOUT.toString()); + } + + if (options?.INORDER) { + args.push('INORDER'); + } + + if (options?.LANGUAGE) { + args.push('LANGUAGE', options.LANGUAGE); + } + + if (options?.EXPANDER) { + args.push('EXPANDER', options.EXPANDER); + } + + if (options?.SCORER) { + args.push('SCORER', options.SCORER); + } + + if (options?.SORTBY) { + args.push('SORTBY'); + + if (typeof options.SORTBY === 'string' || options.SORTBY instanceof Buffer) { + args.push(options.SORTBY); + } else { + args.push(options.SORTBY.BY); + + if (options.SORTBY.DIRECTION) { + args.push(options.SORTBY.DIRECTION); + } + } + } + + if (options?.LIMIT) { + args.push('LIMIT', options.LIMIT.from.toString(), options.LIMIT.size.toString()); + } + + pushParamsArgument(args, options?.PARAMS); + + if (options?.DIALECT !== undefined) { + args.push('DIALECT', options.DIALECT.toString()); + } + + return args; + }, + transformReply: undefined as unknown as () => any +} as const satisfies Command; diff --git a/packages/search/lib/commands/SEARCH_NOCONTENT.spec.ts b/packages/search/lib/commands/SEARCH_NOCONTENT.spec.ts index da5a6feaba..be998b9e63 100644 --- a/packages/search/lib/commands/SEARCH_NOCONTENT.spec.ts +++ b/packages/search/lib/commands/SEARCH_NOCONTENT.spec.ts @@ -1,45 +1,34 @@ import { strict as assert } from 'assert'; -import { SchemaFieldTypes } from '.'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments, transformReply } from './SEARCH_NOCONTENT'; +import SEARCH_NOCONTENT from './SEARCH_NOCONTENT'; -describe('SEARCH_NOCONTENT', () => { - describe('transformArguments', () => { - it('without options', () => { - assert.deepEqual( - transformArguments('index', 'query'), - ['FT.SEARCH', 'index', 'query', 'NOCONTENT'] - ); - }); +describe('FT.SEARCH NOCONTENT', () => { + describe('transformArguments', () => { + it('without options', () => { + assert.deepEqual( + SEARCH_NOCONTENT.transformArguments('index', 'query'), + ['FT.SEARCH', 'index', 'query', 'NOCONTENT'] + ); }); + }); - describe('transformReply', () => { - it('returns total and keys', () => { - assert.deepEqual(transformReply([3, '1', '2', '3']), { - total: 3, - documents: ['1', '2', '3'] - }) - }); - }); + describe('client.ft.searchNoContent', () => { + testUtils.testWithClient('returns total and keys', async client => { + await Promise.all([ + client.ft.create('index', { + field: 'TEXT' + }), + client.hSet('1', 'field', 'field1'), + client.hSet('2', 'field', 'field2') + ]); - describe('client.ft.searchNoContent', () => { - testUtils.testWithClient('returns total and keys', async client => { - await Promise.all([ - client.ft.create('index', { - field: SchemaFieldTypes.TEXT - }), - client.hSet('1', 'field', 'field1'), - client.hSet('2', 'field', 'field2'), - client.hSet('3', 'field', 'field3') - ]); - - assert.deepEqual( - await client.ft.searchNoContent('index', '*'), - { - total: 3, - documents: ['1','2','3'] - } - ); - }, GLOBAL.SERVERS.OPEN); - }); + assert.deepEqual( + await client.ft.searchNoContent('index', '*'), + { + total: 2, + documents: ['1', '2'] + } + ); + }, GLOBAL.SERVERS.OPEN); + }); }); diff --git a/packages/search/lib/commands/SEARCH_NOCONTENT.ts b/packages/search/lib/commands/SEARCH_NOCONTENT.ts index ab50ae2b9f..2885309177 100644 --- a/packages/search/lib/commands/SEARCH_NOCONTENT.ts +++ b/packages/search/lib/commands/SEARCH_NOCONTENT.ts @@ -1,30 +1,13 @@ -import { RedisCommandArguments } from "@redis/client/dist/lib/commands"; -import { pushSearchOptions } from "."; -import { SearchOptions, SearchRawReply } from "./SEARCH"; +import { Command } from '@redis/client/dist/lib/RESP/types'; +import SEARCH from './SEARCH'; -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments( - index: string, - query: string, - options?: SearchOptions -): RedisCommandArguments { - return pushSearchOptions( - ['FT.SEARCH', index, query, 'NOCONTENT'], - options - ); -} - -export interface SearchNoContentReply { - total: number; - documents: Array; -}; - -export function transformReply(reply: SearchRawReply): SearchNoContentReply { - return { - total: reply[0], - documents: reply.slice(1) - }; -} +export default { + FIRST_KEY_INDEX: SEARCH.FIRST_KEY_INDEX, + IS_READ_ONLY: SEARCH.IS_READ_ONLY, + transformArguments(...args: Parameters) { + const redisArgs = SEARCH.transformArguments(...args); + redisArgs.push('NOCONTENT'); + return redisArgs; + }, + transformReply: undefined as unknown as () => any +} as const satisfies Command; diff --git a/packages/search/lib/commands/index.ts b/packages/search/lib/commands/index.ts index 43831c90ac..978ee1b265 100644 --- a/packages/search/lib/commands/index.ts +++ b/packages/search/lib/commands/index.ts @@ -1,7 +1,7 @@ import _LIST from './_LIST'; import ALTER from './ALTER'; -// import AGGREGATE_WITHCURSOR from './AGGREGATE_WITHCURSOR'; -// import AGGREGATE from './AGGREGATE'; +import AGGREGATE_WITHCURSOR from './AGGREGATE_WITHCURSOR'; +import AGGREGATE from './AGGREGATE'; import ALIASADD from './ALIASADD'; import ALIASDEL from './ALIASDEL'; import ALIASUPDATE from './ALIASUPDATE'; @@ -19,7 +19,8 @@ import DROPINDEX from './DROPINDEX'; // import INFO from './INFO'; // import PROFILESEARCH from './PROFILE_SEARCH'; // import PROFILEAGGREGATE from './PROFILE_AGGREGATE'; -// import SEARCH from './SEARCH'; +import SEARCH_NOCONTENT from './SEARCH_NOCONTENT'; +import SEARCH from './SEARCH'; import SPELLCHECK from './SPELLCHECK'; import SUGADD from './SUGADD'; import SUGDEL from './SUGDEL'; @@ -31,6 +32,7 @@ import SUGLEN from './SUGLEN'; import SYNDUMP from './SYNDUMP'; import SYNUPDATE from './SYNUPDATE'; import TAGVALS from './TAGVALS'; +import { RedisArgument } from '@redis/client'; // import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; // import { pushOptionalVariadicArgument, pushVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers'; // import { SearchOptions } from './SEARCH'; @@ -41,10 +43,10 @@ export default { _list: _LIST, ALTER, alter: ALTER, - // AGGREGATE_WITHCURSOR, - // aggregateWithCursor: AGGREGATE_WITHCURSOR, - // AGGREGATE, - // aggregate: AGGREGATE, + AGGREGATE_WITHCURSOR, + aggregateWithCursor: AGGREGATE_WITHCURSOR, + AGGREGATE, + aggregate: AGGREGATE, ALIASADD, aliasAdd: ALIASADD, ALIASDEL, @@ -79,8 +81,10 @@ export default { // profileSearch: PROFILESEARCH, // PROFILEAGGREGATE, // profileAggregate: PROFILEAGGREGATE, - // SEARCH, - // search: SEARCH, + SEARCH_NOCONTENT, + searchNoContent: SEARCH_NOCONTENT, + SEARCH, + search: SEARCH, SPELLCHECK, spellCheck: SPELLCHECK, SUGADD, @@ -104,539 +108,3 @@ export default { TAGVALS, tagVals: TAGVALS }; - -// export enum RedisSearchLanguages { -// ARABIC = 'Arabic', -// BASQUE = 'Basque', -// CATALANA = 'Catalan', -// DANISH = 'Danish', -// DUTCH = 'Dutch', -// ENGLISH = 'English', -// FINNISH = 'Finnish', -// FRENCH = 'French', -// GERMAN = 'German', -// GREEK = 'Greek', -// HUNGARIAN = 'Hungarian', -// INDONESAIN = 'Indonesian', -// IRISH = 'Irish', -// ITALIAN = 'Italian', -// LITHUANIAN = 'Lithuanian', -// NEPALI = 'Nepali', -// NORWEIGAN = 'Norwegian', -// PORTUGUESE = 'Portuguese', -// ROMANIAN = 'Romanian', -// RUSSIAN = 'Russian', -// SPANISH = 'Spanish', -// SWEDISH = 'Swedish', -// TAMIL = 'Tamil', -// TURKISH = 'Turkish', -// CHINESE = 'Chinese' -// } - -export type PropertyName = `${'@' | '$.'}${string}`; - -// export type SortByProperty = string | { -// BY: string; -// DIRECTION?: 'ASC' | 'DESC'; -// }; - -// export function pushSortByProperty(args: RedisCommandArguments, sortBy: SortByProperty): void { -// if (typeof sortBy === 'string') { -// args.push(sortBy); -// } else { -// args.push(sortBy.BY); - -// if (sortBy.DIRECTION) { -// args.push(sortBy.DIRECTION); -// } -// } -// } - -// export function pushSortByArguments(args: RedisCommandArguments, name: string, sortBy: SortByProperty | Array): RedisCommandArguments { -// const lengthBefore = args.push( -// name, -// '' // will be overwritten -// ); - -// if (Array.isArray(sortBy)) { -// for (const field of sortBy) { -// pushSortByProperty(args, field); -// } -// } else { -// pushSortByProperty(args, sortBy); -// } - -// args[lengthBefore - 1] = (args.length - lengthBefore).toString(); - -// return args; -// } - -// export function pushArgumentsWithLength(args: CommandArguments, fn: (args: CommandArguments) => void) { -// const lengthIndex = args.push('') - 1; -// fn(args); -// args[lengthIndex] = (args.length - lengthIndex - 1).toString(); -// return args; -// } - -// export enum SchemaFieldTypes { -// TEXT = 'TEXT', -// NUMERIC = 'NUMERIC', -// GEO = 'GEO', -// TAG = 'TAG', -// VECTOR = 'VECTOR' -// } - -// type CreateSchemaField< -// T extends SchemaFieldTypes, -// E = Record -// > = T | ({ -// type: T; -// AS?: string; -// } & E); - -// type CreateSchemaCommonField< -// T extends SchemaFieldTypes, -// E = Record -// > = CreateSchemaField< -// T, -// ({ -// SORTABLE?: true | 'UNF'; -// NOINDEX?: true; -// } & E) -// >; - -// export enum SchemaTextFieldPhonetics { -// DM_EN = 'dm:en', -// DM_FR = 'dm:fr', -// FM_PT = 'dm:pt', -// DM_ES = 'dm:es' -// } - -// type CreateSchemaTextField = CreateSchemaCommonField; - -// type CreateSchemaNumericField = CreateSchemaCommonField; - -// type CreateSchemaGeoField = CreateSchemaCommonField; - -// type CreateSchemaTagField = CreateSchemaCommonField; - -// export enum VectorAlgorithms { -// FLAT = 'FLAT', -// HNSW = 'HNSW' -// } - -// type CreateSchemaVectorField< -// T extends VectorAlgorithms, -// A extends Record -// > = CreateSchemaField; - -// type CreateSchemaFlatVectorField = CreateSchemaVectorField; - -// type CreateSchemaHNSWVectorField = CreateSchemaVectorField; - -// export interface RediSearchSchema { -// [field: string]: -// CreateSchemaTextField | -// CreateSchemaNumericField | -// CreateSchemaGeoField | -// CreateSchemaTagField | -// CreateSchemaFlatVectorField | -// CreateSchemaHNSWVectorField; -// } - -// export function pushSchema(args: RedisCommandArguments, schema: RediSearchSchema) { -// for (const [field, fieldOptions] of Object.entries(schema)) { -// args.push(field); - -// if (typeof fieldOptions === 'string') { -// args.push(fieldOptions); -// continue; -// } - -// if (fieldOptions.AS) { -// args.push('AS', fieldOptions.AS); -// } - -// args.push(fieldOptions.type); - -// switch (fieldOptions.type) { -// case SchemaFieldTypes.TEXT: -// if (fieldOptions.NOSTEM) { -// args.push('NOSTEM'); -// } - -// if (fieldOptions.WEIGHT) { -// args.push('WEIGHT', fieldOptions.WEIGHT.toString()); -// } - -// if (fieldOptions.PHONETIC) { -// args.push('PHONETIC', fieldOptions.PHONETIC); -// } - -// if (fieldOptions.WITHSUFFIXTRIE) { -// args.push('WITHSUFFIXTRIE'); -// } - -// break; - -// // case SchemaFieldTypes.NUMERIC: -// // case SchemaFieldTypes.GEO: -// // break; - -// case SchemaFieldTypes.TAG: -// if (fieldOptions.SEPARATOR) { -// args.push('SEPARATOR', fieldOptions.SEPARATOR); -// } - -// if (fieldOptions.CASESENSITIVE) { -// args.push('CASESENSITIVE'); -// } - -// if (fieldOptions.WITHSUFFIXTRIE) { -// args.push('WITHSUFFIXTRIE'); -// } - -// break; - -// case SchemaFieldTypes.VECTOR: -// args.push(fieldOptions.ALGORITHM); - -// pushArgumentsWithLength(args, () => { -// args.push( -// 'TYPE', fieldOptions.TYPE, -// 'DIM', fieldOptions.DIM.toString(), -// 'DISTANCE_METRIC', fieldOptions.DISTANCE_METRIC -// ); - -// if (fieldOptions.INITIAL_CAP) { -// args.push('INITIAL_CAP', fieldOptions.INITIAL_CAP.toString()); -// } - -// switch (fieldOptions.ALGORITHM) { -// case VectorAlgorithms.FLAT: -// if (fieldOptions.BLOCK_SIZE) { -// args.push('BLOCK_SIZE', fieldOptions.BLOCK_SIZE.toString()); -// } - -// break; - -// case VectorAlgorithms.HNSW: -// if (fieldOptions.M) { -// args.push('M', fieldOptions.M.toString()); -// } - -// if (fieldOptions.EF_CONSTRUCTION) { -// args.push('EF_CONSTRUCTION', fieldOptions.EF_CONSTRUCTION.toString()); -// } - -// if (fieldOptions.EF_RUNTIME) { -// args.push('EF_RUNTIME', fieldOptions.EF_RUNTIME.toString()); -// } - -// break; -// } -// }); - -// continue; // vector fields do not contain SORTABLE and NOINDEX options -// } - -// if (fieldOptions.SORTABLE) { -// args.push('SORTABLE'); - -// if (fieldOptions.SORTABLE === 'UNF') { -// args.push('UNF'); -// } -// } - -// if (fieldOptions.NOINDEX) { -// args.push('NOINDEX'); -// } -// } -// } - -// export type Params = Record; - -// export function pushParamsArgs( -// args: RedisCommandArguments, -// params?: Params -// ): RedisCommandArguments { -// if (params) { -// const enrties = Object.entries(params); -// args.push('PARAMS', (enrties.length * 2).toString()); -// for (const [key, value] of enrties) { -// args.push(key, typeof value === 'number' ? value.toString() : value); -// } -// } - -// return args; -// } - -// export function pushSearchOptions( -// args: RedisCommandArguments, -// options?: SearchOptions -// ): RedisCommandArguments { -// if (options?.VERBATIM) { -// args.push('VERBATIM'); -// } - -// if (options?.NOSTOPWORDS) { -// args.push('NOSTOPWORDS'); -// } - -// // if (options?.WITHSCORES) { -// // args.push('WITHSCORES'); -// // } - -// // if (options?.WITHPAYLOADS) { -// // args.push('WITHPAYLOADS'); -// // } - -// pushOptionalVariadicArgument(args, 'INKEYS', options?.INKEYS); -// pushOptionalVariadicArgument(args, 'INFIELDS', options?.INFIELDS); -// pushOptionalVariadicArgument(args, 'RETURN', options?.RETURN); - -// if (options?.SUMMARIZE) { -// args.push('SUMMARIZE'); - -// if (typeof options.SUMMARIZE === 'object') { -// if (options.SUMMARIZE.FIELDS) { -// args.push('FIELDS'); -// pushVariadicArgument(args, options.SUMMARIZE.FIELDS); -// } - -// if (options.SUMMARIZE.FRAGS) { -// args.push('FRAGS', options.SUMMARIZE.FRAGS.toString()); -// } - -// if (options.SUMMARIZE.LEN) { -// args.push('LEN', options.SUMMARIZE.LEN.toString()); -// } - -// if (options.SUMMARIZE.SEPARATOR) { -// args.push('SEPARATOR', options.SUMMARIZE.SEPARATOR); -// } -// } -// } - -// if (options?.HIGHLIGHT) { -// args.push('HIGHLIGHT'); - -// if (typeof options.HIGHLIGHT === 'object') { -// if (options.HIGHLIGHT.FIELDS) { -// args.push('FIELDS'); -// pushVariadicArgument(args, options.HIGHLIGHT.FIELDS); -// } - -// if (options.HIGHLIGHT.TAGS) { -// args.push('TAGS', options.HIGHLIGHT.TAGS.open, options.HIGHLIGHT.TAGS.close); -// } -// } -// } - -// if (options?.SLOP) { -// args.push('SLOP', options.SLOP.toString()); -// } - -// if (options?.INORDER) { -// args.push('INORDER'); -// } - -// if (options?.LANGUAGE) { -// args.push('LANGUAGE', options.LANGUAGE); -// } - -// if (options?.EXPANDER) { -// args.push('EXPANDER', options.EXPANDER); -// } - -// if (options?.SCORER) { -// args.push('SCORER', options.SCORER); -// } - -// // if (options?.EXPLAINSCORE) { -// // args.push('EXPLAINSCORE'); -// // } - -// // if (options?.PAYLOAD) { -// // args.push('PAYLOAD', options.PAYLOAD); -// // } - -// if (options?.SORTBY) { -// args.push('SORTBY'); -// pushSortByProperty(args, options.SORTBY); -// } - -// // if (options?.MSORTBY) { -// // pushSortByArguments(args, 'MSORTBY', options.MSORTBY); -// // } - -// if (options?.LIMIT) { -// args.push( -// 'LIMIT', -// options.LIMIT.from.toString(), -// options.LIMIT.size.toString() -// ); -// } - -// if (options?.PARAMS) { -// pushParamsArgs(args, options.PARAMS); -// } - -// if (options?.DIALECT) { -// args.push('DIALECT', options.DIALECT.toString()); -// } - -// if (options?.RETURN?.length === 0) { -// args.preserve = true; -// } - -// if (options?.TIMEOUT !== undefined) { -// args.push('TIMEOUT', options.TIMEOUT.toString()); -// } - -// return args; -// } - -// interface SearchDocumentValue { -// [key: string]: string | number | null | Array | SearchDocumentValue; -// } - -// export interface SearchReply { -// total: number; -// documents: Array<{ -// id: string; -// value: SearchDocumentValue; -// }>; -// } - -// export interface ProfileOptions { -// LIMITED?: true; -// } - -// export type ProfileRawReply = [ -// results: T, -// profile: [ -// _: string, -// TotalProfileTime: string, -// _: string, -// ParsingTime: string, -// _: string, -// PipelineCreationTime: string, -// _: string, -// IteratorsProfile: Array -// ] -// ]; - -// export interface ProfileReply { -// results: SearchReply | AGGREGATE.AggregateReply; -// profile: ProfileData; -// } - -// interface ChildIterator { -// type?: string, -// counter?: number, -// term?: string, -// size?: number, -// time?: string, -// childIterators?: Array -// } - -// interface IteratorsProfile { -// type?: string, -// counter?: number, -// queryType?: string, -// time?: string, -// childIterators?: Array -// } - -// interface ProfileData { -// totalProfileTime: string, -// parsingTime: string, -// pipelineCreationTime: string, -// iteratorsProfile: IteratorsProfile -// } - -// export function transformProfile(reply: Array): ProfileData { -// return { -// totalProfileTime: reply[0][1], -// parsingTime: reply[1][1], -// pipelineCreationTime: reply[2][1], -// iteratorsProfile: transformIterators(reply[3][1]) -// }; -// } - -// function transformIterators(IteratorsProfile: Array): IteratorsProfile { -// var res: IteratorsProfile = {}; -// for (let i = 0; i < IteratorsProfile.length; i += 2) { -// const value = IteratorsProfile[i + 1]; -// switch (IteratorsProfile[i]) { -// case 'Type': -// res.type = value; -// break; -// case 'Counter': -// res.counter = value; -// break; -// case 'Time': -// res.time = value; -// break; -// case 'Query type': -// res.queryType = value; -// break; -// case 'Child iterators': -// res.childIterators = value.map(transformChildIterators); -// break; -// } -// } - -// return res; -// } - -// function transformChildIterators(IteratorsProfile: Array): ChildIterator { -// var res: ChildIterator = {}; -// for (let i = 1; i < IteratorsProfile.length; i += 2) { -// const value = IteratorsProfile[i + 1]; -// switch (IteratorsProfile[i]) { -// case 'Type': -// res.type = value; -// break; -// case 'Counter': -// res.counter = value; -// break; -// case 'Time': -// res.time = value; -// break; -// case 'Size': -// res.size = value; -// break; -// case 'Term': -// res.term = value; -// break; -// case 'Child iterators': -// res.childIterators = value.map(transformChildIterators); -// break; -// } -// } - -// return res; -// } diff --git a/packages/search/package.json b/packages/search/package.json index ede33a6d83..614ce51b44 100644 --- a/packages/search/package.json +++ b/packages/search/package.json @@ -9,7 +9,7 @@ "!dist/tsconfig.tsbuildinfo" ], "scripts": { - "test": "nyc -r text-summary -r lcov mocha -r source-map-support/register -r ts-node/register './lib/**/*.spec.ts'" + "test": "nyc -r text-summary -r lcov mocha -r tsx './lib/**/*.spec.ts'" }, "peerDependencies": { "@redis/client": "*" diff --git a/packages/test-utils/lib/dockers.ts b/packages/test-utils/lib/dockers.ts index c2d7683894..d282005e11 100644 --- a/packages/test-utils/lib/dockers.ts +++ b/packages/test-utils/lib/dockers.ts @@ -46,7 +46,7 @@ export interface RedisServerDocker { dockerId: string; } -// extrea ".." cause it'll be in `./dist` +// extra ".." cause it'll be in `./dist` const DOCKER_FODLER_PATH = path.join(__dirname, '../../docker'); async function spawnRedisServerDocker({ image, version }: RedisServerDockerConfig, serverArguments: Array): Promise { diff --git a/packages/time-series/lib/index.ts b/packages/time-series/lib/index.ts index 9372621b00..8a9efc8b37 100644 --- a/packages/time-series/lib/index.ts +++ b/packages/time-series/lib/index.ts @@ -1,11 +1,7 @@ -export { default } from './commands'; - export { - TIME_SERIES_ENCODING, - TimeSeriesEncoding, - TIME_SERIES_DUPLICATE_POLICIES, - TimeSeriesDuplicatePolicies + default, + TIME_SERIES_ENCODING, TimeSeriesEncoding, + TIME_SERIES_DUPLICATE_POLICIES, TimeSeriesDuplicatePolicies } from './commands'; - export { TIME_SERIES_AGGREGATION_TYPE, TimeSeriesAggregationType } from './commands/CREATERULE'; export { TIME_SERIES_BUCKET_TIMESTAMP, TimeSeriesBucketTimestamp } from './commands/RANGE'; diff --git a/packages/time-series/package.json b/packages/time-series/package.json index 1ffa3bd103..f19c69a64d 100644 --- a/packages/time-series/package.json +++ b/packages/time-series/package.json @@ -9,7 +9,7 @@ "!dist/tsconfig.tsbuildinfo" ], "scripts": { - "test": "nyc -r text-summary -r lcov mocha -r source-map-support/register -r ts-node/register './lib/**/*.spec.ts'" + "test": "nyc -r text-summary -r lcov mocha -r tsx './lib/**/*.spec.ts'" }, "peerDependencies": { "@redis/client": "*" diff --git a/tsconfig.base.json b/tsconfig.base.json index cb4c502639..3bec460a0d 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -1,12 +1,18 @@ { - "extends": "@tsconfig/node18/tsconfig.json", "compilerOptions": { + "lib": ["ES2023"], + "module": "ES2022", + "moduleResolution": "Node", + "target": "ES2022", + + "strict": true, + "forceConsistentCasingInFileNames": true, + "noUnusedLocals": true, + "esModuleInterop": true, + "skipLibCheck": true, + "composite": true, "declaration": true, "allowJs": true - }, - "ts-node": { - "files": true, - "transpileOnly": true } }