1
0
mirror of https://github.com/redis/node-redis.git synced 2025-08-06 02:15:48 +03:00

new "transform arguments" API for better key and metadata extraction (#2733)

* Parser support with all commands

* remove "dist" from all imports for consistency

* address most of my review comments

* small tweak to multi type mapping handling

* tweak multi commands / fix addScript cases

* nits

* addressed all in person review comments

* revert addCommand/addScript changes to multi-commands

addCommand needs to be there for sendCommand like ability within a multi.

If its there, it might as well be used by createCommand() et al, to avoid repeating code.

addScript is there (even though only used once), but now made private to keep the logic for bookkeeping near each other.
This commit is contained in:
Shaya Potter
2024-10-31 18:16:59 +02:00
committed by GitHub
parent 5ace34b9c9
commit 4708736f3b
1016 changed files with 6347 additions and 6542 deletions

View File

@@ -1,5 +1,6 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import { parseArgs } from './generic-transformers';
import ACL_CAT from './ACL_CAT';
describe('ACL CAT', () => {
@@ -8,14 +9,14 @@ describe('ACL CAT', () => {
describe('transformArguments', () => {
it('simple', () => {
assert.deepEqual(
ACL_CAT.transformArguments(),
parseArgs(ACL_CAT),
['ACL', 'CAT']
);
});
it('with categoryName', () => {
assert.deepEqual(
ACL_CAT.transformArguments('dangerous'),
parseArgs(ACL_CAT, 'dangerous'),
['ACL', 'CAT', 'dangerous']
);
});

View File

@@ -1,16 +1,14 @@
import { CommandParser } from '../client/parser';
import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types';
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments(categoryName?: RedisArgument) {
const args: Array<RedisArgument> = ['ACL', 'CAT'];
parseCommand(parser: CommandParser, categoryName?: RedisArgument) {
parser.push('ACL', 'CAT');
if (categoryName) {
args.push(categoryName);
parser.push(categoryName);
}
return args;
},
transformReply: undefined as unknown as () => ArrayReply<BlobStringReply>
} as const satisfies Command;

View File

@@ -1,6 +1,7 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import ACL_DELUSER from './ACL_DELUSER';
import { parseArgs } from './generic-transformers';
describe('ACL DELUSER', () => {
testUtils.isVersionGreaterThanHook([6]);
@@ -8,14 +9,14 @@ describe('ACL DELUSER', () => {
describe('transformArguments', () => {
it('string', () => {
assert.deepEqual(
ACL_DELUSER.transformArguments('username'),
parseArgs(ACL_DELUSER, 'username'),
['ACL', 'DELUSER', 'username']
);
});
it('array', () => {
assert.deepEqual(
ACL_DELUSER.transformArguments(['1', '2']),
parseArgs(ACL_DELUSER, ['1', '2']),
['ACL', 'DELUSER', '1', '2']
);
});

View File

@@ -1,11 +1,13 @@
import { CommandParser } from '../client/parser';
import { NumberReply, Command } from '../RESP/types';
import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers';
import { RedisVariadicArgument } from './generic-transformers';
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments(username: RedisVariadicArgument) {
return pushVariadicArguments(['ACL', 'DELUSER'], username);
parseCommand(parser: CommandParser, username: RedisVariadicArgument) {
parser.push('ACL', 'DELUSER');
parser.pushVariadic(username);
},
transformReply: undefined as unknown as () => NumberReply
} as const satisfies Command;

View File

@@ -1,13 +1,14 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import ACL_DRYRUN from './ACL_DRYRUN';
import { parseArgs } from './generic-transformers';
describe('ACL DRYRUN', () => {
testUtils.isVersionGreaterThanHook([7]);
it('transformArguments', () => {
assert.deepEqual(
ACL_DRYRUN.transformArguments('default', ['GET', 'key']),
parseArgs(ACL_DRYRUN, 'default', ['GET', 'key']),
['ACL', 'DRYRUN', 'default', 'GET', 'key']
);
});

View File

@@ -1,15 +1,11 @@
import { CommandParser } from '../client/parser';
import { RedisArgument, SimpleStringReply, BlobStringReply, Command } from '../RESP/types';
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments(username: RedisArgument, command: Array<RedisArgument>) {
return [
'ACL',
'DRYRUN',
username,
...command
];
parseCommand(parser: CommandParser, username: RedisArgument, command: Array<RedisArgument>) {
parser.push('ACL', 'DRYRUN', username, ...command);
},
transformReply: undefined as unknown as () => SimpleStringReply<'OK'> | BlobStringReply
} as const satisfies Command;

View File

@@ -1,6 +1,7 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import ACL_GENPASS from './ACL_GENPASS';
import { parseArgs } from './generic-transformers';
describe('ACL GENPASS', () => {
testUtils.isVersionGreaterThanHook([6]);
@@ -8,14 +9,14 @@ describe('ACL GENPASS', () => {
describe('transformArguments', () => {
it('simple', () => {
assert.deepEqual(
ACL_GENPASS.transformArguments(),
parseArgs(ACL_GENPASS),
['ACL', 'GENPASS']
);
});
it('with bits', () => {
assert.deepEqual(
ACL_GENPASS.transformArguments(128),
parseArgs(ACL_GENPASS, 128),
['ACL', 'GENPASS', '128']
);
});

View File

@@ -1,16 +1,14 @@
import { CommandParser } from '../client/parser';
import { BlobStringReply, Command } from '../RESP/types';
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments(bits?: number) {
const args = ['ACL', 'GENPASS'];
parseCommand(parser: CommandParser, bits?: number) {
parser.push('ACL', 'GENPASS');
if (bits) {
args.push(bits.toString());
parser.push(bits.toString());
}
return args;
},
transformReply: undefined as unknown as () => BlobStringReply
} as const satisfies Command;

View File

@@ -1,13 +1,14 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import ACL_GETUSER from './ACL_GETUSER';
import { parseArgs } from './generic-transformers';
describe('ACL GETUSER', () => {
testUtils.isVersionGreaterThanHook([6]);
it('transformArguments', () => {
assert.deepEqual(
ACL_GETUSER.transformArguments('username'),
parseArgs(ACL_GETUSER, 'username'),
['ACL', 'GETUSER', 'username']
);
});

View File

@@ -1,3 +1,4 @@
import { CommandParser } from '../client/parser';
import { RedisArgument, TuplesToMapReply, BlobStringReply, ArrayReply, UnwrapReply, Resp2Reply, Command } from '../RESP/types';
type AclUser = TuplesToMapReply<[
@@ -17,10 +18,10 @@ type AclUser = TuplesToMapReply<[
]>;
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments(username: RedisArgument) {
return ['ACL', 'GETUSER', username];
parseCommand(parser: CommandParser, username: RedisArgument) {
parser.push('ACL', 'GETUSER', username);
},
transformReply: {
2: (reply: UnwrapReply<Resp2Reply<AclUser>>) => ({

View File

@@ -1,13 +1,14 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import ACL_LIST from './ACL_LIST';
import { parseArgs } from './generic-transformers';
describe('ACL LIST', () => {
testUtils.isVersionGreaterThanHook([6]);
it('transformArguments', () => {
assert.deepEqual(
ACL_LIST.transformArguments(),
parseArgs(ACL_LIST),
['ACL', 'LIST']
);
});

View File

@@ -1,10 +1,11 @@
import { CommandParser } from '../client/parser';
import { ArrayReply, BlobStringReply, Command } from '../RESP/types';
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments() {
return ['ACL', 'LIST'];
parseCommand(parser: CommandParser) {
parser.push('ACL', 'LIST');
},
transformReply: undefined as unknown as () => ArrayReply<BlobStringReply>
} as const satisfies Command;

View File

@@ -1,13 +1,14 @@
import { strict as assert } from 'node:assert';
import testUtils from '../test-utils';
import ACL_LOAD from './ACL_LOAD';
import { parseArgs } from './generic-transformers';
describe('ACL LOAD', () => {
testUtils.isVersionGreaterThanHook([6]);
it('transformArguments', () => {
assert.deepEqual(
ACL_LOAD.transformArguments(),
parseArgs(ACL_LOAD),
['ACL', 'LOAD']
);
});

View File

@@ -1,10 +1,11 @@
import { CommandParser } from '../client/parser';
import { SimpleStringReply, Command } from '../RESP/types';
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments() {
return ['ACL', 'LOAD'];
parseCommand(parser: CommandParser) {
parser.push('ACL', 'LOAD');
},
transformReply: undefined as unknown as () => SimpleStringReply<'OK'>
} as const satisfies Command;

View File

@@ -1,6 +1,7 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import ACL_LOG from './ACL_LOG';
import { parseArgs } from './generic-transformers';
describe('ACL LOG', () => {
testUtils.isVersionGreaterThanHook([6]);
@@ -8,14 +9,14 @@ describe('ACL LOG', () => {
describe('transformArguments', () => {
it('simple', () => {
assert.deepEqual(
ACL_LOG.transformArguments(),
parseArgs(ACL_LOG),
['ACL', 'LOG']
);
});
it('with count', () => {
assert.deepEqual(
ACL_LOG.transformArguments(10),
parseArgs(ACL_LOG, 10),
['ACL', 'LOG', '10']
);
});

View File

@@ -1,3 +1,4 @@
import { CommandParser } from '../client/parser';
import { ArrayReply, TuplesToMapReply, BlobStringReply, NumberReply, DoubleReply, UnwrapReply, Resp2Reply, Command, TypeMapping } from '../RESP/types';
import { transformDoubleReply } from './generic-transformers';
@@ -18,16 +19,13 @@ export type AclLogReply = ArrayReply<TuplesToMapReply<[
]>>;
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments(count?: number) {
const args = ['ACL', 'LOG'];
if (count !== undefined) {
args.push(count.toString());
parseCommand(parser: CommandParser, count?: number) {
parser.push('ACL', 'LOG');
if (count != undefined) {
parser.push(count.toString());
}
return args;
},
transformReply: {
2: (reply: UnwrapReply<Resp2Reply<AclLogReply>>, preserve?: any, typeMapping?: TypeMapping) => {

View File

@@ -1,13 +1,14 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import ACL_LOG_RESET from './ACL_LOG_RESET';
import { parseArgs } from './generic-transformers';
describe('ACL LOG RESET', () => {
testUtils.isVersionGreaterThanHook([6]);
it('transformArguments', () => {
assert.deepEqual(
ACL_LOG_RESET.transformArguments(),
parseArgs(ACL_LOG_RESET),
['ACL', 'LOG', 'RESET']
);
});

View File

@@ -1,11 +1,12 @@
import { CommandParser } from '../client/parser';
import { SimpleStringReply, Command } from '../RESP/types';
import ACL_LOG from './ACL_LOG';
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: ACL_LOG.IS_READ_ONLY,
transformArguments() {
return ['ACL', 'LOG', 'RESET'];
parseCommand(parser: CommandParser) {
parser.push('ACL', 'LOG', 'RESET');
},
transformReply: undefined as unknown as () => SimpleStringReply<'OK'>
} as const satisfies Command;

View File

@@ -1,13 +1,14 @@
import { strict as assert } from 'node:assert';
import testUtils from '../test-utils';
import ACL_SAVE from './ACL_SAVE';
import { parseArgs } from './generic-transformers';
describe('ACL SAVE', () => {
testUtils.isVersionGreaterThanHook([6]);
it('transformArguments', () => {
assert.deepEqual(
ACL_SAVE.transformArguments(),
parseArgs(ACL_SAVE),
['ACL', 'SAVE']
);
});

View File

@@ -1,10 +1,11 @@
import { CommandParser } from '../client/parser';
import { SimpleStringReply, Command } from '../RESP/types';
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments() {
return ['ACL', 'SAVE'];
parseCommand(parser: CommandParser) {
parser.push('ACL', 'SAVE');
},
transformReply: undefined as unknown as () => SimpleStringReply<'OK'>
} as const satisfies Command;

View File

@@ -1,6 +1,7 @@
import { strict as assert } from 'node:assert';
import testUtils from '../test-utils';
import ACL_SETUSER from './ACL_SETUSER';
import { parseArgs } from './generic-transformers';
describe('ACL SETUSER', () => {
testUtils.isVersionGreaterThanHook([6]);
@@ -8,14 +9,14 @@ describe('ACL SETUSER', () => {
describe('transformArguments', () => {
it('string', () => {
assert.deepEqual(
ACL_SETUSER.transformArguments('username', 'allkeys'),
parseArgs(ACL_SETUSER, 'username', 'allkeys'),
['ACL', 'SETUSER', 'username', 'allkeys']
);
});
it('array', () => {
assert.deepEqual(
ACL_SETUSER.transformArguments('username', ['allkeys', 'allchannels']),
parseArgs(ACL_SETUSER, 'username', ['allkeys', 'allchannels']),
['ACL', 'SETUSER', 'username', 'allkeys', 'allchannels']
);
});

View File

@@ -1,11 +1,13 @@
import { CommandParser } from '../client/parser';
import { RedisArgument, SimpleStringReply, Command } from '../RESP/types';
import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers';
import { RedisVariadicArgument } from './generic-transformers';
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments(username: RedisArgument, rule: RedisVariadicArgument) {
return pushVariadicArguments(['ACL', 'SETUSER', username], rule);
parseCommand(parser: CommandParser, username: RedisArgument, rule: RedisVariadicArgument) {
parser.push('ACL', 'SETUSER', username);
parser.pushVariadic(rule);
},
transformReply: undefined as unknown as () => SimpleStringReply<'OK'>
} as const satisfies Command;

View File

@@ -1,13 +1,14 @@
import { strict as assert } from 'node:assert';
import testUtils from '../test-utils';
import ACL_USERS from './ACL_USERS';
import { parseArgs } from './generic-transformers';
describe('ACL USERS', () => {
testUtils.isVersionGreaterThanHook([6]);
it('transformArguments', () => {
assert.deepEqual(
ACL_USERS.transformArguments(),
parseArgs(ACL_USERS),
['ACL', 'USERS']
);
});

View File

@@ -1,10 +1,11 @@
import { CommandParser } from '../client/parser';
import { ArrayReply, BlobStringReply, Command } from '../RESP/types';
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments() {
return ['ACL', 'USERS'];
parseCommand(parser: CommandParser) {
parser.push('ACL', 'USERS');
},
transformReply: undefined as unknown as () => ArrayReply<BlobStringReply>
} as const satisfies Command;

View File

@@ -1,13 +1,14 @@
import { strict as assert } from 'node:assert';
import testUtils from '../test-utils';
import ACL_WHOAMI from './ACL_WHOAMI';
import { parseArgs } from './generic-transformers';
describe('ACL WHOAMI', () => {
testUtils.isVersionGreaterThanHook([6]);
it('transformArguments', () => {
assert.deepEqual(
ACL_WHOAMI.transformArguments(),
parseArgs(ACL_WHOAMI),
['ACL', 'WHOAMI']
);
});

View File

@@ -1,10 +1,11 @@
import { CommandParser } from '../client/parser';
import { BlobStringReply, Command } from '../RESP/types';
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments() {
return ['ACL', 'WHOAMI'];
parseCommand(parser: CommandParser) {
parser.push('ACL', 'WHOAMI');
},
transformReply: undefined as unknown as () => BlobStringReply
} as const satisfies Command;

View File

@@ -1,11 +1,12 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import APPEND from './APPEND';
import { parseArgs } from './generic-transformers';
describe('APPEND', () => {
it('transformArguments', () => {
assert.deepEqual(
APPEND.transformArguments('key', 'value'),
parseArgs(APPEND, 'key', 'value'),
['APPEND', 'key', 'value']
);
});

View File

@@ -1,10 +1,11 @@
import { CommandParser } from '../client/parser';
import { RedisArgument, NumberReply, Command } from '../RESP/types';
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: false,
transformArguments(key: RedisArgument, value: RedisArgument) {
return ['APPEND', key, value];
parseCommand(parser: CommandParser, key: RedisArgument, value: RedisArgument) {
parser.push('APPEND', key, value);
},
transformReply: undefined as unknown as () => NumberReply
} as const satisfies Command;

View File

@@ -1,10 +1,11 @@
import { strict as assert } from 'node:assert';
import ASKING from './ASKING';
import { parseArgs } from './generic-transformers';
describe('ASKING', () => {
it('transformArguments', () => {
assert.deepEqual(
ASKING.transformArguments(),
parseArgs(ASKING),
['ASKING']
);
});

View File

@@ -1,10 +1,13 @@
import { CommandParser } from '../client/parser';
import { SimpleStringReply, Command } from '../RESP/types';
export const ASKING_CMD = 'ASKING';
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments() {
return ['ASKING'];
parseCommand(parser: CommandParser) {
parser.push(ASKING_CMD);
},
transformReply: undefined as unknown as () => SimpleStringReply<'OK'>
} as const satisfies Command;

View File

@@ -1,11 +1,12 @@
import { strict as assert } from 'node:assert';
import AUTH from './AUTH';
import { parseArgs } from './generic-transformers';
describe('AUTH', () => {
describe('transformArguments', () => {
it('password only', () => {
assert.deepEqual(
AUTH.transformArguments({
parseArgs(AUTH, {
password: 'password'
}),
['AUTH', 'password']
@@ -14,7 +15,7 @@ describe('AUTH', () => {
it('username & password', () => {
assert.deepEqual(
AUTH.transformArguments({
parseArgs(AUTH, {
username: 'username',
password: 'password'
}),

View File

@@ -1,3 +1,4 @@
import { CommandParser } from '../client/parser';
import { RedisArgument, SimpleStringReply, Command } from '../RESP/types';
export interface AuthOptions {
@@ -6,18 +7,14 @@ export interface AuthOptions {
}
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments({ username, password }: AuthOptions) {
const args: Array<RedisArgument> = ['AUTH'];
parseCommand(parser: CommandParser, { username, password }: AuthOptions) {
parser.push('AUTH');
if (username !== undefined) {
args.push(username);
parser.push(username);
}
args.push(password);
return args;
parser.push(password);
},
transformReply: undefined as unknown as () => SimpleStringReply<'OK'>
} as const satisfies Command;

View File

@@ -1,11 +1,12 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import BGREWRITEAOF from './BGREWRITEAOF';
import { parseArgs } from './generic-transformers';
describe('BGREWRITEAOF', () => {
it('transformArguments', () => {
assert.deepEqual(
BGREWRITEAOF.transformArguments(),
parseArgs(BGREWRITEAOF),
['BGREWRITEAOF']
);
});

View File

@@ -1,10 +1,11 @@
import { CommandParser } from '../client/parser';
import { SimpleStringReply, Command } from '../RESP/types';
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments() {
return ['BGREWRITEAOF'];
parseCommand(parser: CommandParser) {
parser.push('BGREWRITEAOF');
},
transformReply: undefined as unknown as () => SimpleStringReply
} as const satisfies Command;

View File

@@ -1,19 +1,20 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import BGSAVE from './BGSAVE';
import { parseArgs } from './generic-transformers';
describe('BGSAVE', () => {
describe('transformArguments', () => {
it('simple', () => {
assert.deepEqual(
BGSAVE.transformArguments(),
parseArgs(BGSAVE),
['BGSAVE']
);
});
it('with SCHEDULE', () => {
assert.deepEqual(
BGSAVE.transformArguments({
parseArgs(BGSAVE, {
SCHEDULE: true
}),
['BGSAVE', 'SCHEDULE']

View File

@@ -1,3 +1,4 @@
import { CommandParser } from '../client/parser';
import { SimpleStringReply, Command } from '../RESP/types';
export interface BgSaveOptions {
@@ -5,16 +6,13 @@ export interface BgSaveOptions {
}
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments(options?: BgSaveOptions) {
const args = ['BGSAVE'];
parseCommand(parser: CommandParser, options?: BgSaveOptions) {
parser.push('BGSAVE');
if (options?.SCHEDULE) {
args.push('SCHEDULE');
parser.push('SCHEDULE');
}
return args;
},
transformReply: undefined as unknown as () => SimpleStringReply
} as const satisfies Command;

View File

@@ -1,12 +1,13 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import BITCOUNT from './BITCOUNT';
import { parseArgs } from './generic-transformers';
describe('BITCOUNT', () => {
describe('transformArguments', () => {
describe('parseCommand', () => {
it('simple', () => {
assert.deepEqual(
BITCOUNT.transformArguments('key'),
parseArgs(BITCOUNT, 'key'),
['BITCOUNT', 'key']
);
});
@@ -14,7 +15,7 @@ describe('BITCOUNT', () => {
describe('with range', () => {
it('simple', () => {
assert.deepEqual(
BITCOUNT.transformArguments('key', {
parseArgs(BITCOUNT, 'key', {
start: 0,
end: 1
}),
@@ -24,7 +25,7 @@ describe('BITCOUNT', () => {
it('with mode', () => {
assert.deepEqual(
BITCOUNT.transformArguments('key', {
parseArgs(BITCOUNT, 'key', {
start: 0,
end: 1,
mode: 'BIT'

View File

@@ -1,3 +1,4 @@
import { CommandParser } from '../client/parser';
import { RedisArgument, NumberReply, Command } from '../RESP/types';
export interface BitCountRange {
@@ -7,23 +8,19 @@ export interface BitCountRange {
}
export default {
FIRST_KEY_INDEX: 1,
CACHEABLE: true,
IS_READ_ONLY: true,
transformArguments(key: RedisArgument, range?: BitCountRange) {
const args = ['BITCOUNT', key];
parseCommand(parser: CommandParser, key: RedisArgument, range?: BitCountRange) {
parser.push('BITCOUNT');
parser.pushKey(key);
if (range) {
args.push(
range.start.toString(),
range.end.toString()
);
parser.push(range.start.toString());
parser.push(range.end.toString());
if (range.mode) {
args.push(range.mode);
parser.push(range.mode);
}
}
return args;
},
transformReply: undefined as unknown as () => NumberReply
} as const satisfies Command;

View File

@@ -1,11 +1,12 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import BITFIELD from './BITFIELD';
import { parseArgs } from './generic-transformers';
describe('BITFIELD', () => {
it('transformArguments', () => {
assert.deepEqual(
BITFIELD.transformArguments('key', [{
parseArgs(BITFIELD, 'key', [{
operation: 'OVERFLOW',
behavior: 'WRAP'
}, {

View File

@@ -1,3 +1,4 @@
import { CommandParser } from '../client/parser';
import { RedisArgument, ArrayReply, NumberReply, NullReply, Command } from '../RESP/types';
export type BitFieldEncoding = `${'i' | 'u'}${number}`;
@@ -39,15 +40,15 @@ export type BitFieldRoOperations = Array<
>;
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: false,
transformArguments(key: RedisArgument, operations: BitFieldOperations) {
const args = ['BITFIELD', key];
parseCommand(parser: CommandParser, key: RedisArgument, operations: BitFieldOperations) {
parser.push('BITFIELD');
parser.pushKey(key);
for (const options of operations) {
switch (options.operation) {
case 'GET':
args.push(
parser.push(
'GET',
options.encoding,
options.offset.toString()
@@ -55,7 +56,7 @@ export default {
break;
case 'SET':
args.push(
parser.push(
'SET',
options.encoding,
options.offset.toString(),
@@ -64,7 +65,7 @@ export default {
break;
case 'INCRBY':
args.push(
parser.push(
'INCRBY',
options.encoding,
options.offset.toString(),
@@ -73,15 +74,13 @@ export default {
break;
case 'OVERFLOW':
args.push(
parser.push(
'OVERFLOW',
options.behavior
);
break;
}
}
return args;
},
transformReply: undefined as unknown as () => ArrayReply<NumberReply | NullReply>
} as const satisfies Command;

View File

@@ -1,13 +1,14 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import BITFIELD_RO from './BITFIELD_RO';
import { parseArgs } from './generic-transformers';
describe('BITFIELD_RO', () => {
testUtils.isVersionGreaterThanHook([6, 2]);
it('transformArguments', () => {
it('parseCommand', () => {
assert.deepEqual(
BITFIELD_RO.transformArguments('key', [{
parseArgs(BITFIELD_RO, 'key', [{
encoding: 'i8',
offset: 0
}]),

View File

@@ -1,3 +1,4 @@
import { CommandParser } from '../client/parser';
import { RedisArgument, ArrayReply, NumberReply, Command } from '../RESP/types';
import { BitFieldGetOperation } from './BITFIELD';
@@ -6,20 +7,17 @@ export type BitFieldRoOperations = Array<
>;
export default {
FIRST_KEY_INDEX: 1,
CACHEABLE: true,
IS_READ_ONLY: true,
transformArguments(key: RedisArgument, operations: BitFieldRoOperations) {
const args = ['BITFIELD_RO', key];
parseCommand(parser: CommandParser, key: RedisArgument, operations: BitFieldRoOperations) {
parser.push('BITFIELD_RO');
parser.pushKey(key);
for (const operation of operations) {
args.push(
'GET',
operation.encoding,
operation.offset.toString()
);
parser.push('GET');
parser.push(operation.encoding);
parser.push(operation.offset.toString())
}
return args;
},
transformReply: undefined as unknown as () => ArrayReply<NumberReply>
} as const satisfies Command;

View File

@@ -1,19 +1,20 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import BITOP from './BITOP';
import { parseArgs } from './generic-transformers';
describe('BITOP', () => {
describe('transformArguments', () => {
it('single key', () => {
assert.deepEqual(
BITOP.transformArguments('AND', 'destKey', 'key'),
parseArgs(BITOP, 'AND', 'destKey', 'key'),
['BITOP', 'AND', 'destKey', 'key']
);
});
it('multiple keys', () => {
assert.deepEqual(
BITOP.transformArguments('AND', 'destKey', ['1', '2']),
parseArgs(BITOP, 'AND', 'destKey', ['1', '2']),
['BITOP', 'AND', 'destKey', '1', '2']
);
});

View File

@@ -1,17 +1,20 @@
import { CommandParser } from '../client/parser';
import { NumberReply, Command, RedisArgument } from '../RESP/types';
import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers';
import { RedisVariadicArgument } from './generic-transformers';
export type BitOperations = 'AND' | 'OR' | 'XOR' | 'NOT';
export default {
FIRST_KEY_INDEX: 2,
IS_READ_ONLY: false,
transformArguments(
parseCommand(
parser: CommandParser,
operation: BitOperations,
destKey: RedisArgument,
key: RedisVariadicArgument
) {
return pushVariadicArguments(['BITOP', operation, destKey], key);
parser.push('BITOP', operation);
parser.pushKey(destKey);
parser.pushKeys(key);
},
transformReply: undefined as unknown as () => NumberReply
} as const satisfies Command;

View File

@@ -1,33 +1,34 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import BITPOS from './BITPOS';
import { parseArgs } from './generic-transformers';
describe('BITPOS', () => {
describe('transformArguments', () => {
describe('parseCommand', () => {
it('simple', () => {
assert.deepEqual(
BITPOS.transformArguments('key', 1),
parseArgs(BITPOS, 'key', 1),
['BITPOS', 'key', '1']
);
});
it('with start', () => {
assert.deepEqual(
BITPOS.transformArguments('key', 1, 1),
parseArgs(BITPOS, 'key', 1, 1),
['BITPOS', 'key', '1', '1']
);
});
it('with start and end', () => {
assert.deepEqual(
BITPOS.transformArguments('key', 1, 1, -1),
parseArgs(BITPOS, 'key', 1, 1, -1),
['BITPOS', 'key', '1', '1', '-1']
);
});
it('with start, end and mode', () => {
assert.deepEqual(
BITPOS.transformArguments('key', 1, 1, -1, 'BIT'),
parseArgs(BITPOS, 'key', 1, 1, -1, 'BIT'),
['BITPOS', 'key', '1', '1', '-1', 'BIT']
);
});

View File

@@ -1,31 +1,32 @@
import { CommandParser } from '../client/parser';
import { RedisArgument, NumberReply, Command } from '../RESP/types';
import { BitValue } from './generic-transformers';
export default {
FIRST_KEY_INDEX: 1,
CACHEABLE: true,
IS_READ_ONLY: true,
transformArguments(
parseCommand(parser: CommandParser,
key: RedisArgument,
bit: BitValue,
start?: number,
end?: number,
mode?: 'BYTE' | 'BIT'
) {
const args = ['BITPOS', key, bit.toString()];
parser.push('BITPOS');
parser.pushKey(key);
parser.push(bit.toString());
if (start !== undefined) {
args.push(start.toString());
parser.push(start.toString());
}
if (end !== undefined) {
args.push(end.toString());
parser.push(end.toString());
}
if (mode) {
args.push(mode);
parser.push(mode);
}
return args;
},
transformReply: undefined as unknown as () => NumberReply
} as const satisfies Command;

View File

@@ -1,13 +1,14 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL, BLOCKING_MIN_VALUE } from '../test-utils';
import BLMOVE from './BLMOVE';
import { parseArgs } from './generic-transformers';
describe('BLMOVE', () => {
testUtils.isVersionGreaterThanHook([6, 2]);
it('transformArguments', () => {
assert.deepEqual(
BLMOVE.transformArguments('source', 'destination', 'LEFT', 'RIGHT', 0),
parseArgs(BLMOVE, 'source', 'destination', 'LEFT', 'RIGHT', 0),
['BLMOVE', 'source', 'destination', 'LEFT', 'RIGHT', '0']
);
});

View File

@@ -1,24 +1,20 @@
import { CommandParser } from '../client/parser';
import { RedisArgument, BlobStringReply, NullReply, Command } from '../RESP/types';
import { ListSide } from './generic-transformers';
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: false,
transformArguments(
parseCommand(
parser: CommandParser,
source: RedisArgument,
destination: RedisArgument,
sourceSide: ListSide,
destinationSide: ListSide,
timeout: number
) {
return [
'BLMOVE',
source,
destination,
sourceSide,
destinationSide,
timeout.toString()
];
parser.push('BLMOVE');
parser.pushKeys([source, destination]);
parser.push(sourceSide, destinationSide, timeout.toString())
},
transformReply: undefined as unknown as () => BlobStringReply | NullReply
} as const satisfies Command;

View File

@@ -1,6 +1,7 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL, BLOCKING_MIN_VALUE } from '../test-utils';
import BLMPOP from './BLMPOP';
import { parseArgs } from './generic-transformers';
describe('BLMPOP', () => {
testUtils.isVersionGreaterThanHook([7]);
@@ -8,14 +9,14 @@ describe('BLMPOP', () => {
describe('transformArguments', () => {
it('simple', () => {
assert.deepEqual(
BLMPOP.transformArguments(0, 'key', 'LEFT'),
parseArgs(BLMPOP, 0, 'key', 'LEFT'),
['BLMPOP', '0', '1', 'key', 'LEFT']
);
});
it('with COUNT', () => {
assert.deepEqual(
BLMPOP.transformArguments(0, 'key', 'LEFT', {
parseArgs(BLMPOP, 0, 'key', 'LEFT', {
COUNT: 1
}),
['BLMPOP', '0', '1', 'key', 'LEFT', 'COUNT', '1']

View File

@@ -1,17 +1,12 @@
import { CommandParser } from '../client/parser';
import { Command } from '../RESP/types';
import LMPOP, { LMPopArguments, transformLMPopArguments } from './LMPOP';
import LMPOP, { LMPopArguments, parseLMPopArguments } from './LMPOP';
export default {
FIRST_KEY_INDEX: 3,
IS_READ_ONLY: false,
transformArguments(
timeout: number,
...args: LMPopArguments
) {
return transformLMPopArguments(
['BLMPOP', timeout.toString()],
...args
);
},
parseCommand(parser: CommandParser, timeout: number, ...args: LMPopArguments) {
parser.push('BLMPOP', timeout.toString());
parseLMPopArguments(parser, ...args);
},
transformReply: LMPOP.transformReply
} as const satisfies Command;

View File

@@ -1,19 +1,20 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL, BLOCKING_MIN_VALUE } from '../test-utils';
import BLPOP from './BLPOP';
import { parseArgs } from './generic-transformers';
describe('BLPOP', () => {
describe('transformArguments', () => {
it('single', () => {
assert.deepEqual(
BLPOP.transformArguments('key', 0),
parseArgs(BLPOP, 'key', 0),
['BLPOP', 'key', '0']
);
});
it('multiple', () => {
assert.deepEqual(
BLPOP.transformArguments(['1', '2'], 0),
parseArgs(BLPOP, ['1', '2'], 0),
['BLPOP', '1', '2', '0']
);
});

View File

@@ -1,16 +1,13 @@
import { CommandParser } from '../client/parser';
import { UnwrapReply, NullReply, TuplesReply, BlobStringReply, Command } from '../RESP/types';
import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers';
import { RedisVariadicArgument } from './generic-transformers';
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: true,
transformArguments(
key: RedisVariadicArgument,
timeout: number
) {
const args = pushVariadicArguments(['BLPOP'], key);
args.push(timeout.toString());
return args;
parseCommand(parser: CommandParser, key: RedisVariadicArgument, timeout: number) {
parser.push('BLPOP');
parser.pushKeys(key);
parser.push(timeout.toString());
},
transformReply(reply: UnwrapReply<NullReply | TuplesReply<[BlobStringReply, BlobStringReply]>>) {
if (reply === null) return null;

View File

@@ -1,19 +1,20 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL, BLOCKING_MIN_VALUE } from '../test-utils';
import BRPOP from './BRPOP';
import { parseArgs } from './generic-transformers';
describe('BRPOP', () => {
describe('transformArguments', () => {
it('single', () => {
assert.deepEqual(
BRPOP.transformArguments('key', 0),
parseArgs(BRPOP, 'key', 0),
['BRPOP', 'key', '0']
);
});
it('multiple', () => {
assert.deepEqual(
BRPOP.transformArguments(['1', '2'], 0),
parseArgs(BRPOP, ['1', '2'], 0),
['BRPOP', '1', '2', '0']
);
});

View File

@@ -1,17 +1,14 @@
import { CommandParser } from '../client/parser';
import { Command } from '../RESP/types';
import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers';
import { RedisVariadicArgument } from './generic-transformers';
import BLPOP from './BLPOP';
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: true,
transformArguments(
key: RedisVariadicArgument,
timeout: number
) {
const args = pushVariadicArguments(['BRPOP'], key);
args.push(timeout.toString());
return args;
parseCommand(parser: CommandParser, key: RedisVariadicArgument, timeout: number) {
parser.push('BRPOP');
parser.pushKeys(key);
parser.push(timeout.toString());
},
transformReply: BLPOP.transformReply
} as const satisfies Command;

View File

@@ -1,11 +1,12 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL, BLOCKING_MIN_VALUE } from '../test-utils';
import BRPOPLPUSH from './BRPOPLPUSH';
import { parseArgs } from './generic-transformers';
describe('BRPOPLPUSH', () => {
it('transformArguments', () => {
assert.deepEqual(
BRPOPLPUSH.transformArguments('source', 'destination', 0),
parseArgs(BRPOPLPUSH, 'source', 'destination', 0),
['BRPOPLPUSH', 'source', 'destination', '0']
);
});

View File

@@ -1,14 +1,12 @@
import { CommandParser } from '../client/parser';
import { RedisArgument, BlobStringReply, NullReply, Command } from '../RESP/types';
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: false,
transformArguments(
source: RedisArgument,
destination: RedisArgument,
timeout: number
) {
return ['BRPOPLPUSH', source, destination, timeout.toString()];
parseCommand(parser: CommandParser, source: RedisArgument, destination: RedisArgument, timeout: number) {
parser.push('BRPOPLPUSH');
parser.pushKeys([source, destination]);
parser.push(timeout.toString());
},
transformReply: undefined as unknown as () => BlobStringReply | NullReply
} as const satisfies Command;

View File

@@ -1,6 +1,7 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL, BLOCKING_MIN_VALUE } from '../test-utils';
import BZMPOP from './BZMPOP';
import { parseArgs } from './generic-transformers';
describe('BZMPOP', () => {
testUtils.isVersionGreaterThanHook([7]);
@@ -8,14 +9,14 @@ describe('BZMPOP', () => {
describe('transformArguments', () => {
it('simple', () => {
assert.deepEqual(
BZMPOP.transformArguments(0, 'key', 'MIN'),
parseArgs(BZMPOP, 0, 'key', 'MIN'),
['BZMPOP', '0', '1', 'key', 'MIN']
);
});
it('with COUNT', () => {
assert.deepEqual(
BZMPOP.transformArguments(0, 'key', 'MIN', {
parseArgs(BZMPOP, 0, 'key', 'MIN', {
COUNT: 2
}),
['BZMPOP', '0', '1', 'key', 'MIN', 'COUNT', '2']

View File

@@ -1,11 +1,12 @@
import { CommandParser } from '../client/parser';
import { Command } from '../RESP/types';
import ZMPOP, { ZMPopArguments, transformZMPopArguments } from './ZMPOP';
import ZMPOP, { parseZMPopArguments, ZMPopArguments } from './ZMPOP';
export default {
FIRST_KEY_INDEX: 3,
IS_READ_ONLY: false,
transformArguments(timeout: number, ...args: ZMPopArguments) {
return transformZMPopArguments(['BZMPOP', timeout.toString()], ...args);
parseCommand(parser: CommandParser, timeout: number, ...args: ZMPopArguments) {
parser.push('BZMPOP', timeout.toString());
parseZMPopArguments(parser, ...args);
},
transformReply: ZMPOP.transformReply
} as const satisfies Command;

View File

@@ -1,19 +1,20 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL, BLOCKING_MIN_VALUE } from '../test-utils';
import BZPOPMAX from './BZPOPMAX';
import { parseArgs } from './generic-transformers';
describe('BZPOPMAX', () => {
describe('transformArguments', () => {
it('single', () => {
assert.deepEqual(
BZPOPMAX.transformArguments('key', 0),
parseArgs(BZPOPMAX, 'key', 0),
['BZPOPMAX', 'key', '0']
);
});
it('multiple', () => {
assert.deepEqual(
BZPOPMAX.transformArguments(['1', '2'], 0),
parseArgs(BZPOPMAX, ['1', '2'], 0),
['BZPOPMAX', '1', '2', '0']
);
});

View File

@@ -1,23 +1,13 @@
import { RedisArgument, NullReply, TuplesReply, BlobStringReply, DoubleReply, UnwrapReply, Command, TypeMapping } from '../RESP/types';
import { RedisVariadicArgument, pushVariadicArguments, transformDoubleReply } from './generic-transformers';
export function transformBZPopArguments(
command: RedisArgument,
key: RedisVariadicArgument,
timeout: number
) {
const args = pushVariadicArguments([command], key);
args.push(timeout.toString());
return args;
}
export type BZPopArguments = typeof transformBZPopArguments extends (_: any, ...args: infer T) => any ? T : never;
import { CommandParser } from '../client/parser';
import { NullReply, TuplesReply, BlobStringReply, DoubleReply, UnwrapReply, Command, TypeMapping } from '../RESP/types';
import { RedisVariadicArgument, transformDoubleReply } from './generic-transformers';
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: false,
transformArguments(...args: BZPopArguments) {
return transformBZPopArguments('BZPOPMAX', ...args);
parseCommand(parser: CommandParser, keys: RedisVariadicArgument, timeout: number) {
parser.push('BZPOPMAX');
parser.pushKeys(keys);
parser.push(timeout.toString());
},
transformReply: {
2(

View File

@@ -1,19 +1,20 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL, BLOCKING_MIN_VALUE } from '../test-utils';
import BZPOPMIN from './BZPOPMIN';
import { parseArgs } from './generic-transformers';
describe('BZPOPMIN', () => {
describe('transformArguments', () => {
it('single', () => {
assert.deepEqual(
BZPOPMIN.transformArguments('key', 0),
parseArgs(BZPOPMIN, 'key', 0),
['BZPOPMIN', 'key', '0']
);
});
it('multiple', () => {
assert.deepEqual(
BZPOPMIN.transformArguments(['1', '2'], 0),
parseArgs(BZPOPMIN, ['1', '2'], 0),
['BZPOPMIN', '1', '2', '0']
);
});

View File

@@ -1,11 +1,14 @@
import { CommandParser } from '../client/parser';
import { Command } from '../RESP/types';
import BZPOPMAX, { BZPopArguments, transformBZPopArguments } from './BZPOPMAX';
import { RedisVariadicArgument } from './generic-transformers';
import BZPOPMAX from './BZPOPMAX';
export default {
FIRST_KEY_INDEX: BZPOPMAX.FIRST_KEY_INDEX,
IS_READ_ONLY: BZPOPMAX.IS_READ_ONLY,
transformArguments(...args: BZPopArguments) {
return transformBZPopArguments('BZPOPMIN', ...args);
parseCommand(parser: CommandParser, keys: RedisVariadicArgument, timeout: number) {
parser.push('BZPOPMIN');
parser.pushKeys(keys);
parser.push(timeout.toString());
},
transformReply: BZPOPMAX.transformReply
} as const satisfies Command;

View File

@@ -1,18 +1,19 @@
import { strict as assert } from 'node:assert';
import CLIENT_CACHING from './CLIENT_CACHING';
import { parseArgs } from './generic-transformers';
describe('CLIENT CACHING', () => {
describe('transformArguments', () => {
it('true', () => {
assert.deepEqual(
CLIENT_CACHING.transformArguments(true),
parseArgs(CLIENT_CACHING, true),
['CLIENT', 'CACHING', 'YES']
);
});
it('false', () => {
assert.deepEqual(
CLIENT_CACHING.transformArguments(false),
parseArgs(CLIENT_CACHING, false),
['CLIENT', 'CACHING', 'NO']
);
});

View File

@@ -1,14 +1,15 @@
import { CommandParser } from '../client/parser';
import { SimpleStringReply, Command } from '../RESP/types';
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments(value: boolean) {
return [
parseCommand(parser: CommandParser, value: boolean) {
parser.push(
'CLIENT',
'CACHING',
value ? 'YES' : 'NO'
];
);
},
transformReply: undefined as unknown as () => SimpleStringReply<'OK'>
} as const satisfies Command;

View File

@@ -1,11 +1,12 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import CLIENT_GETNAME from './CLIENT_GETNAME';
import { parseArgs } from './generic-transformers';
describe('CLIENT GETNAME', () => {
it('transformArguments', () => {
assert.deepEqual(
CLIENT_GETNAME.transformArguments(),
parseArgs(CLIENT_GETNAME),
['CLIENT', 'GETNAME']
);
});

View File

@@ -1,13 +1,11 @@
import { CommandParser } from '../client/parser';
import { BlobStringReply, NullReply, Command } from '../RESP/types';
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments() {
return [
'CLIENT',
'GETNAME'
];
parseCommand(parser: CommandParser) {
parser.push('CLIENT', 'GETNAME');
},
transformReply: undefined as unknown as () => BlobStringReply | NullReply
} as const satisfies Command;

View File

@@ -1,10 +1,11 @@
import { strict as assert } from 'node:assert';
import CLIENT_GETREDIR from './CLIENT_GETREDIR';
import { parseArgs } from './generic-transformers';
describe('CLIENT GETREDIR', () => {
it('transformArguments', () => {
assert.deepEqual(
CLIENT_GETREDIR.transformArguments(),
parseArgs(CLIENT_GETREDIR),
['CLIENT', 'GETREDIR']
);
});

View File

@@ -1,10 +1,11 @@
import { CommandParser } from '../client/parser';
import { NumberReply, Command } from '../RESP/types';
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments() {
return ['CLIENT', 'GETREDIR']
parseCommand(parser: CommandParser) {
parser.push('CLIENT', 'GETREDIR');
},
transformReply: undefined as unknown as () => NumberReply
} as const satisfies Command;

View File

@@ -1,11 +1,12 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import CLIENT_ID from './CLIENT_ID';
import { parseArgs } from './generic-transformers';
describe('CLIENT ID', () => {
it('transformArguments', () => {
assert.deepEqual(
CLIENT_ID.transformArguments(),
parseArgs(CLIENT_ID),
['CLIENT', 'ID']
);
});

View File

@@ -1,10 +1,11 @@
import { CommandParser } from '../client/parser';
import { NumberReply, Command } from '../RESP/types';
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments() {
return ['CLIENT', 'ID'];
parseCommand(parser: CommandParser) {
parser.push('CLIENT', 'ID');
},
transformReply: undefined as unknown as () => NumberReply
} as const satisfies Command;

View File

@@ -1,13 +1,14 @@
import { strict as assert } from 'node:assert';
import CLIENT_INFO from './CLIENT_INFO';
import testUtils, { GLOBAL } from '../test-utils';
import { parseArgs } from './generic-transformers';
describe('CLIENT INFO', () => {
testUtils.isVersionGreaterThanHook([6, 2]);
it('transformArguments', () => {
assert.deepEqual(
CLIENT_INFO.transformArguments(),
parseArgs(CLIENT_INFO),
['CLIENT', 'INFO']
);
});

View File

@@ -1,3 +1,4 @@
import { CommandParser } from '../client/parser';
import { Command, VerbatimStringReply } from '../RESP/types';
export interface ClientInfoReply {
@@ -56,10 +57,10 @@ export interface ClientInfoReply {
const CLIENT_INFO_REGEX = /([^\s=]+)=([^\s]*)/g;
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments() {
return ['CLIENT', 'INFO']
parseCommand(parser: CommandParser) {
parser.push('CLIENT', 'INFO');
},
transformReply(rawReply: VerbatimStringReply) {
const map: Record<string, string> = {};

View File

@@ -1,11 +1,12 @@
import { strict as assert } from 'node:assert';
import CLIENT_KILL, { CLIENT_KILL_FILTERS } from './CLIENT_KILL';
import { parseArgs } from './generic-transformers';
describe('CLIENT KILL', () => {
describe('transformArguments', () => {
it('ADDRESS', () => {
assert.deepEqual(
CLIENT_KILL.transformArguments({
parseArgs(CLIENT_KILL, {
filter: CLIENT_KILL_FILTERS.ADDRESS,
address: 'ip:6379'
}),
@@ -15,7 +16,7 @@ describe('CLIENT KILL', () => {
it('LOCAL_ADDRESS', () => {
assert.deepEqual(
CLIENT_KILL.transformArguments({
parseArgs(CLIENT_KILL, {
filter: CLIENT_KILL_FILTERS.LOCAL_ADDRESS,
localAddress: 'ip:6379'
}),
@@ -26,7 +27,7 @@ describe('CLIENT KILL', () => {
describe('ID', () => {
it('string', () => {
assert.deepEqual(
CLIENT_KILL.transformArguments({
parseArgs(CLIENT_KILL, {
filter: CLIENT_KILL_FILTERS.ID,
id: '1'
}),
@@ -36,7 +37,7 @@ describe('CLIENT KILL', () => {
it('number', () => {
assert.deepEqual(
CLIENT_KILL.transformArguments({
parseArgs(CLIENT_KILL, {
filter: CLIENT_KILL_FILTERS.ID,
id: 1
}),
@@ -47,7 +48,7 @@ describe('CLIENT KILL', () => {
it('TYPE', () => {
assert.deepEqual(
CLIENT_KILL.transformArguments({
parseArgs(CLIENT_KILL, {
filter: CLIENT_KILL_FILTERS.TYPE,
type: 'master'
}),
@@ -57,7 +58,7 @@ describe('CLIENT KILL', () => {
it('USER', () => {
assert.deepEqual(
CLIENT_KILL.transformArguments({
parseArgs(CLIENT_KILL, {
filter: CLIENT_KILL_FILTERS.USER,
username: 'username'
}),
@@ -67,7 +68,7 @@ describe('CLIENT KILL', () => {
it('MAXAGE', () => {
assert.deepEqual(
CLIENT_KILL.transformArguments({
parseArgs(CLIENT_KILL, {
filter: CLIENT_KILL_FILTERS.MAXAGE,
maxAge: 10
}),
@@ -78,14 +79,14 @@ describe('CLIENT KILL', () => {
describe('SKIP_ME', () => {
it('undefined', () => {
assert.deepEqual(
CLIENT_KILL.transformArguments(CLIENT_KILL_FILTERS.SKIP_ME),
parseArgs(CLIENT_KILL, CLIENT_KILL_FILTERS.SKIP_ME),
['CLIENT', 'KILL', 'SKIPME']
);
});
it('true', () => {
assert.deepEqual(
CLIENT_KILL.transformArguments({
parseArgs(CLIENT_KILL, {
filter: CLIENT_KILL_FILTERS.SKIP_ME,
skipMe: true
}),
@@ -95,7 +96,7 @@ describe('CLIENT KILL', () => {
it('false', () => {
assert.deepEqual(
CLIENT_KILL.transformArguments({
parseArgs(CLIENT_KILL, {
filter: CLIENT_KILL_FILTERS.SKIP_ME,
skipMe: false
}),
@@ -106,7 +107,7 @@ describe('CLIENT KILL', () => {
it('TYPE & SKIP_ME', () => {
assert.deepEqual(
CLIENT_KILL.transformArguments([
parseArgs(CLIENT_KILL, [
{
filter: CLIENT_KILL_FILTERS.TYPE,
type: 'master'

View File

@@ -1,4 +1,5 @@
import { RedisArgument, NumberReply, Command } from '../RESP/types';
import { CommandParser } from '../client/parser';
import { NumberReply, Command } from '../RESP/types';
export const CLIENT_KILL_FILTERS = {
ADDRESS: 'ADDR',
@@ -47,43 +48,42 @@ export interface ClientKillMaxAge extends ClientKillFilterCommon<CLIENT_KILL_FIL
export type ClientKillFilter = ClientKillAddress | ClientKillLocalAddress | ClientKillId | ClientKillType | ClientKillUser | ClientKillSkipMe | ClientKillMaxAge;
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments(filters: ClientKillFilter | Array<ClientKillFilter>) {
const args = ['CLIENT', 'KILL'];
parseCommand(parser: CommandParser, filters: ClientKillFilter | Array<ClientKillFilter>) {
parser.push('CLIENT', 'KILL');
if (Array.isArray(filters)) {
for (const filter of filters) {
pushFilter(args, filter);
pushFilter(parser, filter);
}
} else {
pushFilter(args, filters);
pushFilter(parser, filters);
}
return args;
},
transformReply: undefined as unknown as () => NumberReply
} as const satisfies Command;
function pushFilter(args: Array<RedisArgument>, filter: ClientKillFilter): void {
function pushFilter(parser: CommandParser, filter: ClientKillFilter): void {
if (filter === CLIENT_KILL_FILTERS.SKIP_ME) {
args.push('SKIPME');
parser.push('SKIPME');
return;
}
args.push(filter.filter);
parser.push(filter.filter);
switch (filter.filter) {
case CLIENT_KILL_FILTERS.ADDRESS:
args.push(filter.address);
parser.push(filter.address);
break;
case CLIENT_KILL_FILTERS.LOCAL_ADDRESS:
args.push(filter.localAddress);
parser.push(filter.localAddress);
break;
case CLIENT_KILL_FILTERS.ID:
args.push(
parser.push(
typeof filter.id === 'number' ?
filter.id.toString() :
filter.id
@@ -91,19 +91,19 @@ function pushFilter(args: Array<RedisArgument>, filter: ClientKillFilter): void
break;
case CLIENT_KILL_FILTERS.TYPE:
args.push(filter.type);
parser.push(filter.type);
break;
case CLIENT_KILL_FILTERS.USER:
args.push(filter.username);
parser.push(filter.username);
break;
case CLIENT_KILL_FILTERS.SKIP_ME:
args.push(filter.skipMe ? 'yes' : 'no');
parser.push(filter.skipMe ? 'yes' : 'no');
break;
case CLIENT_KILL_FILTERS.MAXAGE:
args.push(filter.maxAge.toString());
parser.push(filter.maxAge.toString());
break;
}
}

View File

@@ -1,19 +1,20 @@
import { strict as assert } from 'node:assert';
import CLIENT_LIST from './CLIENT_LIST';
import testUtils, { GLOBAL } from '../test-utils';
import { parseArgs } from './generic-transformers';
describe('CLIENT LIST', () => {
describe('transformArguments', () => {
it('simple', () => {
assert.deepEqual(
CLIENT_LIST.transformArguments(),
parseArgs(CLIENT_LIST),
['CLIENT', 'LIST']
);
});
it('with TYPE', () => {
assert.deepEqual(
CLIENT_LIST.transformArguments({
parseArgs(CLIENT_LIST, {
TYPE: 'NORMAL'
}),
['CLIENT', 'LIST', 'TYPE', 'NORMAL']
@@ -22,7 +23,7 @@ describe('CLIENT LIST', () => {
it('with ID', () => {
assert.deepEqual(
CLIENT_LIST.transformArguments({
parseArgs(CLIENT_LIST, {
ID: ['1', '2']
}),
['CLIENT', 'LIST', 'ID', '1', '2']

View File

@@ -1,5 +1,5 @@
import { CommandParser } from '../client/parser';
import { RedisArgument, VerbatimStringReply, Command } from '../RESP/types';
import { pushVariadicArguments } from './generic-transformers';
import CLIENT_INFO, { ClientInfoReply } from './CLIENT_INFO';
export interface ListFilterType {
@@ -15,21 +15,18 @@ export interface ListFilterId {
export type ListFilter = ListFilterType | ListFilterId;
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments(filter?: ListFilter) {
let args: Array<RedisArgument> = ['CLIENT', 'LIST'];
parseCommand(parser: CommandParser, filter?: ListFilter) {
parser.push('CLIENT', 'LIST');
if (filter) {
if (filter.TYPE !== undefined) {
args.push('TYPE', filter.TYPE);
parser.push('TYPE', filter.TYPE);
} else {
args.push('ID');
args = pushVariadicArguments(args, filter.ID);
parser.push('ID');
parser.pushVariadic(filter.ID);
}
}
return args;
},
transformReply(rawReply: VerbatimStringReply): Array<ClientInfoReply> {
const split = rawReply.toString().split('\n'),

View File

@@ -1,6 +1,7 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import CLIENT_NO_EVICT from './CLIENT_NO-EVICT';
import { parseArgs } from './generic-transformers';
describe('CLIENT NO-EVICT', () => {
testUtils.isVersionGreaterThanHook([7]);
@@ -8,14 +9,14 @@ describe('CLIENT NO-EVICT', () => {
describe('transformArguments', () => {
it('true', () => {
assert.deepEqual(
CLIENT_NO_EVICT.transformArguments(true),
parseArgs(CLIENT_NO_EVICT, true),
['CLIENT', 'NO-EVICT', 'ON']
);
});
it('false', () => {
assert.deepEqual(
CLIENT_NO_EVICT.transformArguments(false),
parseArgs(CLIENT_NO_EVICT, false),
['CLIENT', 'NO-EVICT', 'OFF']
);
});

View File

@@ -1,14 +1,15 @@
import { CommandParser } from '../client/parser';
import { SimpleStringReply, Command } from '../RESP/types';
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments(value: boolean) {
return [
parseCommand(parser: CommandParser, value: boolean) {
parser.push(
'CLIENT',
'NO-EVICT',
value ? 'ON' : 'OFF'
];
);
},
transformReply: undefined as unknown as () => SimpleStringReply<'OK'>
} as const satisfies Command;

View File

@@ -1,6 +1,7 @@
import { strict as assert } from 'assert';
import testUtils, { GLOBAL } from '../test-utils';
import CLIENT_NO_TOUCH from './CLIENT_NO-TOUCH';
import { parseArgs } from './generic-transformers';
describe('CLIENT NO-TOUCH', () => {
testUtils.isVersionGreaterThanHook([7, 2]);
@@ -8,14 +9,14 @@ describe('CLIENT NO-TOUCH', () => {
describe('transformArguments', () => {
it('true', () => {
assert.deepEqual(
CLIENT_NO_TOUCH.transformArguments(true),
parseArgs(CLIENT_NO_TOUCH, true),
['CLIENT', 'NO-TOUCH', 'ON']
);
});
it('false', () => {
assert.deepEqual(
CLIENT_NO_TOUCH.transformArguments(false),
parseArgs(CLIENT_NO_TOUCH, false),
['CLIENT', 'NO-TOUCH', 'OFF']
);
});

View File

@@ -1,14 +1,15 @@
import { CommandParser } from '../client/parser';
import { SimpleStringReply, Command } from '../RESP/types';
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments(value: boolean) {
return [
parseCommand(parser: CommandParser, value: boolean) {
parser.push(
'CLIENT',
'NO-TOUCH',
value ? 'ON' : 'OFF'
];
);
},
transformReply: undefined as unknown as () => SimpleStringReply<'OK'>
} as const satisfies Command;

View File

@@ -1,19 +1,20 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import CLIENT_PAUSE from './CLIENT_PAUSE';
import { parseArgs } from './generic-transformers';
describe('CLIENT PAUSE', () => {
describe('transformArguments', () => {
it('simple', () => {
assert.deepEqual(
CLIENT_PAUSE.transformArguments(0),
parseArgs(CLIENT_PAUSE, 0),
['CLIENT', 'PAUSE', '0']
);
});
it('with mode', () => {
assert.deepEqual(
CLIENT_PAUSE.transformArguments(0, 'ALL'),
parseArgs(CLIENT_PAUSE, 0, 'ALL'),
['CLIENT', 'PAUSE', '0', 'ALL']
);
});

View File

@@ -1,20 +1,14 @@
import { CommandParser } from '../client/parser';
import { SimpleStringReply, Command } from '../RESP/types';
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments(timeout: number, mode?: 'WRITE' | 'ALL') {
const args = [
'CLIENT',
'PAUSE',
timeout.toString()
];
parseCommand(parser: CommandParser, timeout: number, mode?: 'WRITE' | 'ALL') {
parser.push('CLIENT', 'PAUSE', timeout.toString());
if (mode) {
args.push(mode);
parser.push(mode);
}
return args;
},
transformReply: undefined as unknown as () => SimpleStringReply<'OK'>
} as const satisfies Command;

View File

@@ -2,11 +2,12 @@ import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import CLIENT_SETNAME from './CLIENT_SETNAME';
import { parseArgs } from './generic-transformers';
describe('CLIENT SETNAME', () => {
it('transformArguments', () => {
assert.deepEqual(
CLIENT_SETNAME.transformArguments('name'),
parseArgs(CLIENT_SETNAME, 'name'),
['CLIENT', 'SETNAME', 'name']
);
});

View File

@@ -1,10 +1,11 @@
import { CommandParser } from '../client/parser';
import { RedisArgument, SimpleStringReply, Command } from '../RESP/types';
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments(name: RedisArgument) {
return ['CLIENT', 'SETNAME', name];
parseCommand(parser: CommandParser, name: RedisArgument) {
parser.push('CLIENT', 'SETNAME', name);
},
transformReply: undefined as unknown as () => SimpleStringReply<'OK'>
} as const satisfies Command;

View File

@@ -1,6 +1,7 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import CLIENT_TRACKING from './CLIENT_TRACKING';
import { parseArgs } from './generic-transformers';
describe('CLIENT TRACKING', () => {
testUtils.isVersionGreaterThanHook([6]);
@@ -9,14 +10,14 @@ describe('CLIENT TRACKING', () => {
describe('true', () => {
it('simple', () => {
assert.deepEqual(
CLIENT_TRACKING.transformArguments(true),
parseArgs(CLIENT_TRACKING, true),
['CLIENT', 'TRACKING', 'ON']
);
});
it('with REDIRECT', () => {
assert.deepEqual(
CLIENT_TRACKING.transformArguments(true, {
parseArgs(CLIENT_TRACKING, true, {
REDIRECT: 1
}),
['CLIENT', 'TRACKING', 'ON', 'REDIRECT', '1']
@@ -26,7 +27,7 @@ describe('CLIENT TRACKING', () => {
describe('with BCAST', () => {
it('simple', () => {
assert.deepEqual(
CLIENT_TRACKING.transformArguments(true, {
parseArgs(CLIENT_TRACKING, true, {
BCAST: true
}),
['CLIENT', 'TRACKING', 'ON', 'BCAST']
@@ -36,7 +37,7 @@ describe('CLIENT TRACKING', () => {
describe('with PREFIX', () => {
it('string', () => {
assert.deepEqual(
CLIENT_TRACKING.transformArguments(true, {
parseArgs(CLIENT_TRACKING, true, {
BCAST: true,
PREFIX: 'prefix'
}),
@@ -46,7 +47,7 @@ describe('CLIENT TRACKING', () => {
it('array', () => {
assert.deepEqual(
CLIENT_TRACKING.transformArguments(true, {
parseArgs(CLIENT_TRACKING, true, {
BCAST: true,
PREFIX: ['1', '2']
}),
@@ -58,7 +59,7 @@ describe('CLIENT TRACKING', () => {
it('with OPTIN', () => {
assert.deepEqual(
CLIENT_TRACKING.transformArguments(true, {
parseArgs(CLIENT_TRACKING, true, {
OPTIN: true
}),
['CLIENT', 'TRACKING', 'ON', 'OPTIN']
@@ -67,7 +68,7 @@ describe('CLIENT TRACKING', () => {
it('with OPTOUT', () => {
assert.deepEqual(
CLIENT_TRACKING.transformArguments(true, {
parseArgs(CLIENT_TRACKING, true, {
OPTOUT: true
}),
['CLIENT', 'TRACKING', 'ON', 'OPTOUT']
@@ -76,7 +77,7 @@ describe('CLIENT TRACKING', () => {
it('with NOLOOP', () => {
assert.deepEqual(
CLIENT_TRACKING.transformArguments(true, {
parseArgs(CLIENT_TRACKING, true, {
NOLOOP: true
}),
['CLIENT', 'TRACKING', 'ON', 'NOLOOP']
@@ -86,7 +87,7 @@ describe('CLIENT TRACKING', () => {
it('false', () => {
assert.deepEqual(
CLIENT_TRACKING.transformArguments(false),
parseArgs(CLIENT_TRACKING, false),
['CLIENT', 'TRACKING', 'OFF']
);
});

View File

@@ -1,4 +1,5 @@
import { RedisArgument, SimpleStringReply, Command } from '../RESP/types';
import { CommandParser } from '../client/parser';
import { SimpleStringReply, Command } from '../RESP/types';
import { RedisVariadicArgument } from './generic-transformers';
interface CommonOptions {
@@ -26,50 +27,49 @@ export type ClientTrackingOptions = CommonOptions & (
);
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments<M extends boolean>(
parseCommand<M extends boolean>(
parser: CommandParser,
mode: M,
options?: M extends true ? ClientTrackingOptions : never
) {
const args: Array<RedisArgument> = [
parser.push(
'CLIENT',
'TRACKING',
mode ? 'ON' : 'OFF'
];
);
if (mode) {
if (options?.REDIRECT) {
args.push(
parser.push(
'REDIRECT',
options.REDIRECT.toString()
);
}
if (isBroadcast(options)) {
args.push('BCAST');
parser.push('BCAST');
if (options?.PREFIX) {
if (Array.isArray(options.PREFIX)) {
for (const prefix of options.PREFIX) {
args.push('PREFIX', prefix);
parser.push('PREFIX', prefix);
}
} else {
args.push('PREFIX', options.PREFIX);
parser.push('PREFIX', options.PREFIX);
}
}
} else if (isOptIn(options)) {
args.push('OPTIN');
parser.push('OPTIN');
} else if (isOptOut(options)) {
args.push('OPTOUT');
parser.push('OPTOUT');
}
if (options?.NOLOOP) {
args.push('NOLOOP');
parser.push('NOLOOP');
}
}
return args;
},
transformReply: undefined as unknown as () => SimpleStringReply<'OK'>
} as const satisfies Command;

View File

@@ -1,13 +1,14 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import CLIENT_TRACKINGINFO from './CLIENT_TRACKINGINFO';
import { parseArgs } from './generic-transformers';
describe('CLIENT TRACKINGINFO', () => {
testUtils.isVersionGreaterThanHook([6, 2]);
it('transformArguments', () => {
assert.deepEqual(
CLIENT_TRACKINGINFO.transformArguments(),
parseArgs(CLIENT_TRACKINGINFO),
['CLIENT', 'TRACKINGINFO']
);
});

View File

@@ -1,3 +1,4 @@
import { CommandParser } from '../client/parser';
import { TuplesToMapReply, BlobStringReply, SetReply, NumberReply, ArrayReply, UnwrapReply, Resp2Reply, Command } from '../RESP/types';
type TrackingInfo = TuplesToMapReply<[
@@ -7,10 +8,10 @@ type TrackingInfo = TuplesToMapReply<[
]>;
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments() {
return ['CLIENT', 'TRACKINGINFO'];
parseCommand(parser: CommandParser) {
parser.push('CLIENT', 'TRACKINGINFO');
},
transformReply: {
2: (reply: UnwrapReply<Resp2Reply<TrackingInfo>>) => ({

View File

@@ -1,13 +1,14 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import CLIENT_UNPAUSE from './CLIENT_UNPAUSE';
import { parseArgs } from './generic-transformers';
describe('CLIENT UNPAUSE', () => {
testUtils.isVersionGreaterThanHook([6, 2]);
it('transformArguments', () => {
assert.deepEqual(
CLIENT_UNPAUSE.transformArguments(),
parseArgs(CLIENT_UNPAUSE),
['CLIENT', 'UNPAUSE']
);
});

View File

@@ -1,10 +1,11 @@
import { CommandParser } from '../client/parser';
import { SimpleStringReply, Command } from '../RESP/types';
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments() {
return ['CLIENT', 'UNPAUSE'];
parseCommand(parser: CommandParser) {
parser.push('CLIENT', 'UNPAUSE');
},
transformReply: undefined as unknown as () => SimpleStringReply<'OK'>
} as const satisfies Command;

View File

@@ -1,18 +1,19 @@
import { strict as assert } from 'node:assert';
import CLUSTER_ADDSLOTS from './CLUSTER_ADDSLOTS';
import { parseArgs } from './generic-transformers';
describe('CLUSTER ADDSLOTS', () => {
describe('transformArguments', () => {
it('single', () => {
assert.deepEqual(
CLUSTER_ADDSLOTS.transformArguments(0),
parseArgs(CLUSTER_ADDSLOTS, 0),
['CLUSTER', 'ADDSLOTS', '0']
);
});
it('multiple', () => {
assert.deepEqual(
CLUSTER_ADDSLOTS.transformArguments([0, 1]),
parseArgs(CLUSTER_ADDSLOTS, [0, 1]),
['CLUSTER', 'ADDSLOTS', '0', '1']
);
});

View File

@@ -1,14 +1,12 @@
import { CommandParser } from '../client/parser';
import { SimpleStringReply, Command } from '../RESP/types';
import { pushVariadicNumberArguments } from './generic-transformers';
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments(slots: number | Array<number>) {
return pushVariadicNumberArguments(
['CLUSTER', 'ADDSLOTS'],
slots
);
parseCommand(parser: CommandParser, slots: number | Array<number>) {
parser.push('CLUSTER', 'ADDSLOTS');
parser.pushVariadicNumber(slots);
},
transformReply: undefined as unknown as () => SimpleStringReply<'OK'>
} as const satisfies Command;

View File

@@ -1,6 +1,7 @@
import { strict as assert } from 'node:assert';
import testUtils from '../test-utils';
import CLUSTER_ADDSLOTSRANGE from './CLUSTER_ADDSLOTSRANGE';
import { parseArgs } from './generic-transformers';
describe('CLUSTER ADDSLOTSRANGE', () => {
testUtils.isVersionGreaterThanHook([7, 0]);
@@ -8,7 +9,7 @@ describe('CLUSTER ADDSLOTSRANGE', () => {
describe('transformArguments', () => {
it('single', () => {
assert.deepEqual(
CLUSTER_ADDSLOTSRANGE.transformArguments({
parseArgs(CLUSTER_ADDSLOTSRANGE, {
start: 0,
end: 1
}),
@@ -18,7 +19,7 @@ describe('CLUSTER ADDSLOTSRANGE', () => {
it('multiple', () => {
assert.deepEqual(
CLUSTER_ADDSLOTSRANGE.transformArguments([{
parseArgs(CLUSTER_ADDSLOTSRANGE, [{
start: 0,
end: 1
}, {

View File

@@ -1,14 +1,13 @@
import { CommandParser } from '../client/parser';
import { SimpleStringReply, Command } from '../RESP/types';
import { pushSlotRangesArguments, SlotRange } from './generic-transformers';
import { parseSlotRangesArguments, SlotRange } from './generic-transformers';
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments(ranges: SlotRange | Array<SlotRange>) {
return pushSlotRangesArguments(
['CLUSTER', 'ADDSLOTSRANGE'],
ranges
);
parseCommand(parser: CommandParser, ranges: SlotRange | Array<SlotRange>) {
parser.push('CLUSTER', 'ADDSLOTSRANGE');
parseSlotRangesArguments(parser, ranges);
},
transformReply: undefined as unknown as () => SimpleStringReply<'OK'>
} as const satisfies Command;

View File

@@ -1,11 +1,12 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import CLUSTER_BUMPEPOCH from './CLUSTER_BUMPEPOCH';
import { parseArgs } from './generic-transformers';
describe('CLUSTER BUMPEPOCH', () => {
it('transformArguments', () => {
assert.deepEqual(
CLUSTER_BUMPEPOCH.transformArguments(),
parseArgs(CLUSTER_BUMPEPOCH),
['CLUSTER', 'BUMPEPOCH']
);
});

View File

@@ -1,10 +1,11 @@
import { CommandParser } from '../client/parser';
import { SimpleStringReply, Command } from '../RESP/types';
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments() {
return ['CLUSTER', 'BUMPEPOCH'];
parseCommand(parser: CommandParser) {
parser.push('CLUSTER', 'BUMPEPOCH');
},
transformReply: undefined as unknown as () => SimpleStringReply<'BUMPED' | 'STILL'>
} as const satisfies Command;

View File

@@ -1,11 +1,12 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import CLUSTER_COUNT_FAILURE_REPORTS from './CLUSTER_COUNT-FAILURE-REPORTS';
import { parseArgs } from './generic-transformers';
describe('CLUSTER COUNT-FAILURE-REPORTS', () => {
it('transformArguments', () => {
assert.deepEqual(
CLUSTER_COUNT_FAILURE_REPORTS.transformArguments('0'),
parseArgs(CLUSTER_COUNT_FAILURE_REPORTS, '0'),
['CLUSTER', 'COUNT-FAILURE-REPORTS', '0']
);
});

View File

@@ -1,10 +1,11 @@
import { CommandParser } from '../client/parser';
import { RedisArgument, NumberReply, Command } from '../RESP/types';
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments(nodeId: RedisArgument) {
return ['CLUSTER', 'COUNT-FAILURE-REPORTS', nodeId];
parseCommand(parser: CommandParser, nodeId: RedisArgument) {
parser.push('CLUSTER', 'COUNT-FAILURE-REPORTS', nodeId);
},
transformReply: undefined as unknown as () => NumberReply
} as const satisfies Command;

View File

@@ -1,11 +1,12 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import CLUSTER_COUNTKEYSINSLOT from './CLUSTER_COUNTKEYSINSLOT';
import { parseArgs } from './generic-transformers';
describe('CLUSTER COUNTKEYSINSLOT', () => {
it('transformArguments', () => {
assert.deepEqual(
CLUSTER_COUNTKEYSINSLOT.transformArguments(0),
parseArgs(CLUSTER_COUNTKEYSINSLOT, 0),
['CLUSTER', 'COUNTKEYSINSLOT', '0']
);
});

View File

@@ -1,10 +1,11 @@
import { CommandParser } from '../client/parser';
import { NumberReply, Command } from '../RESP/types';
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments(slot: number) {
return ['CLUSTER', 'COUNTKEYSINSLOT', slot.toString()];
parseCommand(parser: CommandParser, slot: number) {
parser.push('CLUSTER', 'COUNTKEYSINSLOT', slot.toString());
},
transformReply: undefined as unknown as () => NumberReply
} as const satisfies Command;

Some files were not shown because too many files have changed in this diff Show More