You've already forked node-redis
mirror of
https://github.com/redis/node-redis.git
synced 2025-08-04 15:02:09 +03:00
use dockers for tests, use npm workspaces, add rejson & redisearch modules, fix some bugs
This commit is contained in:
23
packages/client/lib/commands/ACL_CAT.spec.ts
Normal file
23
packages/client/lib/commands/ACL_CAT.spec.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils from '../test-utils';
|
||||
import { transformArguments } from './ACL_CAT';
|
||||
|
||||
describe('ACL CAT', () => {
|
||||
testUtils.isVersionGreaterThanHook([6]);
|
||||
|
||||
describe('transformArguments', () => {
|
||||
it('simple', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments(),
|
||||
['ACL', 'CAT']
|
||||
);
|
||||
});
|
||||
|
||||
it('with categoryName', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('dangerous'),
|
||||
['ACL', 'CAT', 'dangerous']
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
11
packages/client/lib/commands/ACL_CAT.ts
Normal file
11
packages/client/lib/commands/ACL_CAT.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
export function transformArguments(categoryName?: string): Array<string> {
|
||||
const args = ['ACL', 'CAT'];
|
||||
|
||||
if (categoryName) {
|
||||
args.push(categoryName);
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
export declare function transformReply(): Array<string>;
|
30
packages/client/lib/commands/ACL_DELUSER.spec.ts
Normal file
30
packages/client/lib/commands/ACL_DELUSER.spec.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import { transformArguments } from './ACL_DELUSER';
|
||||
|
||||
describe('ACL DELUSER', () => {
|
||||
testUtils.isVersionGreaterThanHook([6]);
|
||||
|
||||
describe('transformArguments', () => {
|
||||
it('string', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('username'),
|
||||
['ACL', 'DELUSER', 'username']
|
||||
);
|
||||
});
|
||||
|
||||
it('array', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments(['1', '2']),
|
||||
['ACL', 'DELUSER', '1', '2']
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
testUtils.testWithClient('client.aclDelUser', async client => {
|
||||
assert.equal(
|
||||
await client.aclDelUser('dosenotexists'),
|
||||
0
|
||||
);
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
});
|
8
packages/client/lib/commands/ACL_DELUSER.ts
Normal file
8
packages/client/lib/commands/ACL_DELUSER.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { RedisCommandArguments } from '.';
|
||||
import { pushVerdictArguments } from './generic-transformers';
|
||||
|
||||
export function transformArguments(username: string | Array<string>): RedisCommandArguments {
|
||||
return pushVerdictArguments(['ACL', 'DELUSER'], username);
|
||||
}
|
||||
|
||||
export declare const transformReply: (reply: number) => number;
|
23
packages/client/lib/commands/ACL_GENPASS.spec.ts
Normal file
23
packages/client/lib/commands/ACL_GENPASS.spec.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils from '../test-utils';
|
||||
import { transformArguments } from './ACL_GENPASS';
|
||||
|
||||
describe('ACL GENPASS', () => {
|
||||
testUtils.isVersionGreaterThanHook([6]);
|
||||
|
||||
describe('transformArguments', () => {
|
||||
it('simple', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments(),
|
||||
['ACL', 'GENPASS']
|
||||
);
|
||||
});
|
||||
|
||||
it('with bits', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments(128),
|
||||
['ACL', 'GENPASS', '128']
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
11
packages/client/lib/commands/ACL_GENPASS.ts
Normal file
11
packages/client/lib/commands/ACL_GENPASS.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
export function transformArguments(bits?: number): Array<string> {
|
||||
const args = ['ACL', 'GENPASS'];
|
||||
|
||||
if (bits) {
|
||||
args.push(bits.toString());
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
export declare function transformReply(): string;
|
32
packages/client/lib/commands/ACL_GETUSER.spec.ts
Normal file
32
packages/client/lib/commands/ACL_GETUSER.spec.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import { transformArguments } from './ACL_GETUSER';
|
||||
|
||||
describe('ACL GETUSER', () => {
|
||||
testUtils.isVersionGreaterThanHook([6]);
|
||||
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('username'),
|
||||
['ACL', 'GETUSER', 'username']
|
||||
);
|
||||
});
|
||||
|
||||
testUtils.testWithClient('client.aclGetUser', async client => {
|
||||
assert.deepEqual(
|
||||
await client.aclGetUser('default'),
|
||||
{
|
||||
passwords: [],
|
||||
commands: '+@all',
|
||||
keys: ['*'],
|
||||
...(testUtils.isVersionGreaterThan([6, 2]) ? {
|
||||
flags: ['on', 'allkeys', 'allchannels', 'allcommands', 'nopass'],
|
||||
channels: ['*']
|
||||
} : {
|
||||
flags: ['on', 'allkeys', 'allcommands', 'nopass'],
|
||||
channels: undefined
|
||||
})
|
||||
}
|
||||
);
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
});
|
34
packages/client/lib/commands/ACL_GETUSER.ts
Normal file
34
packages/client/lib/commands/ACL_GETUSER.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
export function transformArguments(username: string): Array<string> {
|
||||
return ['ACL', 'GETUSER', username];
|
||||
}
|
||||
|
||||
type AclGetUserRawReply = [
|
||||
_: string,
|
||||
flags: Array<string>,
|
||||
_: string,
|
||||
passwords: Array<string>,
|
||||
_: string,
|
||||
commands: string,
|
||||
_: string,
|
||||
keys: Array<string>,
|
||||
_: string,
|
||||
channels: Array<string>
|
||||
];
|
||||
|
||||
interface AclUser {
|
||||
flags: Array<string>;
|
||||
passwords: Array<string>;
|
||||
commands: string;
|
||||
keys: Array<string>;
|
||||
channels: Array<string>
|
||||
}
|
||||
|
||||
export function transformReply(reply: AclGetUserRawReply): AclUser {
|
||||
return {
|
||||
flags: reply[1],
|
||||
passwords: reply[3],
|
||||
commands: reply[5],
|
||||
keys: reply[7],
|
||||
channels: reply[9]
|
||||
};
|
||||
}
|
14
packages/client/lib/commands/ACL_LIST.spec.ts
Normal file
14
packages/client/lib/commands/ACL_LIST.spec.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils from '../test-utils';
|
||||
import { transformArguments } from './ACL_LIST';
|
||||
|
||||
describe('ACL LIST', () => {
|
||||
testUtils.isVersionGreaterThanHook([6]);
|
||||
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments(),
|
||||
['ACL', 'LIST']
|
||||
);
|
||||
});
|
||||
});
|
5
packages/client/lib/commands/ACL_LIST.ts
Normal file
5
packages/client/lib/commands/ACL_LIST.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export function transformArguments(): Array<string> {
|
||||
return ['ACL', 'LIST'];
|
||||
}
|
||||
|
||||
export declare function transformReply(): Array<string>;
|
14
packages/client/lib/commands/ACL_LOAD.spec.ts
Normal file
14
packages/client/lib/commands/ACL_LOAD.spec.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils from '../test-utils';
|
||||
import { transformArguments } from './ACL_SAVE';
|
||||
|
||||
describe('ACL SAVE', () => {
|
||||
testUtils.isVersionGreaterThanHook([6]);
|
||||
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments(),
|
||||
['ACL', 'SAVE']
|
||||
);
|
||||
});
|
||||
});
|
5
packages/client/lib/commands/ACL_LOAD.ts
Normal file
5
packages/client/lib/commands/ACL_LOAD.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export function transformArguments(): Array<string> {
|
||||
return ['ACL', 'LOAD'];
|
||||
}
|
||||
|
||||
export declare function transformReply(): string;
|
53
packages/client/lib/commands/ACL_LOG.spec.ts
Normal file
53
packages/client/lib/commands/ACL_LOG.spec.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils from '../test-utils';
|
||||
import { transformArguments, transformReply } from './ACL_LOG';
|
||||
|
||||
describe('ACL LOG', () => {
|
||||
testUtils.isVersionGreaterThanHook([6]);
|
||||
|
||||
describe('transformArguments', () => {
|
||||
it('simple', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments(),
|
||||
['ACL', 'LOG']
|
||||
);
|
||||
});
|
||||
|
||||
it('with count', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments(10),
|
||||
['ACL', 'LOG', '10']
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('transformReply', () => {
|
||||
assert.deepEqual(
|
||||
transformReply([[
|
||||
'count',
|
||||
1,
|
||||
'reason',
|
||||
'auth',
|
||||
'context',
|
||||
'toplevel',
|
||||
'object',
|
||||
'AUTH',
|
||||
'username',
|
||||
'someuser',
|
||||
'age-seconds',
|
||||
'4.096',
|
||||
'client-info',
|
||||
'id=6 addr=127.0.0.1:63026 fd=8 name= age=9 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=48 qbuf-free=32720 obl=0 oll=0 omem=0 events=r cmd=auth user=default'
|
||||
]]),
|
||||
[{
|
||||
count: 1,
|
||||
reason: 'auth',
|
||||
context: 'toplevel',
|
||||
object: 'AUTH',
|
||||
username: 'someuser',
|
||||
ageSeconds: 4.096,
|
||||
clientInfo: 'id=6 addr=127.0.0.1:63026 fd=8 name= age=9 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=48 qbuf-free=32720 obl=0 oll=0 omem=0 events=r cmd=auth user=default'
|
||||
}]
|
||||
);
|
||||
});
|
||||
});
|
48
packages/client/lib/commands/ACL_LOG.ts
Normal file
48
packages/client/lib/commands/ACL_LOG.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
export function transformArguments(count?: number): Array<string> {
|
||||
const args = ['ACL', 'LOG'];
|
||||
|
||||
if (count) {
|
||||
args.push(count.toString());
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
type AclLogRawReply = [
|
||||
_: string,
|
||||
count: number,
|
||||
_: string,
|
||||
reason: string,
|
||||
_: string,
|
||||
context: string,
|
||||
_: string,
|
||||
object: string,
|
||||
_: string,
|
||||
username: string,
|
||||
_: string,
|
||||
ageSeconds: string,
|
||||
_: string,
|
||||
clientInfo: string
|
||||
];
|
||||
|
||||
interface AclLog {
|
||||
count: number;
|
||||
reason: string;
|
||||
context: string;
|
||||
object: string;
|
||||
username: string;
|
||||
ageSeconds: number;
|
||||
clientInfo: string;
|
||||
}
|
||||
|
||||
export function transformReply(reply: Array<AclLogRawReply>): Array<AclLog> {
|
||||
return reply.map(log => ({
|
||||
count: log[1],
|
||||
reason: log[3],
|
||||
context: log[5],
|
||||
object: log[7],
|
||||
username: log[9],
|
||||
ageSeconds: Number(log[11]),
|
||||
clientInfo: log[13]
|
||||
}));
|
||||
}
|
14
packages/client/lib/commands/ACL_LOG_RESET.spec.ts
Normal file
14
packages/client/lib/commands/ACL_LOG_RESET.spec.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils from '../test-utils';
|
||||
import { transformArguments } from './ACL_LOG_RESET';
|
||||
|
||||
describe('ACL LOG RESET', () => {
|
||||
testUtils.isVersionGreaterThanHook([6]);
|
||||
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments(),
|
||||
['ACL', 'LOG', 'RESET']
|
||||
);
|
||||
});
|
||||
});
|
5
packages/client/lib/commands/ACL_LOG_RESET.ts
Normal file
5
packages/client/lib/commands/ACL_LOG_RESET.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export function transformArguments(): Array<string> {
|
||||
return ['ACL', 'LOG', 'RESET'];
|
||||
}
|
||||
|
||||
export declare function transformReply(): string;
|
14
packages/client/lib/commands/ACL_SAVE.spec.ts
Normal file
14
packages/client/lib/commands/ACL_SAVE.spec.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils from '../test-utils';
|
||||
import { transformArguments } from './ACL_LOAD';
|
||||
|
||||
describe('ACL LOAD', () => {
|
||||
testUtils.isVersionGreaterThanHook([6]);
|
||||
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments(),
|
||||
['ACL', 'LOAD']
|
||||
);
|
||||
});
|
||||
});
|
5
packages/client/lib/commands/ACL_SAVE.ts
Normal file
5
packages/client/lib/commands/ACL_SAVE.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export function transformArguments(): Array<string> {
|
||||
return ['ACL', 'SAVE'];
|
||||
}
|
||||
|
||||
export declare function transformReply(): string;
|
23
packages/client/lib/commands/ACL_SETUSER.spec.ts
Normal file
23
packages/client/lib/commands/ACL_SETUSER.spec.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils from '../test-utils';
|
||||
import { transformArguments } from './ACL_SETUSER';
|
||||
|
||||
describe('ACL SETUSER', () => {
|
||||
testUtils.isVersionGreaterThanHook([6]);
|
||||
|
||||
describe('transformArguments', () => {
|
||||
it('string', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('username', 'allkeys'),
|
||||
['ACL', 'SETUSER', 'username', 'allkeys']
|
||||
);
|
||||
});
|
||||
|
||||
it('array', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('username', ['allkeys', 'allchannels']),
|
||||
['ACL', 'SETUSER', 'username', 'allkeys', 'allchannels']
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
8
packages/client/lib/commands/ACL_SETUSER.ts
Normal file
8
packages/client/lib/commands/ACL_SETUSER.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { RedisCommandArguments } from '.';
|
||||
import { pushVerdictArguments } from './generic-transformers';
|
||||
|
||||
export function transformArguments(username: string, rule: string | Array<string>): RedisCommandArguments {
|
||||
return pushVerdictArguments(['ACL', 'SETUSER', username], rule);
|
||||
}
|
||||
|
||||
export declare function transformReply(): string;
|
14
packages/client/lib/commands/ACL_USERS.spec.ts
Normal file
14
packages/client/lib/commands/ACL_USERS.spec.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils from '../test-utils';
|
||||
import { transformArguments } from './ACL_USERS';
|
||||
|
||||
describe('ACL USERS', () => {
|
||||
testUtils.isVersionGreaterThanHook([6]);
|
||||
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments(),
|
||||
['ACL', 'USERS']
|
||||
);
|
||||
});
|
||||
});
|
5
packages/client/lib/commands/ACL_USERS.ts
Normal file
5
packages/client/lib/commands/ACL_USERS.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export function transformArguments(): Array<string> {
|
||||
return ['ACL', 'USERS'];
|
||||
}
|
||||
|
||||
export declare function transformReply(): Array<string>;
|
14
packages/client/lib/commands/ACL_WHOAMI.spec.ts
Normal file
14
packages/client/lib/commands/ACL_WHOAMI.spec.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils from '../test-utils';
|
||||
import { transformArguments } from './ACL_WHOAMI';
|
||||
|
||||
describe('ACL WHOAMI', () => {
|
||||
testUtils.isVersionGreaterThanHook([6]);
|
||||
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments(),
|
||||
['ACL', 'WHOAMI']
|
||||
);
|
||||
});
|
||||
});
|
5
packages/client/lib/commands/ACL_WHOAMI.ts
Normal file
5
packages/client/lib/commands/ACL_WHOAMI.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export function transformArguments(): Array<string> {
|
||||
return ['ACL', 'WHOAMI'];
|
||||
}
|
||||
|
||||
export declare function transformReply(): string;
|
11
packages/client/lib/commands/APPEND.spec.ts
Normal file
11
packages/client/lib/commands/APPEND.spec.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import { transformArguments } from './APPEND';
|
||||
|
||||
describe('APPEND', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key', 'value'),
|
||||
['APPEND', 'key', 'value']
|
||||
);
|
||||
});
|
||||
});
|
7
packages/client/lib/commands/APPEND.ts
Normal file
7
packages/client/lib/commands/APPEND.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
export const FIRST_KEY_INDEX = 1;
|
||||
|
||||
export function transformArguments(key: string, value: string): Array<string> {
|
||||
return ['APPEND', key, value];
|
||||
}
|
||||
|
||||
export declare function transformReply(): string;
|
11
packages/client/lib/commands/ASKING.spec.ts
Normal file
11
packages/client/lib/commands/ASKING.spec.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import { transformArguments } from './ASKING';
|
||||
|
||||
describe('ASKING', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments(),
|
||||
['ASKING']
|
||||
);
|
||||
});
|
||||
});
|
5
packages/client/lib/commands/ASKING.ts
Normal file
5
packages/client/lib/commands/ASKING.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export function transformArguments(): Array<string> {
|
||||
return ['ASKING'];
|
||||
}
|
||||
|
||||
export declare function transformReply(): string;
|
25
packages/client/lib/commands/AUTH.spec.ts
Normal file
25
packages/client/lib/commands/AUTH.spec.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import { transformArguments } from './AUTH';
|
||||
|
||||
describe('AUTH', () => {
|
||||
describe('transformArguments', () => {
|
||||
it('password only', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments({
|
||||
password: 'password'
|
||||
}),
|
||||
['AUTH', 'password']
|
||||
);
|
||||
});
|
||||
|
||||
it('username & password', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments({
|
||||
username: 'username',
|
||||
password: 'password'
|
||||
}),
|
||||
['AUTH', 'username', 'password']
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
14
packages/client/lib/commands/AUTH.ts
Normal file
14
packages/client/lib/commands/AUTH.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
export interface AuthOptions {
|
||||
username?: string;
|
||||
password: string;
|
||||
}
|
||||
|
||||
export function transformArguments({username, password}: AuthOptions): Array<string> {
|
||||
if (!username) {
|
||||
return ['AUTH', password];
|
||||
}
|
||||
|
||||
return ['AUTH', username, password];
|
||||
}
|
||||
|
||||
export declare function transformReply(): string;
|
11
packages/client/lib/commands/BGREWRITEAOF.spec.ts
Normal file
11
packages/client/lib/commands/BGREWRITEAOF.spec.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import { transformArguments } from './BGREWRITEAOF';
|
||||
|
||||
describe('BGREWRITEAOF', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments(),
|
||||
['BGREWRITEAOF']
|
||||
);
|
||||
});
|
||||
});
|
5
packages/client/lib/commands/BGREWRITEAOF.ts
Normal file
5
packages/client/lib/commands/BGREWRITEAOF.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export function transformArguments(): Array<string> {
|
||||
return ['BGREWRITEAOF'];
|
||||
}
|
||||
|
||||
export declare function transformReply(): string;
|
23
packages/client/lib/commands/BGSAVE.spec.ts
Normal file
23
packages/client/lib/commands/BGSAVE.spec.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import { describe } from 'mocha';
|
||||
import { transformArguments } from './BGSAVE';
|
||||
|
||||
describe('BGSAVE', () => {
|
||||
describe('transformArguments', () => {
|
||||
it('simple', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments(),
|
||||
['BGSAVE']
|
||||
);
|
||||
});
|
||||
|
||||
it('with SCHEDULE', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments({
|
||||
SCHEDULE: true
|
||||
}),
|
||||
['BGSAVE', 'SCHEDULE']
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
15
packages/client/lib/commands/BGSAVE.ts
Normal file
15
packages/client/lib/commands/BGSAVE.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
interface BgSaveOptions {
|
||||
SCHEDULE?: true;
|
||||
}
|
||||
|
||||
export function transformArguments(options?: BgSaveOptions): Array<string> {
|
||||
const args = ['BGSAVE'];
|
||||
|
||||
if (options?.SCHEDULE) {
|
||||
args.push('SCHEDULE');
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
export declare function transformReply(): string;
|
31
packages/client/lib/commands/BITCOUNT.spec.ts
Normal file
31
packages/client/lib/commands/BITCOUNT.spec.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import { transformArguments } from './BITCOUNT';
|
||||
|
||||
describe('BITCOUNT', () => {
|
||||
describe('transformArguments', () => {
|
||||
it('simple', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key'),
|
||||
['BITCOUNT', 'key']
|
||||
);
|
||||
});
|
||||
|
||||
it('with range', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key', {
|
||||
start: 0,
|
||||
end: 1
|
||||
}),
|
||||
['BITCOUNT', 'key', '0', '1']
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
testUtils.testWithClient('client.bitCount', async client => {
|
||||
assert.equal(
|
||||
await client.bitCount('key'),
|
||||
0
|
||||
);
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
});
|
23
packages/client/lib/commands/BITCOUNT.ts
Normal file
23
packages/client/lib/commands/BITCOUNT.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
export const FIRST_KEY_INDEX = 1;
|
||||
|
||||
export const IS_READ_ONLY = true;
|
||||
|
||||
interface BitCountRange {
|
||||
start: number;
|
||||
end: number;
|
||||
}
|
||||
|
||||
export function transformArguments(key: string, range?: BitCountRange): Array<string> {
|
||||
const args = ['BITCOUNT', key];
|
||||
|
||||
if (range) {
|
||||
args.push(
|
||||
range.start.toString(),
|
||||
range.end.toString()
|
||||
);
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
export declare function transformReply(): number;
|
42
packages/client/lib/commands/BITFIELD.spec.ts
Normal file
42
packages/client/lib/commands/BITFIELD.spec.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import { transformArguments } from './BITFIELD';
|
||||
|
||||
describe('BITFIELD', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key', [{
|
||||
operation: 'OVERFLOW',
|
||||
behavior: 'WRAP'
|
||||
}, {
|
||||
operation: 'GET',
|
||||
type: 'i8',
|
||||
offset: 0
|
||||
}, {
|
||||
operation: 'OVERFLOW',
|
||||
behavior: 'SAT'
|
||||
}, {
|
||||
operation: 'SET',
|
||||
type: 'i16',
|
||||
offset: 1,
|
||||
value: 0
|
||||
}, {
|
||||
operation: 'OVERFLOW',
|
||||
behavior: 'FAIL'
|
||||
}, {
|
||||
operation: 'INCRBY',
|
||||
type: 'i32',
|
||||
offset: 2,
|
||||
increment: 1
|
||||
}]),
|
||||
['BITFIELD', 'key', 'OVERFLOW', 'WRAP', 'GET', 'i8', '0', 'OVERFLOW', 'SAT', 'SET', 'i16', '1', '0', 'OVERFLOW', 'FAIL', 'INCRBY', 'i32', '2', '1']
|
||||
);
|
||||
});
|
||||
|
||||
testUtils.testWithClient('client.bitField', async client => {
|
||||
assert.deepEqual(
|
||||
await client.bitField('key', []),
|
||||
[]
|
||||
);
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
});
|
82
packages/client/lib/commands/BITFIELD.ts
Normal file
82
packages/client/lib/commands/BITFIELD.ts
Normal file
@@ -0,0 +1,82 @@
|
||||
export const FIRST_KEY_INDEX = 1;
|
||||
|
||||
export const IS_READ_ONLY = true;
|
||||
|
||||
type BitFieldType = string; // TODO 'i[1-64]' | 'u[1-63]'
|
||||
|
||||
interface BitFieldOperation<S extends string> {
|
||||
operation: S;
|
||||
}
|
||||
|
||||
interface BitFieldGetOperation extends BitFieldOperation<'GET'> {
|
||||
type: BitFieldType;
|
||||
offset: number | string;
|
||||
}
|
||||
|
||||
interface BitFieldSetOperation extends BitFieldOperation<'SET'> {
|
||||
type: BitFieldType;
|
||||
offset: number | string;
|
||||
value: number;
|
||||
}
|
||||
|
||||
interface BitFieldIncrByOperation extends BitFieldOperation<'INCRBY'> {
|
||||
type: BitFieldType;
|
||||
offset: number | string;
|
||||
increment: number;
|
||||
}
|
||||
|
||||
interface BitFieldOverflowOperation extends BitFieldOperation<'OVERFLOW'> {
|
||||
behavior: string;
|
||||
}
|
||||
|
||||
type BitFieldOperations = Array<
|
||||
BitFieldGetOperation |
|
||||
BitFieldSetOperation |
|
||||
BitFieldIncrByOperation |
|
||||
BitFieldOverflowOperation
|
||||
>;
|
||||
|
||||
export function transformArguments(key: string, operations: BitFieldOperations): Array<string> {
|
||||
const args = ['BITFIELD', key];
|
||||
|
||||
for (const options of operations) {
|
||||
switch (options.operation) {
|
||||
case 'GET':
|
||||
args.push(
|
||||
'GET',
|
||||
options.type,
|
||||
options.offset.toString()
|
||||
);
|
||||
break;
|
||||
|
||||
case 'SET':
|
||||
args.push(
|
||||
'SET',
|
||||
options.type,
|
||||
options.offset.toString(),
|
||||
options.value.toString()
|
||||
);
|
||||
break;
|
||||
|
||||
case 'INCRBY':
|
||||
args.push(
|
||||
'INCRBY',
|
||||
options.type,
|
||||
options.offset.toString(),
|
||||
options.increment.toString()
|
||||
);
|
||||
break;
|
||||
|
||||
case 'OVERFLOW':
|
||||
args.push(
|
||||
'OVERFLOW',
|
||||
options.behavior
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
export declare function transformReply(): Array<number | null>;
|
35
packages/client/lib/commands/BITOP.spec.ts
Normal file
35
packages/client/lib/commands/BITOP.spec.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import { transformArguments } from './BITOP';
|
||||
|
||||
describe('BITOP', () => {
|
||||
describe('transformArguments', () => {
|
||||
it('single key', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('AND', 'destKey', 'key'),
|
||||
['BITOP', 'AND', 'destKey', 'key']
|
||||
);
|
||||
});
|
||||
|
||||
it('multiple keys', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('AND', 'destKey', ['1', '2']),
|
||||
['BITOP', 'AND', 'destKey', '1', '2']
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
testUtils.testWithClient('client.bitOp', async client => {
|
||||
assert.equal(
|
||||
await client.bitOp('AND', 'destKey', 'key'),
|
||||
0
|
||||
);
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
|
||||
testUtils.testWithCluster('cluster.bitOp', async cluster => {
|
||||
assert.equal(
|
||||
await cluster.bitOp('AND', '{tag}destKey', '{tag}key'),
|
||||
0
|
||||
);
|
||||
}, GLOBAL.CLUSTERS.OPEN);
|
||||
});
|
12
packages/client/lib/commands/BITOP.ts
Normal file
12
packages/client/lib/commands/BITOP.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { RedisCommandArguments } from '.';
|
||||
import { pushVerdictArguments } from './generic-transformers';
|
||||
|
||||
export const FIRST_KEY_INDEX = 2;
|
||||
|
||||
type BitOperations = 'AND' | 'OR' | 'XOR' | 'NOT';
|
||||
|
||||
export function transformArguments(operation: BitOperations, destKey: string, key: string | Array<string>): RedisCommandArguments {
|
||||
return pushVerdictArguments(['BITOP', operation, destKey], key);
|
||||
}
|
||||
|
||||
export declare function transformReply(): number;
|
42
packages/client/lib/commands/BITPOS.spec.ts
Normal file
42
packages/client/lib/commands/BITPOS.spec.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import { transformArguments } from './BITPOS';
|
||||
|
||||
describe('BITPOS', () => {
|
||||
describe('transformArguments', () => {
|
||||
it('simple', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key', 1),
|
||||
['BITPOS', 'key', '1']
|
||||
);
|
||||
});
|
||||
|
||||
it('with start', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key', 1, 1),
|
||||
['BITPOS', 'key', '1', '1']
|
||||
);
|
||||
});
|
||||
|
||||
it('with start, end', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key', 1, 1, -1),
|
||||
['BITPOS', 'key', '1', '1', '-1']
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
testUtils.testWithClient('client.bitPos', async client => {
|
||||
assert.equal(
|
||||
await client.bitPos('key', 1, 1),
|
||||
-1
|
||||
);
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
|
||||
testUtils.testWithCluster('cluster.bitPos', async cluster => {
|
||||
assert.equal(
|
||||
await cluster.bitPos('key', 1, 1),
|
||||
-1
|
||||
);
|
||||
}, GLOBAL.CLUSTERS.OPEN);
|
||||
});
|
21
packages/client/lib/commands/BITPOS.ts
Normal file
21
packages/client/lib/commands/BITPOS.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { BitValue } from './generic-transformers';
|
||||
|
||||
export const FIRST_KEY_INDEX = 1;
|
||||
|
||||
export const IS_READ_ONLY = true;
|
||||
|
||||
export function transformArguments(key: string, bit: BitValue, start?: number, end?: number): Array<string> {
|
||||
const args = ['BITPOS', key, bit.toString()];
|
||||
|
||||
if (typeof start === 'number') {
|
||||
args.push(start.toString());
|
||||
}
|
||||
|
||||
if (typeof end === 'number') {
|
||||
args.push(end.toString());
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
export declare function transformReply(): number;
|
43
packages/client/lib/commands/BLMOVE.spec.ts
Normal file
43
packages/client/lib/commands/BLMOVE.spec.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import { transformArguments } from './BLMOVE';
|
||||
import { commandOptions } from '../../index';
|
||||
|
||||
describe('BLMOVE', () => {
|
||||
testUtils.isVersionGreaterThanHook([6, 2]);
|
||||
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('source', 'destination', 'LEFT', 'RIGHT', 0),
|
||||
['BLMOVE', 'source', 'destination', 'LEFT', 'RIGHT', '0']
|
||||
);
|
||||
});
|
||||
|
||||
testUtils.testWithClient('client.blMove', async client => {
|
||||
const [blMoveReply] = await Promise.all([
|
||||
client.blMove(commandOptions({
|
||||
isolated: true
|
||||
}), 'source', 'destination', 'LEFT', 'RIGHT', 0),
|
||||
client.lPush('source', 'element')
|
||||
]);
|
||||
|
||||
assert.equal(
|
||||
blMoveReply,
|
||||
'element'
|
||||
);
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
|
||||
testUtils.testWithCluster('cluster.blMove', async cluster => {
|
||||
const [blMoveReply] = await Promise.all([
|
||||
cluster.blMove(commandOptions({
|
||||
isolated: true
|
||||
}), '{tag}source', '{tag}destination', 'LEFT', 'RIGHT', 0),
|
||||
cluster.lPush('{tag}source', 'element')
|
||||
]);
|
||||
|
||||
assert.equal(
|
||||
blMoveReply,
|
||||
'element'
|
||||
);
|
||||
}, GLOBAL.CLUSTERS.OPEN);
|
||||
});
|
22
packages/client/lib/commands/BLMOVE.ts
Normal file
22
packages/client/lib/commands/BLMOVE.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { LMoveSide } from './LMOVE';
|
||||
|
||||
export const FIRST_KEY_INDEX = 1;
|
||||
|
||||
export function transformArguments(
|
||||
source: string,
|
||||
destination: string,
|
||||
sourceDirection: LMoveSide,
|
||||
destinationDirection: LMoveSide,
|
||||
timeout: number
|
||||
): Array<string> {
|
||||
return [
|
||||
'BLMOVE',
|
||||
source,
|
||||
destination,
|
||||
sourceDirection,
|
||||
destinationDirection,
|
||||
timeout.toString()
|
||||
];
|
||||
}
|
||||
|
||||
export declare function transformReply(): string | null;
|
79
packages/client/lib/commands/BLPOP.spec.ts
Normal file
79
packages/client/lib/commands/BLPOP.spec.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import { transformArguments, transformReply } from './BLPOP';
|
||||
import { commandOptions } from '../../index';
|
||||
|
||||
describe('BLPOP', () => {
|
||||
describe('transformArguments', () => {
|
||||
it('single', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key', 0),
|
||||
['BLPOP', 'key', '0']
|
||||
);
|
||||
});
|
||||
|
||||
it('multiple', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments(['key1', 'key2'], 0),
|
||||
['BLPOP', 'key1', 'key2', '0']
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('transformReply', () => {
|
||||
it('null', () => {
|
||||
assert.equal(
|
||||
transformReply(null),
|
||||
null
|
||||
);
|
||||
});
|
||||
|
||||
it('member', () => {
|
||||
assert.deepEqual(
|
||||
transformReply(['key', 'element']),
|
||||
{
|
||||
key: 'key',
|
||||
element: 'element'
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
testUtils.testWithClient('client.blPop', async client => {
|
||||
const [ blPopReply ] = await Promise.all([
|
||||
client.blPop(
|
||||
commandOptions({ isolated: true }),
|
||||
'key',
|
||||
1
|
||||
),
|
||||
client.lPush('key', 'element'),
|
||||
]);
|
||||
|
||||
assert.deepEqual(
|
||||
blPopReply,
|
||||
{
|
||||
key: 'key',
|
||||
element: 'element'
|
||||
}
|
||||
);
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
|
||||
testUtils.testWithCluster('cluster.blPop', async cluster => {
|
||||
const [ blPopReply ] = await Promise.all([
|
||||
cluster.blPop(
|
||||
commandOptions({ isolated: true }),
|
||||
'key',
|
||||
1
|
||||
),
|
||||
cluster.lPush('key', 'element'),
|
||||
]);
|
||||
|
||||
assert.deepEqual(
|
||||
blPopReply,
|
||||
{
|
||||
key: 'key',
|
||||
element: 'element'
|
||||
}
|
||||
);
|
||||
}, GLOBAL.CLUSTERS.OPEN);
|
||||
});
|
26
packages/client/lib/commands/BLPOP.ts
Normal file
26
packages/client/lib/commands/BLPOP.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { RedisCommandArguments } from '.';
|
||||
import { pushVerdictArguments } from './generic-transformers';
|
||||
|
||||
export const FIRST_KEY_INDEX = 1;
|
||||
|
||||
export function transformArguments(keys: string | Buffer | Array<string | Buffer>, timeout: number): RedisCommandArguments {
|
||||
const args = pushVerdictArguments(['BLPOP'], keys);
|
||||
|
||||
args.push(timeout.toString());
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
type BLPOPReply = null | {
|
||||
key: string;
|
||||
element: string;
|
||||
};
|
||||
|
||||
export function transformReply(reply: null | [string, string]): BLPOPReply {
|
||||
if (reply === null) return null;
|
||||
|
||||
return {
|
||||
key: reply[0],
|
||||
element: reply[1]
|
||||
};
|
||||
}
|
79
packages/client/lib/commands/BRPOP.spec.ts
Normal file
79
packages/client/lib/commands/BRPOP.spec.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import { transformArguments, transformReply } from './BRPOP';
|
||||
import { commandOptions } from '../../index';
|
||||
|
||||
describe('BRPOP', () => {
|
||||
describe('transformArguments', () => {
|
||||
it('single', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key', 0),
|
||||
['BRPOP', 'key', '0']
|
||||
);
|
||||
});
|
||||
|
||||
it('multiple', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments(['key1', 'key2'], 0),
|
||||
['BRPOP', 'key1', 'key2', '0']
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('transformReply', () => {
|
||||
it('null', () => {
|
||||
assert.equal(
|
||||
transformReply(null),
|
||||
null
|
||||
);
|
||||
});
|
||||
|
||||
it('member', () => {
|
||||
assert.deepEqual(
|
||||
transformReply(['key', 'element']),
|
||||
{
|
||||
key: 'key',
|
||||
element: 'element'
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
testUtils.testWithClient('client.brPop', async client => {
|
||||
const [ brPopReply ] = await Promise.all([
|
||||
client.brPop(
|
||||
commandOptions({ isolated: true }),
|
||||
'key',
|
||||
1
|
||||
),
|
||||
client.lPush('key', 'element'),
|
||||
]);
|
||||
|
||||
assert.deepEqual(
|
||||
brPopReply,
|
||||
{
|
||||
key: 'key',
|
||||
element: 'element'
|
||||
}
|
||||
);
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
|
||||
testUtils.testWithCluster('cluster.brPop', async cluster => {
|
||||
const [ brPopReply ] = await Promise.all([
|
||||
cluster.brPop(
|
||||
commandOptions({ isolated: true }),
|
||||
'key',
|
||||
1
|
||||
),
|
||||
cluster.lPush('key', 'element'),
|
||||
]);
|
||||
|
||||
assert.deepEqual(
|
||||
brPopReply,
|
||||
{
|
||||
key: 'key',
|
||||
element: 'element'
|
||||
}
|
||||
);
|
||||
}, GLOBAL.CLUSTERS.OPEN);
|
||||
});
|
26
packages/client/lib/commands/BRPOP.ts
Normal file
26
packages/client/lib/commands/BRPOP.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { RedisCommandArguments } from '.';
|
||||
import { pushVerdictArguments } from './generic-transformers';
|
||||
|
||||
export const FIRST_KEY_INDEX = 1;
|
||||
|
||||
export function transformArguments(key: string | Array<string>, timeout: number): RedisCommandArguments {
|
||||
const args = pushVerdictArguments(['BRPOP'], key);
|
||||
|
||||
args.push(timeout.toString());
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
type BRPOPReply = null | {
|
||||
key: string;
|
||||
element: string;
|
||||
};
|
||||
|
||||
export function transformReply(reply: null | [string, string]): BRPOPReply {
|
||||
if (reply === null) return null;
|
||||
|
||||
return {
|
||||
key: reply[0],
|
||||
element: reply[1]
|
||||
};
|
||||
}
|
47
packages/client/lib/commands/BRPOPLPUSH.spec.ts
Normal file
47
packages/client/lib/commands/BRPOPLPUSH.spec.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import { transformArguments } from './BRPOPLPUSH';
|
||||
import { commandOptions } from '../../index';
|
||||
|
||||
describe('BRPOPLPUSH', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('source', 'destination', 0),
|
||||
['BRPOPLPUSH', 'source', 'destination', '0']
|
||||
);
|
||||
});
|
||||
|
||||
testUtils.testWithClient('client.brPopLPush', async client => {
|
||||
const [ popReply ] = await Promise.all([
|
||||
client.brPopLPush(
|
||||
commandOptions({ isolated: true }),
|
||||
'source',
|
||||
'destination',
|
||||
0
|
||||
),
|
||||
client.lPush('source', 'element')
|
||||
]);
|
||||
|
||||
assert.equal(
|
||||
popReply,
|
||||
'element'
|
||||
);
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
|
||||
testUtils.testWithCluster('cluster.brPopLPush', async cluster => {
|
||||
const [ popReply ] = await Promise.all([
|
||||
cluster.brPopLPush(
|
||||
commandOptions({ isolated: true }),
|
||||
'{tag}source',
|
||||
'{tag}destination',
|
||||
0
|
||||
),
|
||||
cluster.lPush('{tag}source', 'element')
|
||||
]);
|
||||
|
||||
assert.equal(
|
||||
popReply,
|
||||
'element'
|
||||
);
|
||||
}, GLOBAL.CLUSTERS.OPEN);
|
||||
});
|
7
packages/client/lib/commands/BRPOPLPUSH.ts
Normal file
7
packages/client/lib/commands/BRPOPLPUSH.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
export const FIRST_KEY_INDEX = 1;
|
||||
|
||||
export function transformArguments(source: string, destination: string, timeout: number): Array<string> {
|
||||
return ['BRPOPLPUSH', source, destination, timeout.toString()];
|
||||
}
|
||||
|
||||
export declare function transformReply(): number | null;
|
65
packages/client/lib/commands/BZPOPMAX.spec.ts
Normal file
65
packages/client/lib/commands/BZPOPMAX.spec.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import { transformArguments, transformReply } from './BZPOPMAX';
|
||||
import { commandOptions } from '../../index';
|
||||
|
||||
describe('BZPOPMAX', () => {
|
||||
describe('transformArguments', () => {
|
||||
it('single', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key', 0),
|
||||
['BZPOPMAX', 'key', '0']
|
||||
);
|
||||
});
|
||||
|
||||
it('multiple', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments(['1', '2'], 0),
|
||||
['BZPOPMAX', '1', '2', '0']
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('transformReply', () => {
|
||||
it('null', () => {
|
||||
assert.equal(
|
||||
transformReply(null),
|
||||
null
|
||||
);
|
||||
});
|
||||
|
||||
it('member', () => {
|
||||
assert.deepEqual(
|
||||
transformReply(['key', 'value', '1']),
|
||||
{
|
||||
key: 'key',
|
||||
value: 'value',
|
||||
score: 1
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
testUtils.testWithClient('client.bzPopMax', async client => {
|
||||
const [ bzPopMaxReply ] = await Promise.all([
|
||||
client.bzPopMax(
|
||||
commandOptions({ isolated: true }),
|
||||
'key',
|
||||
0
|
||||
),
|
||||
client.zAdd('key', [{
|
||||
value: '1',
|
||||
score: 1
|
||||
}])
|
||||
]);
|
||||
|
||||
assert.deepEqual(
|
||||
bzPopMaxReply,
|
||||
{
|
||||
key: 'key',
|
||||
value: '1',
|
||||
score: 1
|
||||
}
|
||||
);
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
});
|
28
packages/client/lib/commands/BZPOPMAX.ts
Normal file
28
packages/client/lib/commands/BZPOPMAX.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { RedisCommandArguments } from '.';
|
||||
import { pushVerdictArguments, transformReplyNumberInfinity, ZMember } from './generic-transformers';
|
||||
|
||||
export const FIRST_KEY_INDEX = 1;
|
||||
|
||||
export function transformArguments(key: string | Array<string>, timeout: number): RedisCommandArguments {
|
||||
const args = pushVerdictArguments(['BZPOPMAX'], key);
|
||||
|
||||
args.push(timeout.toString());
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
interface ZMemberWithKey extends ZMember {
|
||||
key: string;
|
||||
}
|
||||
|
||||
type BZPopMaxReply = ZMemberWithKey | null;
|
||||
|
||||
export function transformReply(reply: [key: string, value: string, score: string] | null): BZPopMaxReply | null {
|
||||
if (!reply) return null;
|
||||
|
||||
return {
|
||||
key: reply[0],
|
||||
value: reply[1],
|
||||
score: transformReplyNumberInfinity(reply[2])
|
||||
};
|
||||
}
|
65
packages/client/lib/commands/BZPOPMIN.spec.ts
Normal file
65
packages/client/lib/commands/BZPOPMIN.spec.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import { transformArguments, transformReply } from './BZPOPMIN';
|
||||
import { commandOptions } from '../../index';
|
||||
|
||||
describe('BZPOPMIN', () => {
|
||||
describe('transformArguments', () => {
|
||||
it('single', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key', 0),
|
||||
['BZPOPMIN', 'key', '0']
|
||||
);
|
||||
});
|
||||
|
||||
it('multiple', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments(['1', '2'], 0),
|
||||
['BZPOPMIN', '1', '2', '0']
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('transformReply', () => {
|
||||
it('null', () => {
|
||||
assert.equal(
|
||||
transformReply(null),
|
||||
null
|
||||
);
|
||||
});
|
||||
|
||||
it('member', () => {
|
||||
assert.deepEqual(
|
||||
transformReply(['key', 'value', '1']),
|
||||
{
|
||||
key: 'key',
|
||||
value: 'value',
|
||||
score: 1
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
testUtils.testWithClient('client.bzPopMin', async client => {
|
||||
const [ bzPopMinReply ] = await Promise.all([
|
||||
client.bzPopMin(
|
||||
commandOptions({ isolated: true }),
|
||||
'key',
|
||||
0
|
||||
),
|
||||
client.zAdd('key', [{
|
||||
value: '1',
|
||||
score: 1
|
||||
}])
|
||||
]);
|
||||
|
||||
assert.deepEqual(
|
||||
bzPopMinReply,
|
||||
{
|
||||
key: 'key',
|
||||
value: '1',
|
||||
score: 1
|
||||
}
|
||||
);
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
});
|
28
packages/client/lib/commands/BZPOPMIN.ts
Normal file
28
packages/client/lib/commands/BZPOPMIN.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { RedisCommandArguments } from '.';
|
||||
import { pushVerdictArguments, transformReplyNumberInfinity, ZMember } from './generic-transformers';
|
||||
|
||||
export const FIRST_KEY_INDEX = 1;
|
||||
|
||||
export function transformArguments(key: string | Array<string>, timeout: number): RedisCommandArguments {
|
||||
const args = pushVerdictArguments(['BZPOPMIN'], key);
|
||||
|
||||
args.push(timeout.toString());
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
interface ZMemberWithKey extends ZMember {
|
||||
key: string;
|
||||
}
|
||||
|
||||
type BZPopMinReply = ZMemberWithKey | null;
|
||||
|
||||
export function transformReply(reply: [key: string, value: string, score: string] | null): BZPopMinReply | null {
|
||||
if (!reply) return null;
|
||||
|
||||
return {
|
||||
key: reply[0],
|
||||
value: reply[1],
|
||||
score: transformReplyNumberInfinity(reply[2])
|
||||
};
|
||||
}
|
19
packages/client/lib/commands/CLIENT_ID.spec.ts
Normal file
19
packages/client/lib/commands/CLIENT_ID.spec.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import { transformArguments } from './CLIENT_ID';
|
||||
|
||||
describe('CLIENT ID', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments(),
|
||||
['CLIENT', 'ID']
|
||||
);
|
||||
});
|
||||
|
||||
testUtils.testWithClient('client.clientId', async client => {
|
||||
assert.equal(
|
||||
typeof (await client.clientId()),
|
||||
'number'
|
||||
);
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
});
|
7
packages/client/lib/commands/CLIENT_ID.ts
Normal file
7
packages/client/lib/commands/CLIENT_ID.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
export const IS_READ_ONLY = true;
|
||||
|
||||
export function transformArguments(): Array<string> {
|
||||
return ['CLIENT', 'ID'];
|
||||
}
|
||||
|
||||
export declare function transformReply(): number;
|
42
packages/client/lib/commands/CLIENT_INFO.spec.ts
Normal file
42
packages/client/lib/commands/CLIENT_INFO.spec.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import { transformArguments, transformReply } from './CLIENT_INFO';
|
||||
|
||||
describe('CLIENT INFO', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments(),
|
||||
['CLIENT', 'INFO']
|
||||
);
|
||||
});
|
||||
|
||||
it('transformReply', () => {
|
||||
assert.deepEqual(
|
||||
transformReply('id=526512 addr=127.0.0.1:36244 laddr=127.0.0.1:6379 fd=8 name= age=11213 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=26 qbuf-free=40928 argv-mem=10 obl=0 oll=0 omem=0 tot-mem=61466 events=r cmd=client user=default redir=-1\n'),
|
||||
{
|
||||
id: 526512,
|
||||
addr: '127.0.0.1:36244',
|
||||
laddr: '127.0.0.1:6379',
|
||||
fd: 8,
|
||||
name: '',
|
||||
age: 11213,
|
||||
idle: 0,
|
||||
flags: 'N',
|
||||
db: 0,
|
||||
sub: 0,
|
||||
psub: 0,
|
||||
multi: -1,
|
||||
qbuf: 26,
|
||||
qbufFree: 40928,
|
||||
argvMem: 10,
|
||||
obl: 0,
|
||||
oll: 0,
|
||||
omem: 0,
|
||||
totMem: 61466,
|
||||
events: 'r',
|
||||
cmd: 'client',
|
||||
user: 'default',
|
||||
redir: -1
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
85
packages/client/lib/commands/CLIENT_INFO.ts
Normal file
85
packages/client/lib/commands/CLIENT_INFO.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
export function transformArguments(): Array<string> {
|
||||
return ['CLIENT', 'INFO'];
|
||||
}
|
||||
|
||||
interface ClientInfoReply {
|
||||
id: number;
|
||||
addr: string;
|
||||
laddr: string;
|
||||
fd: number;
|
||||
name: string;
|
||||
age: number;
|
||||
idle: number;
|
||||
flags: string;
|
||||
db: number;
|
||||
sub: number;
|
||||
psub: number;
|
||||
multi: number;
|
||||
qbuf: number;
|
||||
qbufFree: number;
|
||||
argvMem: number;
|
||||
obl: number;
|
||||
oll: number;
|
||||
omem: number;
|
||||
totMem: number;
|
||||
events: string;
|
||||
cmd: string;
|
||||
user: string;
|
||||
redir: number;
|
||||
}
|
||||
|
||||
const REGEX = /=([^\s]*)/g;
|
||||
|
||||
export function transformReply(reply: string): ClientInfoReply {
|
||||
const [
|
||||
[, id],
|
||||
[, addr],
|
||||
[, laddr],
|
||||
[, fd],
|
||||
[, name],
|
||||
[, age],
|
||||
[, idle],
|
||||
[, flags],
|
||||
[, db],
|
||||
[, sub],
|
||||
[, psub],
|
||||
[, multi],
|
||||
[, qbuf],
|
||||
[, qbufFree],
|
||||
[, argvMem],
|
||||
[, obl],
|
||||
[, oll],
|
||||
[, omem],
|
||||
[, totMem],
|
||||
[, events],
|
||||
[, cmd],
|
||||
[, user],
|
||||
[, redir]
|
||||
] = [...reply.matchAll(REGEX)];
|
||||
|
||||
return {
|
||||
id: Number(id),
|
||||
addr,
|
||||
laddr,
|
||||
fd: Number(fd),
|
||||
name,
|
||||
age: Number(age),
|
||||
idle: Number(idle),
|
||||
flags,
|
||||
db: Number(db),
|
||||
sub: Number(sub),
|
||||
psub: Number(psub),
|
||||
multi: Number(multi),
|
||||
qbuf: Number(qbuf),
|
||||
qbufFree: Number(qbufFree),
|
||||
argvMem: Number(argvMem),
|
||||
obl: Number(obl),
|
||||
oll: Number(oll),
|
||||
omem: Number(omem),
|
||||
totMem: Number(totMem),
|
||||
events,
|
||||
cmd,
|
||||
user,
|
||||
redir: Number(redir)
|
||||
};
|
||||
}
|
20
packages/client/lib/commands/CLUSTER_ADDSLOTS.spec.ts
Normal file
20
packages/client/lib/commands/CLUSTER_ADDSLOTS.spec.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import { transformArguments } from './CLUSTER_ADDSLOTS';
|
||||
|
||||
describe('CLUSTER ADDSLOTS', () => {
|
||||
describe('transformArguments', () => {
|
||||
it('single', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments(0),
|
||||
['CLUSTER', 'ADDSLOTS', '0']
|
||||
);
|
||||
});
|
||||
|
||||
it('multiple', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments([0, 1]),
|
||||
['CLUSTER', 'ADDSLOTS', '0', '1']
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
13
packages/client/lib/commands/CLUSTER_ADDSLOTS.ts
Normal file
13
packages/client/lib/commands/CLUSTER_ADDSLOTS.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
export function transformArguments(slots: number | Array<number>): Array<string> {
|
||||
const args = ['CLUSTER', 'ADDSLOTS'];
|
||||
|
||||
if (typeof slots === 'number') {
|
||||
args.push(slots.toString());
|
||||
} else {
|
||||
args.push(...slots.map(String));
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
export declare function transformReply(): string;
|
11
packages/client/lib/commands/CLUSTER_FLUSHSLOTS.spec.ts
Normal file
11
packages/client/lib/commands/CLUSTER_FLUSHSLOTS.spec.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import { transformArguments } from './CLUSTER_FLUSHSLOTS';
|
||||
|
||||
describe('CLUSTER FLUSHSLOTS', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments(),
|
||||
['CLUSTER', 'FLUSHSLOTS']
|
||||
);
|
||||
});
|
||||
});
|
5
packages/client/lib/commands/CLUSTER_FLUSHSLOTS.ts
Normal file
5
packages/client/lib/commands/CLUSTER_FLUSHSLOTS.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export function transformArguments(): Array<string> {
|
||||
return ['CLUSTER', 'FLUSHSLOTS'];
|
||||
}
|
||||
|
||||
export declare function transformReply(): string;
|
11
packages/client/lib/commands/CLUSTER_GETKEYSINSLOT.spec.ts
Normal file
11
packages/client/lib/commands/CLUSTER_GETKEYSINSLOT.spec.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import { transformArguments } from './CLUSTER_GETKEYSINSLOT';
|
||||
|
||||
describe('CLUSTER GETKEYSINSLOT', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments(0, 10),
|
||||
['CLUSTER', 'GETKEYSINSLOT', '0', '10']
|
||||
);
|
||||
});
|
||||
});
|
5
packages/client/lib/commands/CLUSTER_GETKEYSINSLOT.ts
Normal file
5
packages/client/lib/commands/CLUSTER_GETKEYSINSLOT.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export function transformArguments(slot: number, count: number): Array<string> {
|
||||
return ['CLUSTER', 'GETKEYSINSLOT', slot.toString(), count.toString()];
|
||||
}
|
||||
|
||||
export declare function transformReply(): string;
|
46
packages/client/lib/commands/CLUSTER_INFO.spec.ts
Normal file
46
packages/client/lib/commands/CLUSTER_INFO.spec.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import { transformArguments, transformReply } from './CLUSTER_INFO';
|
||||
|
||||
describe('CLUSTER INFO', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments(),
|
||||
['CLUSTER', 'INFO']
|
||||
);
|
||||
});
|
||||
|
||||
it('transformReply', () => {
|
||||
assert.deepEqual(
|
||||
transformReply([
|
||||
'cluster_state:ok',
|
||||
'cluster_slots_assigned:16384',
|
||||
'cluster_slots_ok:16384',
|
||||
'cluster_slots_pfail:0',
|
||||
'cluster_slots_fail:0',
|
||||
'cluster_known_nodes:6',
|
||||
'cluster_size:3',
|
||||
'cluster_current_epoch:6',
|
||||
'cluster_my_epoch:2',
|
||||
'cluster_stats_messages_sent:1483972',
|
||||
'cluster_stats_messages_received:1483968'
|
||||
].join('\r\n')),
|
||||
{
|
||||
state: 'ok',
|
||||
slots: {
|
||||
assigned: 16384,
|
||||
ok: 16384,
|
||||
pfail: 0,
|
||||
fail: 0
|
||||
},
|
||||
knownNodes: 6,
|
||||
size: 3,
|
||||
currentEpoch: 6,
|
||||
myEpoch: 2,
|
||||
stats: {
|
||||
messagesSent: 1483972,
|
||||
messagesReceived: 1483968
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
47
packages/client/lib/commands/CLUSTER_INFO.ts
Normal file
47
packages/client/lib/commands/CLUSTER_INFO.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
export function transformArguments(): Array<string> {
|
||||
return ['CLUSTER', 'INFO'];
|
||||
}
|
||||
|
||||
interface ClusterInfoReply {
|
||||
state: string;
|
||||
slots: {
|
||||
assigned: number;
|
||||
ok: number;
|
||||
pfail: number;
|
||||
fail: number;
|
||||
};
|
||||
knownNodes: number;
|
||||
size: number;
|
||||
currentEpoch: number;
|
||||
myEpoch: number;
|
||||
stats: {
|
||||
messagesSent: number;
|
||||
messagesReceived: number;
|
||||
};
|
||||
}
|
||||
|
||||
export function transformReply(reply: string): ClusterInfoReply {
|
||||
const lines = reply.split('\r\n');
|
||||
|
||||
return {
|
||||
state: extractLineValue(lines[0]),
|
||||
slots: {
|
||||
assigned: Number(extractLineValue(lines[1])),
|
||||
ok: Number(extractLineValue(lines[2])),
|
||||
pfail: Number(extractLineValue(lines[3])),
|
||||
fail: Number(extractLineValue(lines[4]))
|
||||
},
|
||||
knownNodes: Number(extractLineValue(lines[5])),
|
||||
size: Number(extractLineValue(lines[6])),
|
||||
currentEpoch: Number(extractLineValue(lines[7])),
|
||||
myEpoch: Number(extractLineValue(lines[8])),
|
||||
stats: {
|
||||
messagesSent: Number(extractLineValue(lines[9])),
|
||||
messagesReceived: Number(extractLineValue(lines[10]))
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function extractLineValue(line: string): string {
|
||||
return line.substring(line.indexOf(':') + 1);
|
||||
}
|
11
packages/client/lib/commands/CLUSTER_MEET.spec.ts
Normal file
11
packages/client/lib/commands/CLUSTER_MEET.spec.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import { transformArguments } from './CLUSTER_MEET';
|
||||
|
||||
describe('CLUSTER MEET', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('127.0.0.1', 6379),
|
||||
['CLUSTER', 'MEET', '127.0.0.1', '6379']
|
||||
);
|
||||
});
|
||||
});
|
5
packages/client/lib/commands/CLUSTER_MEET.ts
Normal file
5
packages/client/lib/commands/CLUSTER_MEET.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export function transformArguments(ip: string, port: number): Array<string> {
|
||||
return ['CLUSTER', 'MEET', ip, port.toString()];
|
||||
}
|
||||
|
||||
export declare function transformReply(): string;
|
95
packages/client/lib/commands/CLUSTER_NODES.spec.ts
Normal file
95
packages/client/lib/commands/CLUSTER_NODES.spec.ts
Normal file
@@ -0,0 +1,95 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import { RedisClusterNodeLinkStates, transformArguments, transformReply } from './CLUSTER_NODES';
|
||||
|
||||
describe('CLUSTER NODES', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments(),
|
||||
['CLUSTER', 'NODES']
|
||||
);
|
||||
});
|
||||
|
||||
describe('transformReply', () => {
|
||||
it('simple', () => {
|
||||
assert.deepEqual(
|
||||
transformReply([
|
||||
'master 127.0.0.1:30001@31001 myself,master - 0 0 1 connected 0-16384',
|
||||
'slave 127.0.0.1:30002@31002 slave master 0 0 1 connected',
|
||||
''
|
||||
].join('\n')),
|
||||
[{
|
||||
id: 'master',
|
||||
url: '127.0.0.1:30001@31001',
|
||||
host: '127.0.0.1',
|
||||
port: 30001,
|
||||
cport: 31001,
|
||||
flags: ['myself', 'master'],
|
||||
pingSent: 0,
|
||||
pongRecv: 0,
|
||||
configEpoch: 1,
|
||||
linkState: RedisClusterNodeLinkStates.CONNECTED,
|
||||
slots: [{
|
||||
from: 0,
|
||||
to: 16384
|
||||
}],
|
||||
replicas: [{
|
||||
id: 'slave',
|
||||
url: '127.0.0.1:30002@31002',
|
||||
host: '127.0.0.1',
|
||||
port: 30002,
|
||||
cport: 31002,
|
||||
flags: ['slave'],
|
||||
pingSent: 0,
|
||||
pongRecv: 0,
|
||||
configEpoch: 1,
|
||||
linkState: RedisClusterNodeLinkStates.CONNECTED
|
||||
}]
|
||||
}]
|
||||
);
|
||||
});
|
||||
|
||||
it.skip('with importing slots', () => {
|
||||
assert.deepEqual(
|
||||
transformReply(
|
||||
'id 127.0.0.1:30001@31001 master - 0 0 0 connected 0-<-16384\n'
|
||||
),
|
||||
[{
|
||||
id: 'id',
|
||||
url: '127.0.0.1:30001@31001',
|
||||
host: '127.0.0.1',
|
||||
port: 30001,
|
||||
cport: 31001,
|
||||
flags: ['master'],
|
||||
pingSent: 0,
|
||||
pongRecv: 0,
|
||||
configEpoch: 0,
|
||||
linkState: RedisClusterNodeLinkStates.CONNECTED,
|
||||
slots: [], // TODO
|
||||
replicas: []
|
||||
}]
|
||||
);
|
||||
});
|
||||
|
||||
it.skip('with migrating slots', () => {
|
||||
assert.deepEqual(
|
||||
transformReply(
|
||||
'id 127.0.0.1:30001@31001 master - 0 0 0 connected 0->-16384\n'
|
||||
),
|
||||
[{
|
||||
id: 'id',
|
||||
url: '127.0.0.1:30001@31001',
|
||||
host: '127.0.0.1',
|
||||
port: 30001,
|
||||
cport: 31001,
|
||||
flags: ['master'],
|
||||
pingSent: 0,
|
||||
pongRecv: 0,
|
||||
configEpoch: 0,
|
||||
linkState: RedisClusterNodeLinkStates.CONNECTED,
|
||||
slots: [], // TODO
|
||||
replicas: []
|
||||
}]
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
96
packages/client/lib/commands/CLUSTER_NODES.ts
Normal file
96
packages/client/lib/commands/CLUSTER_NODES.ts
Normal file
@@ -0,0 +1,96 @@
|
||||
export function transformArguments(): Array<string> {
|
||||
return ['CLUSTER', 'NODES'];
|
||||
}
|
||||
|
||||
export enum RedisClusterNodeLinkStates {
|
||||
CONNECTED = 'connected',
|
||||
DISCONNECTED = 'disconnected'
|
||||
}
|
||||
|
||||
interface RedisClusterNodeTransformedUrl {
|
||||
host: string;
|
||||
port: number;
|
||||
cport: number;
|
||||
}
|
||||
|
||||
export interface RedisClusterReplicaNode extends RedisClusterNodeTransformedUrl {
|
||||
id: string;
|
||||
url: string;
|
||||
flags: Array<string>;
|
||||
pingSent: number;
|
||||
pongRecv: number;
|
||||
configEpoch: number;
|
||||
linkState: RedisClusterNodeLinkStates;
|
||||
}
|
||||
|
||||
export interface RedisClusterMasterNode extends RedisClusterReplicaNode {
|
||||
slots: Array<{
|
||||
from: number;
|
||||
to: number;
|
||||
}>;
|
||||
replicas: Array<RedisClusterReplicaNode>;
|
||||
}
|
||||
|
||||
export function transformReply(reply: string): Array<RedisClusterMasterNode> {
|
||||
const lines = reply.split('\n');
|
||||
lines.pop(); // last line is empty
|
||||
|
||||
const mastersMap = new Map<string, RedisClusterMasterNode>(),
|
||||
replicasMap = new Map<string, Array<RedisClusterReplicaNode>>();
|
||||
|
||||
for (const line of lines) {
|
||||
const [id, url, flags, masterId, pingSent, pongRecv, configEpoch, linkState, ...slots] = line.split(' '),
|
||||
node = {
|
||||
id,
|
||||
url,
|
||||
...transformNodeUrl(url),
|
||||
flags: flags.split(','),
|
||||
pingSent: Number(pingSent),
|
||||
pongRecv: Number(pongRecv),
|
||||
configEpoch: Number(configEpoch),
|
||||
linkState: (linkState as RedisClusterNodeLinkStates)
|
||||
};
|
||||
|
||||
if (masterId === '-') {
|
||||
let replicas = replicasMap.get(id);
|
||||
if (!replicas) {
|
||||
replicas = [];
|
||||
replicasMap.set(id, replicas);
|
||||
}
|
||||
|
||||
mastersMap.set(id, {
|
||||
...node,
|
||||
slots: slots.map(slot => {
|
||||
// TODO: importing & exporting (https://redis.io/commands/cluster-nodes#special-slot-entries)
|
||||
const [fromString, toString] = slot.split('-', 2),
|
||||
from = Number(fromString);
|
||||
return {
|
||||
from,
|
||||
to: toString ? Number(toString) : from
|
||||
};
|
||||
}),
|
||||
replicas
|
||||
});
|
||||
} else {
|
||||
const replicas = replicasMap.get(masterId);
|
||||
if (!replicas) {
|
||||
replicasMap.set(masterId, [node]);
|
||||
} else {
|
||||
replicas.push(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [...mastersMap.values()];
|
||||
}
|
||||
|
||||
function transformNodeUrl(url: string): RedisClusterNodeTransformedUrl {
|
||||
const indexOfColon = url.indexOf(':'),
|
||||
indexOfAt = url.indexOf('@', indexOfColon);
|
||||
|
||||
return {
|
||||
host: url.substring(0, indexOfColon),
|
||||
port: Number(url.substring(indexOfColon + 1, indexOfAt)),
|
||||
cport: Number(url.substring(indexOfAt + 1))
|
||||
};
|
||||
}
|
27
packages/client/lib/commands/CLUSTER_RESET.spec.ts
Normal file
27
packages/client/lib/commands/CLUSTER_RESET.spec.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import { transformArguments } from './CLUSTER_RESET';
|
||||
|
||||
describe('CLUSTER RESET', () => {
|
||||
describe('transformArguments', () => {
|
||||
it('simple', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments(),
|
||||
['CLUSTER', 'RESET']
|
||||
);
|
||||
});
|
||||
|
||||
it('HARD', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('HARD'),
|
||||
['CLUSTER', 'RESET', 'HARD']
|
||||
);
|
||||
});
|
||||
|
||||
it('SOFT', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('SOFT'),
|
||||
['CLUSTER', 'RESET', 'SOFT']
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
13
packages/client/lib/commands/CLUSTER_RESET.ts
Normal file
13
packages/client/lib/commands/CLUSTER_RESET.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
export type ClusterResetModes = 'HARD' | 'SOFT';
|
||||
|
||||
export function transformArguments(mode?: ClusterResetModes): Array<string> {
|
||||
const args = ['CLUSTER', 'RESET'];
|
||||
|
||||
if (mode) {
|
||||
args.push(mode);
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
export declare function transformReply(): string;
|
20
packages/client/lib/commands/CLUSTER_SETSLOT.spec.ts
Normal file
20
packages/client/lib/commands/CLUSTER_SETSLOT.spec.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import { ClusterSlotStates, transformArguments } from './CLUSTER_SETSLOT';
|
||||
|
||||
describe('CLUSTER SETSLOT', () => {
|
||||
describe('transformArguments', () => {
|
||||
it('simple', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments(0, ClusterSlotStates.IMPORTING),
|
||||
['CLUSTER', 'SETSLOT', '0', 'IMPORTING']
|
||||
);
|
||||
});
|
||||
|
||||
it('with nodeId', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments(0, ClusterSlotStates.IMPORTING, 'nodeId'),
|
||||
['CLUSTER', 'SETSLOT', '0', 'IMPORTING', 'nodeId']
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
18
packages/client/lib/commands/CLUSTER_SETSLOT.ts
Normal file
18
packages/client/lib/commands/CLUSTER_SETSLOT.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
export enum ClusterSlotStates {
|
||||
IMPORTING = 'IMPORTING',
|
||||
MIGRATING = 'MIGRATING',
|
||||
STABLE = 'STABLE',
|
||||
NODE = 'NODE'
|
||||
}
|
||||
|
||||
export function transformArguments(slot: number, state: ClusterSlotStates, nodeId?: string): Array<string> {
|
||||
const args = ['CLUSTER', 'SETSLOT', slot.toString(), state];
|
||||
|
||||
if (nodeId) {
|
||||
args.push(nodeId);
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
export declare function transformReply(): string;
|
76
packages/client/lib/commands/CLUSTER_SLOTS.spec.ts
Normal file
76
packages/client/lib/commands/CLUSTER_SLOTS.spec.ts
Normal file
@@ -0,0 +1,76 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import { transformArguments, transformReply } from './CLUSTER_SLOTS';
|
||||
|
||||
describe('CLUSTER SLOTS', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments(),
|
||||
['CLUSTER', 'SLOTS']
|
||||
);
|
||||
});
|
||||
|
||||
it('transformReply', () => {
|
||||
assert.deepEqual(
|
||||
transformReply([
|
||||
[
|
||||
0,
|
||||
5460,
|
||||
['127.0.0.1', 30001, '09dbe9720cda62f7865eabc5fd8857c5d2678366'],
|
||||
['127.0.0.1', 30004, '821d8ca00d7ccf931ed3ffc7e3db0599d2271abf']
|
||||
],
|
||||
[
|
||||
5461,
|
||||
10922,
|
||||
['127.0.0.1', 30002, 'c9d93d9f2c0c524ff34cc11838c2003d8c29e013'],
|
||||
['127.0.0.1', 30005, 'faadb3eb99009de4ab72ad6b6ed87634c7ee410f']
|
||||
],
|
||||
[
|
||||
10923,
|
||||
16383,
|
||||
['127.0.0.1', 30003, '044ec91f325b7595e76dbcb18cc688b6a5b434a1'],
|
||||
['127.0.0.1', 30006, '58e6e48d41228013e5d9c1c37c5060693925e97e']
|
||||
]
|
||||
]),
|
||||
[{
|
||||
from: 0,
|
||||
to: 5460,
|
||||
master: {
|
||||
ip: '127.0.0.1',
|
||||
port: 30001,
|
||||
id: '09dbe9720cda62f7865eabc5fd8857c5d2678366'
|
||||
},
|
||||
replicas: [{
|
||||
ip: '127.0.0.1',
|
||||
port: 30004,
|
||||
id: '821d8ca00d7ccf931ed3ffc7e3db0599d2271abf'
|
||||
}]
|
||||
}, {
|
||||
from: 5461,
|
||||
to: 10922,
|
||||
master: {
|
||||
ip: '127.0.0.1',
|
||||
port: 30002,
|
||||
id: 'c9d93d9f2c0c524ff34cc11838c2003d8c29e013'
|
||||
},
|
||||
replicas: [{
|
||||
ip: '127.0.0.1',
|
||||
port: 30005,
|
||||
id: 'faadb3eb99009de4ab72ad6b6ed87634c7ee410f'
|
||||
}]
|
||||
}, {
|
||||
from: 10923,
|
||||
to: 16383,
|
||||
master: {
|
||||
ip: '127.0.0.1',
|
||||
port: 30003,
|
||||
id: '044ec91f325b7595e76dbcb18cc688b6a5b434a1'
|
||||
},
|
||||
replicas: [{
|
||||
ip: '127.0.0.1',
|
||||
port: 30006,
|
||||
id: '58e6e48d41228013e5d9c1c37c5060693925e97e'
|
||||
}]
|
||||
}]
|
||||
);
|
||||
});
|
||||
});
|
41
packages/client/lib/commands/CLUSTER_SLOTS.ts
Normal file
41
packages/client/lib/commands/CLUSTER_SLOTS.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import { RedisCommandArguments } from '.';
|
||||
|
||||
export function transformArguments(): RedisCommandArguments {
|
||||
return ['CLUSTER', 'SLOTS'];
|
||||
}
|
||||
|
||||
type ClusterSlotsRawNode = [ip: string, port: number, id: string];
|
||||
|
||||
type ClusterSlotsRawReply = Array<[from: number, to: number, master: ClusterSlotsRawNode, ...replicas: Array<ClusterSlotsRawNode>]>;
|
||||
|
||||
type ClusterSlotsNode = {
|
||||
ip: string;
|
||||
port: number;
|
||||
id: string;
|
||||
};
|
||||
|
||||
export type ClusterSlotsReply = Array<{
|
||||
from: number;
|
||||
to: number;
|
||||
master: ClusterSlotsNode;
|
||||
replicas: Array<ClusterSlotsNode>;
|
||||
}>;
|
||||
|
||||
export function transformReply(reply: ClusterSlotsRawReply): ClusterSlotsReply {
|
||||
return reply.map(([from, to, master, ...replicas]) => {
|
||||
return {
|
||||
from,
|
||||
to,
|
||||
master: transformNode(master),
|
||||
replicas: replicas.map(transformNode)
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function transformNode([ip, port, id]: ClusterSlotsRawNode): ClusterSlotsNode {
|
||||
return {
|
||||
ip,
|
||||
port,
|
||||
id
|
||||
};
|
||||
}
|
17
packages/client/lib/commands/COMMAND.spec.ts
Normal file
17
packages/client/lib/commands/COMMAND.spec.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import { transformArguments } from './COMMAND';
|
||||
import { assertPingCommand } from './COMMAND_INFO.spec';
|
||||
|
||||
describe('COMMAND', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments(),
|
||||
['COMMAND']
|
||||
);
|
||||
});
|
||||
|
||||
// testUtils.testWithClient('client.command', async client => {
|
||||
// assertPingCommand((await client.command()).find(command => command.name === 'ping'));
|
||||
// }, GLOBAL.SERVERS.OPEN);
|
||||
});
|
12
packages/client/lib/commands/COMMAND.ts
Normal file
12
packages/client/lib/commands/COMMAND.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { RedisCommandArguments } from '.';
|
||||
import { CommandRawReply, CommandReply, transformCommandReply } from './generic-transformers';
|
||||
|
||||
export const IS_READ_ONLY = true;
|
||||
|
||||
export function transformArguments(): RedisCommandArguments {
|
||||
return ['COMMAND'];
|
||||
}
|
||||
|
||||
export function transformReply(reply: Array<CommandRawReply>): Array<CommandReply> {
|
||||
return reply.map(transformCommandReply);
|
||||
}
|
19
packages/client/lib/commands/COMMAND_COUNT.spec.ts
Normal file
19
packages/client/lib/commands/COMMAND_COUNT.spec.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import { transformArguments } from './COMMAND_COUNT';
|
||||
|
||||
describe('COMMAND COUNT', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments(),
|
||||
['COMMAND', 'COUNT']
|
||||
);
|
||||
});
|
||||
|
||||
testUtils.testWithClient('client.commandCount', async client => {
|
||||
assert.equal(
|
||||
typeof await client.commandCount(),
|
||||
'number'
|
||||
);
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
});
|
9
packages/client/lib/commands/COMMAND_COUNT.ts
Normal file
9
packages/client/lib/commands/COMMAND_COUNT.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { RedisCommandArguments } from '.';
|
||||
|
||||
export const IS_READ_ONLY = true;
|
||||
|
||||
export function transformArguments(): RedisCommandArguments {
|
||||
return ['COMMAND', 'COUNT'];
|
||||
}
|
||||
|
||||
export declare function transformReply(): number;
|
19
packages/client/lib/commands/COMMAND_GETKEYS.spec.ts
Normal file
19
packages/client/lib/commands/COMMAND_GETKEYS.spec.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import { transformArguments } from './COMMAND_GETKEYS';
|
||||
|
||||
describe('COMMAND GETKEYS', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments(['GET', 'key']),
|
||||
['COMMAND', 'GETKEYS', 'GET', 'key']
|
||||
);
|
||||
});
|
||||
|
||||
testUtils.testWithClient('client.commandGetKeys', async client => {
|
||||
assert.deepEqual(
|
||||
await client.commandGetKeys(['GET', 'key']),
|
||||
['key']
|
||||
);
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
});
|
9
packages/client/lib/commands/COMMAND_GETKEYS.ts
Normal file
9
packages/client/lib/commands/COMMAND_GETKEYS.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { RedisCommandArguments } from '.';
|
||||
|
||||
export const IS_READ_ONLY = true;
|
||||
|
||||
export function transformArguments(args: Array<string>): RedisCommandArguments {
|
||||
return ['COMMAND', 'GETKEYS', ...args];
|
||||
}
|
||||
|
||||
export declare function transformReply(): Array<string>;
|
36
packages/client/lib/commands/COMMAND_INFO.spec.ts
Normal file
36
packages/client/lib/commands/COMMAND_INFO.spec.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import { transformArguments } from './COMMAND_INFO';
|
||||
import { CommandCategories, CommandFlags, CommandReply } from './generic-transformers';
|
||||
|
||||
export function assertPingCommand(commandInfo: CommandReply | null | undefined): void {
|
||||
assert.deepEqual(
|
||||
commandInfo,
|
||||
{
|
||||
name: 'ping',
|
||||
arity: -1,
|
||||
flags: new Set([CommandFlags.STALE, CommandFlags.FAST]),
|
||||
firstKeyIndex: 0,
|
||||
lastKeyIndex: 0,
|
||||
step: 0,
|
||||
categories: new Set(
|
||||
testUtils.isVersionGreaterThan([6]) ?
|
||||
[CommandCategories.FAST, CommandCategories.CONNECTION] :
|
||||
[]
|
||||
)
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
describe('COMMAND INFO', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments(['PING']),
|
||||
['COMMAND', 'INFO', 'PING']
|
||||
);
|
||||
});
|
||||
|
||||
testUtils.testWithClient('client.commandInfo', async client => {
|
||||
assertPingCommand((await client.commandInfo(['PING']))[0]);
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
});
|
12
packages/client/lib/commands/COMMAND_INFO.ts
Normal file
12
packages/client/lib/commands/COMMAND_INFO.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { RedisCommandArguments } from '.';
|
||||
import { CommandRawReply, CommandReply, transformCommandReply } from './generic-transformers';
|
||||
|
||||
export const IS_READ_ONLY = true;
|
||||
|
||||
export function transformArguments(commands: Array<string>): RedisCommandArguments {
|
||||
return ['COMMAND', 'INFO', ...commands];
|
||||
}
|
||||
|
||||
export function transformReply(reply: Array<CommandRawReply | null>): Array<CommandReply | null> {
|
||||
return reply.map(command => command ? transformCommandReply(command) : null);
|
||||
}
|
11
packages/client/lib/commands/CONFIG_GET.spec.ts
Normal file
11
packages/client/lib/commands/CONFIG_GET.spec.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import { transformArguments } from './CONFIG_GET';
|
||||
|
||||
describe('CONFIG GET', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('*'),
|
||||
['CONFIG', 'GET', '*']
|
||||
);
|
||||
});
|
||||
});
|
5
packages/client/lib/commands/CONFIG_GET.ts
Normal file
5
packages/client/lib/commands/CONFIG_GET.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export function transformArguments(parameter: string): Array<string> {
|
||||
return ['CONFIG', 'GET', parameter];
|
||||
}
|
||||
|
||||
export { transformReplyTuples as transformReply } from './generic-transformers';
|
11
packages/client/lib/commands/CONFIG_RESETSTAT.spec.ts
Normal file
11
packages/client/lib/commands/CONFIG_RESETSTAT.spec.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import { transformArguments } from './CONFIG_RESETSTAT';
|
||||
|
||||
describe('CONFIG RESETSTAT', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments(),
|
||||
['CONFIG', 'RESETSTAT']
|
||||
);
|
||||
});
|
||||
});
|
5
packages/client/lib/commands/CONFIG_RESETSTAT.ts
Normal file
5
packages/client/lib/commands/CONFIG_RESETSTAT.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export function transformArguments(): Array<string> {
|
||||
return ['CONFIG', 'RESETSTAT'];
|
||||
}
|
||||
|
||||
export declare function transformReply(): string;
|
11
packages/client/lib/commands/CONFIG_REWRITE.spec.ts
Normal file
11
packages/client/lib/commands/CONFIG_REWRITE.spec.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import { transformArguments } from './CONFIG_REWRITE';
|
||||
|
||||
describe('CONFIG REWRITE', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments(),
|
||||
['CONFIG', 'REWRITE']
|
||||
);
|
||||
});
|
||||
});
|
5
packages/client/lib/commands/CONFIG_REWRITE.ts
Normal file
5
packages/client/lib/commands/CONFIG_REWRITE.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export function transformArguments(): Array<string> {
|
||||
return ['CONFIG', 'REWRITE'];
|
||||
}
|
||||
|
||||
export declare function transformReply(): string;
|
11
packages/client/lib/commands/CONFIG_SET.spec.ts
Normal file
11
packages/client/lib/commands/CONFIG_SET.spec.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import { transformArguments } from './CONFIG_SET';
|
||||
|
||||
describe('CONFIG SET', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('parameter', 'value'),
|
||||
['CONFIG', 'SET', 'parameter', 'value']
|
||||
);
|
||||
});
|
||||
});
|
5
packages/client/lib/commands/CONFIG_SET.ts
Normal file
5
packages/client/lib/commands/CONFIG_SET.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export function transformArguments(parameter: string, value: string): Array<string> {
|
||||
return ['CONFIG', 'SET', parameter, value];
|
||||
}
|
||||
|
||||
export declare function transformReply(): string;
|
67
packages/client/lib/commands/COPY.spec.ts
Normal file
67
packages/client/lib/commands/COPY.spec.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import { transformArguments, transformReply } from './COPY';
|
||||
|
||||
describe('COPY', () => {
|
||||
testUtils.isVersionGreaterThanHook([6, 2]);
|
||||
|
||||
describe('transformArguments', () => {
|
||||
it('simple', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('source', 'destination'),
|
||||
['COPY', 'source', 'destination']
|
||||
);
|
||||
});
|
||||
|
||||
it('with destination DB flag', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('source', 'destination', {
|
||||
destinationDb: 1
|
||||
}),
|
||||
['COPY', 'source', 'destination', 'DB', '1']
|
||||
);
|
||||
});
|
||||
|
||||
it('with replace flag', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('source', 'destination', {
|
||||
replace: true
|
||||
}),
|
||||
['COPY', 'source', 'destination', 'REPLACE']
|
||||
);
|
||||
});
|
||||
|
||||
it('with both flags', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('source', 'destination', {
|
||||
destinationDb: 1,
|
||||
replace: true
|
||||
}),
|
||||
['COPY', 'source', 'destination', 'DB', '1', 'REPLACE']
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('transformReply', () => {
|
||||
it('0', () => {
|
||||
assert.equal(
|
||||
transformReply(0),
|
||||
false
|
||||
);
|
||||
});
|
||||
|
||||
it('1', () => {
|
||||
assert.equal(
|
||||
transformReply(1),
|
||||
true
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
testUtils.testWithClient('client.copy', async client => {
|
||||
assert.equal(
|
||||
await client.copy('source', 'destination'),
|
||||
false
|
||||
);
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
});
|
22
packages/client/lib/commands/COPY.ts
Normal file
22
packages/client/lib/commands/COPY.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
interface CopyCommandOptions {
|
||||
destinationDb?: number;
|
||||
replace?: boolean;
|
||||
}
|
||||
|
||||
export const FIRST_KEY_INDEX = 1;
|
||||
|
||||
export function transformArguments(source: string, destination: string, options?: CopyCommandOptions): Array<string> {
|
||||
const args = ['COPY', source, destination];
|
||||
|
||||
if (options?.destinationDb) {
|
||||
args.push('DB', options.destinationDb.toString());
|
||||
}
|
||||
|
||||
if (options?.replace) {
|
||||
args.push('REPLACE');
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
export { transformReplyBoolean as transformReply } from './generic-transformers';
|
19
packages/client/lib/commands/DBSIZE.spec.ts
Normal file
19
packages/client/lib/commands/DBSIZE.spec.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import { transformArguments } from './DBSIZE';
|
||||
|
||||
describe('DBSIZE', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments(),
|
||||
['DBSIZE']
|
||||
);
|
||||
});
|
||||
|
||||
testUtils.testWithClient('client.dbSize', async client => {
|
||||
assert.equal(
|
||||
await client.dbSize(),
|
||||
0
|
||||
);
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
});
|
7
packages/client/lib/commands/DBSIZE.ts
Normal file
7
packages/client/lib/commands/DBSIZE.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
export const IS_READ_ONLY = true;
|
||||
|
||||
export function transformArguments(): Array<string> {
|
||||
return ['DBSIZE'];
|
||||
}
|
||||
|
||||
export declare function transformReply(): number;
|
19
packages/client/lib/commands/DECR.spec.ts
Normal file
19
packages/client/lib/commands/DECR.spec.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import { transformArguments } from './DECR';
|
||||
|
||||
describe('DECR', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key'),
|
||||
['DECR', 'key']
|
||||
);
|
||||
});
|
||||
|
||||
testUtils.testWithClient('client.decr', async client => {
|
||||
assert.equal(
|
||||
await client.decr('key'),
|
||||
-1
|
||||
);
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
});
|
7
packages/client/lib/commands/DECR.ts
Normal file
7
packages/client/lib/commands/DECR.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
export const FIRST_KEY_INDEX = 1;
|
||||
|
||||
export function transformArguments(key: string): Array<string> {
|
||||
return ['DECR', key];
|
||||
}
|
||||
|
||||
export declare function transformReply(): number;
|
19
packages/client/lib/commands/DECRBY.spec.ts
Normal file
19
packages/client/lib/commands/DECRBY.spec.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import { transformArguments } from './DECRBY';
|
||||
|
||||
describe('DECRBY', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key', 2),
|
||||
['DECRBY', 'key', '2']
|
||||
);
|
||||
});
|
||||
|
||||
testUtils.testWithClient('client.decrBy', async client => {
|
||||
assert.equal(
|
||||
await client.decrBy('key', 2),
|
||||
-2
|
||||
);
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
});
|
7
packages/client/lib/commands/DECRBY.ts
Normal file
7
packages/client/lib/commands/DECRBY.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
export const FIRST_KEY_INDEX = 1;
|
||||
|
||||
export function transformArguments(key: string, decrement: number): Array<string> {
|
||||
return ['DECRBY', key, decrement.toString()];
|
||||
}
|
||||
|
||||
export declare function transformReply(): number;
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user