Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
14 commits
Select commit Hold shift + click to select a range
142f586
feat(api): exact u64 array integer replies via per-command ioredis bi…
VaskoAtanasovRedis Jun 22, 2026
b83dfc6
feat(api): CLI shows exact u64 for array integer-reply commands [RI-8…
VaskoAtanasovRedis Jun 22, 2026
5bcc1d5
feat(api): Workbench exact u64 for array commands; share the command …
VaskoAtanasovRedis Jun 22, 2026
1078231
test(api): restore the >2^53 ARGREP search integration assertion [RI-…
VaskoAtanasovRedis Jun 22, 2026
e6217a9
test(api): prove the (2^53, 2^63) bigint zone for ARLEN + ARSCAN [RI-…
VaskoAtanasovRedis Jun 22, 2026
b2c41ac
test(api): lock the array u64 RESP wire encoding in CI [RI-8296]
VaskoAtanasovRedis Jun 22, 2026
b1fddc3
test(api): gate the RESP encoding probe off cluster declaratively [RI…
VaskoAtanasovRedis Jun 23, 2026
53ff004
fix(api): keep array u64 exact in key-info and CLI text output [RI-8296]
VaskoAtanasovRedis Jun 23, 2026
ee72988
test(api): apply patches in the integration test image [RI-8296]
VaskoAtanasovRedis Jun 23, 2026
443e702
fix(api): show exact u64 array integer replies in CLI and Workbench […
VaskoAtanasovRedis Jun 29, 2026
683e430
fix(api): include AROP in the array u64 bigint opt-in [RI-8296]
VaskoAtanasovRedis Jun 30, 2026
32b9087
test(api): type formatter strategy specs to keep the TS baseline exac…
VaskoAtanasovRedis Jun 30, 2026
cdcba22
fix(api): keep the array aggregate endpoint exact for u64 results [RI…
VaskoAtanasovRedis Jun 30, 2026
481ddc7
fix(api): add ARINFO to the array u64 bigint opt-in [RI-8296]
VaskoAtanasovRedis Jul 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions redisinsight/api/.tscheck.rec.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,15 +84,15 @@
"TS7053": 3
},
"src/common/transformers/redis-reply/strategies/ascii-formatter.strategey.spec.ts": {
"TS7005": 8,
"TS7034": 2
"TS7005": 1,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kudos 🍕

"TS7034": 1
},
"src/common/transformers/redis-reply/strategies/ascii-formatter.strategy.ts": {
"TS7053": 2
},
"src/common/transformers/redis-reply/strategies/utf8-formatter.strategy.spec.ts": {
"TS7005": 9,
"TS7034": 2
"TS7005": 1,
"TS7034": 1
},
"src/common/transformers/redis-reply/strategies/utf8-formatter.strategy.ts": {
"TS7053": 2
Expand Down Expand Up @@ -497,15 +497,15 @@
"TS7053": 3
},
"src/modules/cli/services/cli-business/output-formatter/strategies/raw-formatter.strategy.spec.ts": {
"TS7005": 8,
"TS7034": 2
"TS7005": 1,
"TS7034": 1
},
"src/modules/cli/services/cli-business/output-formatter/strategies/raw-formatter.strategy.ts": {
"TS7053": 2
},
"src/modules/cli/services/cli-business/output-formatter/strategies/text-formatter.strategy.spec.ts": {
"TS7005": 10,
"TS7034": 2
"TS7005": 1,
"TS7034": 1
},
"src/modules/cli/services/cli-business/output-formatter/strategies/utf-8-formatter.strategy.ts": {
"TS7053": 2
Expand Down
107 changes: 107 additions & 0 deletions redisinsight/api/patches/ioredis+5.3.2.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
diff --git a/node_modules/ioredis/built/Command.d.ts b/node_modules/ioredis/built/Command.d.ts
index ea90aa2..ca28897 100644
--- a/node_modules/ioredis/built/Command.d.ts
+++ b/node_modules/ioredis/built/Command.d.ts
@@ -6,6 +6,7 @@ interface CommandOptions {
* Set the encoding of the reply, by default buffer will be returned.
*/
replyEncoding?: BufferEncoding | null;
+ integerReply?: "number" | "bigint";
errorStack?: Error;
keyPrefix?: string;
/**
@@ -75,6 +76,7 @@ export default class Command implements Respondable {
resolve: (result: any) => void;
promise: Promise<any>;
private replyEncoding;
+ integerReply?: "number" | "bigint";
private errorStack;
private bufferMode;
private callback;
diff --git a/node_modules/ioredis/built/Command.js b/node_modules/ioredis/built/Command.js
index 40cd1a6..aad90af 100644
--- a/node_modules/ioredis/built/Command.js
+++ b/node_modules/ioredis/built/Command.js
@@ -39,6 +39,7 @@ class Command {
this.isResolved = false;
this.transformed = false;
this.replyEncoding = options.replyEncoding;
+ this.integerReply = options.integerReply;
this.errorStack = options.errorStack;
this.args = args.flat();
this.callback = callback;
diff --git a/node_modules/ioredis/built/DataHandler.d.ts b/node_modules/ioredis/built/DataHandler.d.ts
index 93e97d9..24fe877 100644
--- a/node_modules/ioredis/built/DataHandler.d.ts
+++ b/node_modules/ioredis/built/DataHandler.d.ts
@@ -26,7 +26,11 @@ interface ParserOptions {
}
export default class DataHandler {
private redis;
+ private parser;
+ private stringNumbers;
constructor(redis: DataHandledable, parserOptions: ParserOptions);
+ private updateIntegerReplyMode;
+ private convertIntegerReply;
private returnFatalError;
private returnError;
private returnReply;
diff --git a/node_modules/ioredis/built/DataHandler.js b/node_modules/ioredis/built/DataHandler.js
index 1db1848..f985ed5 100644
--- a/node_modules/ioredis/built/DataHandler.js
+++ b/node_modules/ioredis/built/DataHandler.js
@@ -8,6 +8,7 @@ const debug = (0, utils_1.Debug)("dataHandler");
class DataHandler {
constructor(redis, parserOptions) {
this.redis = redis;
+ this.stringNumbers = parserOptions.stringNumbers;
const parser = new RedisParser({
stringNumbers: parserOptions.stringNumbers,
returnBuffers: true,
@@ -21,10 +22,27 @@ class DataHandler {
this.returnReply(reply);
},
});
+ this.parser = parser;
redis.stream.on("data", (data) => {
+ this.updateIntegerReplyMode();
parser.execute(data);
});
}
+ updateIntegerReplyMode() {
+ var _a, _b;
+ const item = (_a = this.redis.commandQueue) === null || _a === void 0 ? void 0 : _a.peekFront();
+ const integerReply = (_b = item === null || item === void 0 ? void 0 : item.command) === null || _b === void 0 ? void 0 : _b.integerReply;
+ this.parser.setStringNumbers(this.stringNumbers || integerReply === "bigint");
Comment thread
VaskoAtanasovRedis marked this conversation as resolved.
Comment thread
VaskoAtanasovRedis marked this conversation as resolved.
+ }
+ convertIntegerReply(reply) {
+ if (typeof reply === "string") {
+ return BigInt(reply);
+ }
+ if (Array.isArray(reply)) {
+ return reply.map((item) => this.convertIntegerReply(item));
+ }
+ return reply;
+ }
returnFatalError(err) {
err.message += ". Please report this.";
this.redis.recoverFromFatalError(err, err, { offlineQueue: false });
@@ -34,6 +52,7 @@ class DataHandler {
if (!item) {
return;
}
+ this.updateIntegerReplyMode();
err.command = {
name: item.command.name,
args: item.command.args,
@@ -51,6 +70,10 @@ class DataHandler {
if (!item) {
return;
}
+ this.updateIntegerReplyMode();
+ if (item.command.integerReply === "bigint") {
+ reply = this.convertIntegerReply(reply);
+ }
Comment thread
cursor[bot] marked this conversation as resolved.
if (Command_1.default.checkFlag("ENTER_SUBSCRIBER_MODE", item.command.name)) {
this.redis.condition.subscriber = new SubscriptionSet_1.default();
this.redis.condition.subscriber.add(item.command.name, reply[1].toString());
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ASCIIFormatterStrategy } from './ascii-formatter.strategy';

describe('ASCIIFormatterStrategy', () => {
let strategy;
let strategy: ASCIIFormatterStrategy;
beforeEach(async () => {
strategy = new ASCIIFormatterStrategy();
});
Expand All @@ -28,6 +28,24 @@ describe('ASCIIFormatterStrategy', () => {

expect(output).toEqual('string value');
});
it('should tag a bigint reply as an integer type', () => {
const output = strategy.format(BigInt('9007199254740994'));

expect(output).toEqual({ type: 'integer', value: '9007199254740994' });
});
it('should tag bigint leaves nested in an array', () => {
const input = [
BigInt('0'),
[BigInt('9007199254740994'), Buffer.from('value')],
];
const mockResponse = [
{ type: 'integer', value: '0' },
[{ type: 'integer', value: '9007199254740994' }, 'value'],
];
const output = strategy.format(input);

expect(output).toEqual(mockResponse);
});
it('should return correct value for empty array', () => {
const input = [];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ import { IFormatterStrategy } from '../formatter.interface';

export class ASCIIFormatterStrategy implements IFormatterStrategy {
public format(reply: any): any {
if (typeof reply === 'bigint') {
// Tag u64 integers so the UI prints `(integer) N`, not a quoted string.
return { type: 'integer', value: reply.toString() };
}
if (reply instanceof Buffer) {
return getASCIISafeStringFromBuffer(reply);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { UTF8FormatterStrategy } from './utf8-formatter.strategy';

describe('UTF8FormatterStrategy', () => {
let strategy;
let strategy: UTF8FormatterStrategy;
beforeEach(async () => {
strategy = new UTF8FormatterStrategy();
});
Expand All @@ -28,6 +28,24 @@ describe('UTF8FormatterStrategy', () => {

expect(output).toEqual('string value');
});
it('should tag a bigint reply as an integer type', () => {
const output = strategy.format(BigInt('9007199254740994'));

expect(output).toEqual({ type: 'integer', value: '9007199254740994' });
});
it('should tag bigint leaves nested in an array', () => {
const input = [
BigInt('0'),
[BigInt('9007199254740994'), Buffer.from('value')],
];
const mockResponse = [
{ type: 'integer', value: '0' },
[{ type: 'integer', value: '9007199254740994' }, 'value'],
];
const output = strategy.format(input);

expect(output).toEqual(mockResponse);
});
it('should return correct value for empty array', () => {
const input = [];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ import { IFormatterStrategy } from '../formatter.interface';

export class UTF8FormatterStrategy implements IFormatterStrategy {
public format(reply: any): any {
if (typeof reply === 'bigint') {
// Tag u64 integers so the UI prints `(integer) N`, not a quoted string.
return { type: 'integer', value: reply.toString() };
}
if (reply instanceof Buffer) {
return getUTF8FromBuffer(reply);
}
Expand Down
Loading
Loading