1
0
mirror of https://github.com/redis/node-redis.git synced 2025-08-07 13:22:56 +03:00
This commit is contained in:
dovi
2023-05-03 17:34:07 -04:00
59 changed files with 443 additions and 348 deletions

View File

@@ -385,10 +385,10 @@ export class Decoder {
} }
// Precalculated multipliers for decimal points to improve performance // Precalculated multipliers for decimal points to improve performance
// "A Number only keeps about 17 decimal places of precision" // "... about 15 to 17 decimal places ..."
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number#:~:text=about%2015%20to%2017%20decimal%20places
static _DOUBLE_DECIMAL_MULTIPLIERS = [ static _DOUBLE_DECIMAL_MULTIPLIERS = [
0.1, 0.01, 0.001, 0.0001, 0.00001, 0.000001, 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6,
1e-7, 1e-8, 1e-9, 1e-10, 1e-11, 1e-12, 1e-7, 1e-8, 1e-9, 1e-10, 1e-11, 1e-12,
1e-13, 1e-14, 1e-15, 1e-16, 1e-17 1e-13, 1e-14, 1e-15, 1e-16, 1e-17
]; ];

View File

@@ -19,7 +19,7 @@ describe('BITOP', () => {
}); });
}); });
testUtils.testAll('client.bitOp', async client => { testUtils.testAll('bitOp', async client => {
assert.equal( assert.equal(
await client.bitOp('AND', '{tag}destKey', '{tag}key'), await client.bitOp('AND', '{tag}destKey', '{tag}key'),
0 0

View File

@@ -1,6 +1,7 @@
import { SimpleStringReply, Command } from '../RESP/types'; import { SimpleStringReply, Command } from '../RESP/types';
export default { export default {
FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: true, IS_READ_ONLY: true,
transformArguments(value: boolean) { transformArguments(value: boolean) {
return [ return [

View File

@@ -1,6 +1,7 @@
import { BlobStringReply, NullReply, Command } from '../RESP/types'; import { BlobStringReply, NullReply, Command } from '../RESP/types';
export default { export default {
FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: true, IS_READ_ONLY: true,
transformArguments() { transformArguments() {
return [ return [

View File

@@ -1,6 +1,7 @@
import { NumberReply, Command } from '../RESP/types'; import { NumberReply, Command } from '../RESP/types';
export default { export default {
FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: true, IS_READ_ONLY: true,
transformArguments() { transformArguments() {
return ['CLIENT', 'GETREDIR'] return ['CLIENT', 'GETREDIR']

View File

@@ -1,6 +1,7 @@
import { NumberReply, Command } from '../RESP/types'; import { NumberReply, Command } from '../RESP/types';
export default { export default {
FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: true, IS_READ_ONLY: true,
transformArguments() { transformArguments() {
return ['CLIENT', 'ID']; return ['CLIENT', 'ID'];

View File

@@ -56,6 +56,7 @@ export interface ClientInfoReply {
const CLIENT_INFO_REGEX = /([^\s=]+)=([^\s]*)/g; const CLIENT_INFO_REGEX = /([^\s=]+)=([^\s]*)/g;
export default { export default {
FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: true, IS_READ_ONLY: true,
transformArguments() { transformArguments() {
return ['CLIENT', 'INFO'] return ['CLIENT', 'INFO']

View File

@@ -42,6 +42,7 @@ export type ClientKillSkipMe = CLIENT_KILL_FILTERS['SKIP_ME'] | (ClientKillFilte
export type ClientKillFilter = ClientKillAddress | ClientKillLocalAddress | ClientKillId | ClientKillType | ClientKillUser | ClientKillSkipMe; export type ClientKillFilter = ClientKillAddress | ClientKillLocalAddress | ClientKillId | ClientKillType | ClientKillUser | ClientKillSkipMe;
export default { export default {
FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: true, IS_READ_ONLY: true,
transformArguments(filters: ClientKillFilter | Array<ClientKillFilter>) { transformArguments(filters: ClientKillFilter | Array<ClientKillFilter>) {
const args = ['CLIENT', 'KILL']; const args = ['CLIENT', 'KILL'];

View File

@@ -15,6 +15,7 @@ export interface ListFilterId {
export type ListFilter = ListFilterType | ListFilterId; export type ListFilter = ListFilterType | ListFilterId;
export default { export default {
FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: true, IS_READ_ONLY: true,
transformArguments(filter?: ListFilter) { transformArguments(filter?: ListFilter) {
let args: Array<RedisArgument> = ['CLIENT', 'LIST']; let args: Array<RedisArgument> = ['CLIENT', 'LIST'];

View File

@@ -1,6 +1,7 @@
import { SimpleStringReply, Command } from '../RESP/types'; import { SimpleStringReply, Command } from '../RESP/types';
export default { export default {
FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: true, IS_READ_ONLY: true,
transformArguments(value: boolean) { transformArguments(value: boolean) {
return [ return [

View File

@@ -1,6 +1,7 @@
import { SimpleStringReply, Command } from '../RESP/types'; import { SimpleStringReply, Command } from '../RESP/types';
export default { export default {
FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: true, IS_READ_ONLY: true,
transformArguments(timeout: number, mode?: 'WRITE' | 'ALL') { transformArguments(timeout: number, mode?: 'WRITE' | 'ALL') {
const args = [ const args = [

View File

@@ -1,6 +1,7 @@
import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; import { RedisArgument, SimpleStringReply, Command } from '../RESP/types';
export default { export default {
FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: true, IS_READ_ONLY: true,
transformArguments(name: RedisArgument) { transformArguments(name: RedisArgument) {
return ['CLIENT', 'SETNAME', name]; return ['CLIENT', 'SETNAME', name];

View File

@@ -1,6 +1,7 @@
import { SimpleStringReply, Command } from '../RESP/types'; import { SimpleStringReply, Command } from '../RESP/types';
export default { export default {
FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: true, IS_READ_ONLY: true,
transformArguments() { transformArguments() {
return ['CLIENT', 'UNPAUSE']; return ['CLIENT', 'UNPAUSE'];

View File

@@ -2,6 +2,7 @@ import { SimpleStringReply, Command } from '../RESP/types';
import { pushVariadicNumberArguments } from './generic-transformers'; import { pushVariadicNumberArguments } from './generic-transformers';
export default { export default {
FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: true, IS_READ_ONLY: true,
transformArguments(slots: number | Array<number>) { transformArguments(slots: number | Array<number>) {
return pushVariadicNumberArguments( return pushVariadicNumberArguments(

View File

@@ -2,6 +2,7 @@ import { SimpleStringReply, Command } from '../RESP/types';
import { pushSlotRangesArguments, SlotRange } from './generic-transformers'; import { pushSlotRangesArguments, SlotRange } from './generic-transformers';
export default { export default {
FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: true, IS_READ_ONLY: true,
transformArguments(ranges: SlotRange | Array<SlotRange>) { transformArguments(ranges: SlotRange | Array<SlotRange>) {
return pushSlotRangesArguments( return pushSlotRangesArguments(

View File

@@ -1,6 +1,7 @@
import { SimpleStringReply, Command } from '../RESP/types'; import { SimpleStringReply, Command } from '../RESP/types';
export default { export default {
FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: true, IS_READ_ONLY: true,
transformArguments() { transformArguments() {
return ['CLUSTER', 'BUMPEPOCH']; return ['CLUSTER', 'BUMPEPOCH'];

View File

@@ -1,6 +1,7 @@
import { RedisArgument, NumberReply, Command } from '../RESP/types'; import { RedisArgument, NumberReply, Command } from '../RESP/types';
export default { export default {
FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: true, IS_READ_ONLY: true,
transformArguments(nodeId: RedisArgument) { transformArguments(nodeId: RedisArgument) {
return ['CLUSTER', 'COUNT-FAILURE-REPORTS', nodeId]; return ['CLUSTER', 'COUNT-FAILURE-REPORTS', nodeId];

View File

@@ -1,6 +1,7 @@
import { NumberReply, Command } from '../RESP/types'; import { NumberReply, Command } from '../RESP/types';
export default { export default {
FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: true, IS_READ_ONLY: true,
transformArguments(slot: number) { transformArguments(slot: number) {
return ['CLUSTER', 'COUNT-FAILURE-REPORTS', slot.toString()]; return ['CLUSTER', 'COUNT-FAILURE-REPORTS', slot.toString()];

View File

@@ -2,6 +2,7 @@ import { SimpleStringReply, Command } from '../RESP/types';
import { pushVariadicNumberArguments } from './generic-transformers'; import { pushVariadicNumberArguments } from './generic-transformers';
export default { export default {
FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: true, IS_READ_ONLY: true,
transformArguments(slots: number | Array<number>) { transformArguments(slots: number | Array<number>) {
return pushVariadicNumberArguments( return pushVariadicNumberArguments(

View File

@@ -2,6 +2,7 @@ import { SimpleStringReply, Command } from '../RESP/types';
import { pushSlotRangesArguments, SlotRange } from './generic-transformers'; import { pushSlotRangesArguments, SlotRange } from './generic-transformers';
export default { export default {
FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: true, IS_READ_ONLY: true,
transformArguments(ranges: SlotRange | Array<SlotRange>) { transformArguments(ranges: SlotRange | Array<SlotRange>) {
return pushSlotRangesArguments( return pushSlotRangesArguments(

View File

@@ -8,6 +8,7 @@ export const FAILOVER_MODES = {
export type FailoverModes = typeof FAILOVER_MODES[keyof typeof FAILOVER_MODES]; export type FailoverModes = typeof FAILOVER_MODES[keyof typeof FAILOVER_MODES];
export default { export default {
FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: true, IS_READ_ONLY: true,
transformArguments(mode?: FailoverModes) { transformArguments(mode?: FailoverModes) {
const args = ['CLUSTER', 'FAILOVER']; const args = ['CLUSTER', 'FAILOVER'];

View File

@@ -1,6 +1,7 @@
import { SimpleStringReply, Command } from '../RESP/types'; import { SimpleStringReply, Command } from '../RESP/types';
export default { export default {
FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: true, IS_READ_ONLY: true,
transformArguments() { transformArguments() {
return ['CLUSTER', 'FLUSHSLOTS']; return ['CLUSTER', 'FLUSHSLOTS'];

View File

@@ -1,6 +1,7 @@
import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; import { RedisArgument, SimpleStringReply, Command } from '../RESP/types';
export default { export default {
FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: true, IS_READ_ONLY: true,
transformArguments(nodeId: RedisArgument) { transformArguments(nodeId: RedisArgument) {
return ['CLUSTER', 'FORGET', nodeId]; return ['CLUSTER', 'FORGET', nodeId];

View File

@@ -1,6 +1,7 @@
import { ArrayReply, BlobStringReply, Command } from '../RESP/types'; import { ArrayReply, BlobStringReply, Command } from '../RESP/types';
export default { export default {
FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: true, IS_READ_ONLY: true,
transformArguments(slot: number, count: number) { transformArguments(slot: number, count: number) {
return ['CLUSTER', 'GETKEYSINSLOT', slot.toString(), count.toString()]; return ['CLUSTER', 'GETKEYSINSLOT', slot.toString(), count.toString()];

View File

@@ -16,6 +16,7 @@ type ClusterSlotsRawReply = ArrayReply<[
export type ClusterSlotsNode = ReturnType<typeof transformNode>; export type ClusterSlotsNode = ReturnType<typeof transformNode>;
export default { export default {
FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: true, IS_READ_ONLY: true,
transformArguments() { transformArguments() {
return ['CLUSTER', 'SLOTS']; return ['CLUSTER', 'SLOTS'];

View File

@@ -2,6 +2,7 @@ import { RedisArgument, Command } from '../RESP/types';
import { transformTuplesReply } from './generic-transformers'; import { transformTuplesReply } from './generic-transformers';
export default { export default {
FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: true, IS_READ_ONLY: true,
transformArguments(parameter: RedisArgument) { transformArguments(parameter: RedisArgument) {
return ['CONFIG', 'GET', parameter]; return ['CONFIG', 'GET', parameter];

View File

@@ -1,6 +1,7 @@
import { NumberReply, Command } from '../RESP/types'; import { NumberReply, Command } from '../RESP/types';
export default { export default {
FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: true, IS_READ_ONLY: true,
transformArguments() { transformArguments() {
return ['DBSIZE']; return ['DBSIZE'];

View File

@@ -3,6 +3,7 @@ import { RedisVariadicArgument, pushVariadicArguments } from './generic-transfor
export default { export default {
FIRST_KEY_INDEX: 1, FIRST_KEY_INDEX: 1,
IS_READ_ONLY: false,
transformArguments(keys: RedisVariadicArgument) { transformArguments(keys: RedisVariadicArgument) {
return pushVariadicArguments(['DEL'], keys); return pushVariadicArguments(['DEL'], keys);
}, },

View File

@@ -1,6 +1,7 @@
import { RedisArgument, BlobStringReply, Command } from '../RESP/types'; import { RedisArgument, BlobStringReply, Command } from '../RESP/types';
export default { export default {
FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: true, IS_READ_ONLY: true,
transformArguments(message: RedisArgument) { transformArguments(message: RedisArgument) {
return ['ECHO', message]; return ['ECHO', message];

View File

@@ -1,26 +1,22 @@
import { strict as assert } from 'assert'; import { strict as assert } from 'assert';
import testUtils, { GLOBAL } from '../test-utils'; import testUtils, { GLOBAL } from '../test-utils';
import { transformArguments } from './GETBIT'; import GETBIT from './GETBIT';
describe('GETBIT', () => { describe('GETBIT', () => {
it('transformArguments', () => { it('transformArguments', () => {
assert.deepEqual( assert.deepEqual(
transformArguments('key', 0), GETBIT.transformArguments('key', 0),
['GETBIT', 'key', '0'] ['GETBIT', 'key', '0']
); );
}); });
testUtils.testWithClient('client.getBit', async client => { testUtils.testAll('getBit', async client => {
assert.equal( assert.equal(
await client.getBit('key', 0), await client.getBit('key', 0),
0 0
); );
}, GLOBAL.SERVERS.OPEN); }, {
client: GLOBAL.SERVERS.OPEN,
testUtils.testWithCluster('cluster.getBit', async cluster => { cluster: GLOBAL.CLUSTERS.OPEN
assert.equal( });
await cluster.getBit('key', 0),
0
);
}, GLOBAL.CLUSTERS.OPEN);
}); });

View File

@@ -6,7 +6,17 @@ describe('GETEX', () => {
testUtils.isVersionGreaterThanHook([6, 2]); testUtils.isVersionGreaterThanHook([6, 2]);
describe('transformArguments', () => { describe('transformArguments', () => {
it('EX', () => { it('EX | PX', () => {
assert.deepEqual(
GETEX.transformArguments('key', {
type: 'EX',
value: 1
}),
['GETEX', 'key', 'EX', '1']
);
});
it('EX (backwards compatibility)', () => {
assert.deepEqual( assert.deepEqual(
GETEX.transformArguments('key', { GETEX.transformArguments('key', {
EX: 1 EX: 1
@@ -15,7 +25,7 @@ describe('GETEX', () => {
); );
}); });
it('PX', () => { it('PX (backwards compatibility)', () => {
assert.deepEqual( assert.deepEqual(
GETEX.transformArguments('key', { GETEX.transformArguments('key', {
PX: 1 PX: 1
@@ -24,7 +34,29 @@ describe('GETEX', () => {
); );
}); });
describe('EXAT', () => { describe('EXAT | PXAT', () => {
it('number', () => {
assert.deepEqual(
GETEX.transformArguments('key', {
type: 'EXAT',
value: 1
}),
['GETEX', 'key', 'EXAT', '1']
);
});
it('date', () => {
const d = new Date();
assert.deepEqual(
GETEX.transformArguments('key', {
EXAT: d
}),
['GETEX', 'key', 'EXAT', Math.floor(d.getTime() / 1000).toString()]
);
});
});
describe('EXAT (backwards compatibility)', () => {
it('number', () => { it('number', () => {
assert.deepEqual( assert.deepEqual(
GETEX.transformArguments('key', { GETEX.transformArguments('key', {
@@ -45,7 +77,7 @@ describe('GETEX', () => {
}); });
}); });
describe('PXAT', () => { describe('PXAT (backwards compatibility)', () => {
it('number', () => { it('number', () => {
assert.deepEqual( assert.deepEqual(
GETEX.transformArguments('key', { GETEX.transformArguments('key', {
@@ -66,7 +98,7 @@ describe('GETEX', () => {
}); });
}); });
it('PERSIST', () => { it('PERSIST (backwards compatibility)', () => {
assert.deepEqual( assert.deepEqual(
GETEX.transformArguments('key', { GETEX.transformArguments('key', {
PERSIST: true PERSIST: true
@@ -79,7 +111,7 @@ describe('GETEX', () => {
testUtils.testAll('getEx', async client => { testUtils.testAll('getEx', async client => {
assert.equal( assert.equal(
await client.getEx('key', { await client.getEx('key', {
PERSIST: true type: 'PERSIST'
}), }),
null null
); );

View File

@@ -1,36 +1,77 @@
import { RedisArgument, BlobStringReply, NullReply, Command } from '../RESP/types'; import { RedisArgument, BlobStringReply, NullReply, Command } from '../RESP/types';
import { transformEXAT, transformPXAT } from './generic-transformers'; import { transformEXAT, transformPXAT } from './generic-transformers';
export type GetExModes = { export type GetExOptions = {
type: 'EX' | 'PX';
value: number;
} | {
type: 'EXAT' | 'PXAT';
value: number | Date;
} | {
type: 'PERSIST';
} | {
/**
* @deprecated Use `{ type: 'EX', value: number }` instead.
*/
EX: number; EX: number;
} | { } | {
/**
* @deprecated Use `{ type: 'PX', value: number }` instead.
*/
PX: number; PX: number;
} | { } | {
/**
* @deprecated Use `{ type: 'EXAT', value: number | Date }` instead.
*/
EXAT: number | Date; EXAT: number | Date;
} | { } | {
/**
* @deprecated Use `{ type: 'PXAT', value: number | Date }` instead.
*/
PXAT: number | Date; PXAT: number | Date;
} | { } | {
/**
* @deprecated Use `{ type: 'PERSIST' }` instead.
*/
PERSIST: true; PERSIST: true;
}; };
export default { export default {
FIRST_KEY_INDEX: 1, FIRST_KEY_INDEX: 1,
IS_READ_ONLY: true, IS_READ_ONLY: true,
transformArguments(key: RedisArgument, mode: GetExModes) { transformArguments(key: RedisArgument, options: GetExOptions) {
const args = ['GETEX', key]; const args = ['GETEX', key];
if ('EX' in mode) { if ('type' in options) {
args.push('EX', mode.EX.toString()); switch (options.type) {
} else if ('PX' in mode) { case 'EX':
args.push('PX', mode.PX.toString()); case 'PX':
} else if ('EXAT' in mode) { args.push(options.type, options.value.toString());
args.push('EXAT', transformEXAT(mode.EXAT)); break;
} else if ('PXAT' in mode) {
args.push('PXAT', transformPXAT(mode.PXAT)); case 'EXAT':
} else { // PERSIST case 'PXAT':
args.push('PERSIST'); args.push(options.type, transformEXAT(options.value));
} break;
case 'PERSIST':
args.push('PERSIST');
break;
}
} else {
if ('EX' in options) {
args.push('EX', options.EX.toString());
} else if ('PX' in options) {
args.push('PX', options.PX.toString());
} else if ('EXAT' in options) {
args.push('EXAT', transformEXAT(options.EXAT));
} else if ('PXAT' in options) {
args.push('PXAT', transformPXAT(options.PXAT));
} else { // PERSIST
args.push('PERSIST');
}
}
return args; return args;
}, },
transformReply: undefined as unknown as () => BlobStringReply | NullReply transformReply: undefined as unknown as () => BlobStringReply | NullReply

View File

@@ -1,21 +1,24 @@
import { strict as assert } from 'assert'; import { strict as assert } from 'assert';
import testUtils, { GLOBAL } from '../test-utils'; import testUtils, { GLOBAL } from '../test-utils';
import { transformArguments } from './HRANDFIELD_COUNT'; import HRANDFIELD_COUNT from './HRANDFIELD_COUNT';
describe('HRANDFIELD COUNT', () => { describe('HRANDFIELD COUNT', () => {
testUtils.isVersionGreaterThanHook([6, 2, 5]); testUtils.isVersionGreaterThanHook([6, 2, 5]);
it('transformArguments', () => { it('transformArguments', () => {
assert.deepEqual( assert.deepEqual(
transformArguments('key', 1), HRANDFIELD_COUNT.transformArguments('key', 1),
['HRANDFIELD', 'key', '1'] ['HRANDFIELD', 'key', '1']
); );
}); });
testUtils.testWithClient('client.hRandFieldCount', async client => { testUtils.testAll('hRandFieldCount', async client => {
assert.deepEqual( assert.deepEqual(
await client.hRandFieldCount('key', 1), await client.hRandFieldCount('key', 1),
[] []
); );
}, GLOBAL.SERVERS.OPEN); }, {
client: GLOBAL.SERVERS.OPEN,
cluster: GLOBAL.CLUSTERS.OPEN
});
}); });

View File

@@ -1,77 +1,56 @@
import { strict as assert } from 'assert'; import { strict as assert } from 'assert';
import testUtils, { GLOBAL } from '../test-utils'; import testUtils, { GLOBAL } from '../test-utils';
import { transformArguments, transformReply } from './HSCAN'; import HSCAN from './HSCAN';
describe('HSCAN', () => { describe('HSCAN', () => {
describe('transformArguments', () => { describe('transformArguments', () => {
it('cusror only', () => { it('cusror only', () => {
assert.deepEqual( assert.deepEqual(
transformArguments('key', 0), HSCAN.transformArguments('key', 0),
['HSCAN', 'key', '0'] ['HSCAN', 'key', '0']
); );
});
it('with MATCH', () => {
assert.deepEqual(
transformArguments('key', 0, {
MATCH: 'pattern'
}),
['HSCAN', 'key', '0', 'MATCH', 'pattern']
);
});
it('with COUNT', () => {
assert.deepEqual(
transformArguments('key', 0, {
COUNT: 1
}),
['HSCAN', 'key', '0', 'COUNT', '1']
);
});
it('with MATCH & COUNT', () => {
assert.deepEqual(
transformArguments('key', 0, {
MATCH: 'pattern',
COUNT: 1
}),
['HSCAN', 'key', '0', 'MATCH', 'pattern', 'COUNT', '1']
);
});
}); });
describe('transformReply', () => { it('with MATCH', () => {
it('without tuples', () => { assert.deepEqual(
assert.deepEqual( HSCAN.transformArguments('key', 0, {
transformReply(['0', []]), MATCH: 'pattern'
{ }),
cursor: 0, ['HSCAN', 'key', '0', 'MATCH', 'pattern']
tuples: [] );
}
);
});
it('with tuples', () => {
assert.deepEqual(
transformReply(['0', ['field', 'value']]),
{
cursor: 0,
tuples: [{
field: 'field',
value: 'value'
}]
}
);
});
}); });
testUtils.testWithClient('client.hScan', async client => { it('with COUNT', () => {
assert.deepEqual( assert.deepEqual(
await client.hScan('key', 0), HSCAN.transformArguments('key', 0, {
{ COUNT: 1
cursor: 0, }),
tuples: [] ['HSCAN', 'key', '0', 'COUNT', '1']
} );
); });
}, GLOBAL.SERVERS.OPEN);
it('with MATCH & COUNT', () => {
assert.deepEqual(
HSCAN.transformArguments('key', 0, {
MATCH: 'pattern',
COUNT: 1
}),
['HSCAN', 'key', '0', 'MATCH', 'pattern', 'COUNT', '1']
);
});
});
testUtils.testWithClient('client.hScan', async client => {
await client.hSet('key', 'field', 'value');
assert.deepEqual(
await client.hScan('key', 0),
{
cursor: 0,
entries: [{
field: 'field',
value: 'value'
}]
}
);
}, GLOBAL.SERVERS.OPEN);
}); });

View File

@@ -1,74 +1,70 @@
import { strict as assert } from 'assert'; import { strict as assert } from 'assert';
import { transformArguments } from './HSET';
import testUtils, { GLOBAL } from '../test-utils'; import testUtils, { GLOBAL } from '../test-utils';
import HSET from './HSET';
describe('HSET', () => { describe('HSET', () => {
describe('transformArguments', () => { describe('transformArguments', () => {
describe('field, value', () => { describe('field, value', () => {
it('string', () => { it('string', () => {
assert.deepEqual( assert.deepEqual(
transformArguments('key', 'field', 'value'), HSET.transformArguments('key', 'field', 'value'),
['HSET', 'key', 'field', 'value'] ['HSET', 'key', 'field', 'value']
); );
}); });
it('number', () => { it('number', () => {
assert.deepEqual( assert.deepEqual(
transformArguments('key', 1, 2), HSET.transformArguments('key', 1, 2),
['HSET', 'key', '1', '2'] ['HSET', 'key', '1', '2']
); );
}); });
it('Buffer', () => { it('Buffer', () => {
assert.deepEqual( assert.deepEqual(
transformArguments(Buffer.from('key'), Buffer.from('field'), Buffer.from('value')), HSET.transformArguments(Buffer.from('key'), Buffer.from('field'), Buffer.from('value')),
['HSET', Buffer.from('key'), Buffer.from('field'), Buffer.from('value')] ['HSET', Buffer.from('key'), Buffer.from('field'), Buffer.from('value')]
); );
}); });
});
it('Map', () => {
assert.deepEqual(
transformArguments('key', new Map([['field', 'value']])),
['HSET', 'key', 'field', 'value']
);
});
it('Array', () => {
assert.deepEqual(
transformArguments('key', [['field', 'value']]),
['HSET', 'key', 'field', 'value']
);
});
describe('Object', () => {
it('string', () => {
assert.deepEqual(
transformArguments('key', { field: 'value' }),
['HSET', 'key', 'field', 'value']
);
});
it('Buffer', () => {
assert.deepEqual(
transformArguments('key', { field: Buffer.from('value') }),
['HSET', 'key', 'field', Buffer.from('value')]
);
});
});
}); });
testUtils.testWithClient('client.hSet', async client => { it('Map', () => {
assert.equal( assert.deepEqual(
await client.hSet('key', 'field', 'value'), HSET.transformArguments('key', new Map([['field', 'value']])),
1 ['HSET', 'key', 'field', 'value']
); );
}, GLOBAL.SERVERS.OPEN); });
testUtils.testWithCluster('cluster.hSet', async cluster => { it('Array', () => {
assert.equal( assert.deepEqual(
await cluster.hSet('key', { field: 'value' }), HSET.transformArguments('key', [['field', 'value']]),
1 ['HSET', 'key', 'field', 'value']
);
});
describe('Object', () => {
it('string', () => {
assert.deepEqual(
HSET.transformArguments('key', { field: 'value' }),
['HSET', 'key', 'field', 'value']
); );
}, GLOBAL.CLUSTERS.OPEN); });
it('Buffer', () => {
assert.deepEqual(
HSET.transformArguments('key', { field: Buffer.from('value') }),
['HSET', 'key', 'field', Buffer.from('value')]
);
});
});
});
testUtils.testAll('hSet', async client => {
assert.equal(
await client.hSet('key', 'field', 'value'),
1
);
}, {
client: GLOBAL.SERVERS.OPEN,
cluster: GLOBAL.CLUSTERS.OPEN
});
}); });

View File

@@ -1,19 +1,22 @@
import { strict as assert } from 'assert'; import { strict as assert } from 'assert';
import testUtils, { GLOBAL } from '../test-utils'; import testUtils, { GLOBAL } from '../test-utils';
import { transformArguments } from './HSETNX'; import HSETNX from './HSETNX';
describe('HSETNX', () => { describe('HSETNX', () => {
it('transformArguments', () => { it('transformArguments', () => {
assert.deepEqual( assert.deepEqual(
transformArguments('key', 'field', 'value'), HSETNX.transformArguments('key', 'field', 'value'),
['HSETNX', 'key', 'field', 'value'] ['HSETNX', 'key', 'field', 'value']
); );
}); });
testUtils.testWithClient('client.hSetNX', async client => { testUtils.testAll('hSetNX', async client => {
assert.equal( assert.equal(
await client.hSetNX('key', 'field', 'value'), await client.hSetNX('key', 'field', 'value'),
true 1
); );
}, GLOBAL.SERVERS.OPEN); }, {
client: GLOBAL.SERVERS.OPEN,
cluster: GLOBAL.CLUSTERS.OPEN
});
}); });

View File

@@ -1,19 +1,22 @@
import { strict as assert } from 'assert'; import { strict as assert } from 'assert';
import testUtils, { GLOBAL } from '../test-utils'; import testUtils, { GLOBAL } from '../test-utils';
import { transformArguments } from './HSTRLEN'; import HSTRLEN from './HSTRLEN';
describe('HSTRLEN', () => { describe('HSTRLEN', () => {
it('transformArguments', () => { it('transformArguments', () => {
assert.deepEqual( assert.deepEqual(
transformArguments('key', 'field'), HSTRLEN.transformArguments('key', 'field'),
['HSTRLEN', 'key', 'field'] ['HSTRLEN', 'key', 'field']
); );
}); });
testUtils.testWithClient('client.hStrLen', async client => { testUtils.testAll('hStrLen', async client => {
assert.equal( assert.equal(
await client.hStrLen('key', 'field'), await client.hStrLen('key', 'field'),
0 0
); );
}, GLOBAL.SERVERS.OPEN); }, {
client: GLOBAL.SERVERS.OPEN,
cluster: GLOBAL.CLUSTERS.OPEN
});
}); });

View File

@@ -4,7 +4,7 @@ export default {
FIRST_KEY_INDEX: 1, FIRST_KEY_INDEX: 1,
IS_READ_ONLY: true, IS_READ_ONLY: true,
transformArguments(key: RedisArgument, field: RedisArgument) { transformArguments(key: RedisArgument, field: RedisArgument) {
return ['HSETLEN', key, field]; return ['HSTRLEN', key, field];
}, },
transformReply: undefined as unknown as () => ArrayReply<BlobStringReply> transformReply: undefined as unknown as () => ArrayReply<BlobStringReply>
} as const satisfies Command; } as const satisfies Command;

View File

@@ -1,19 +1,22 @@
import { strict as assert } from 'assert'; import { strict as assert } from 'assert';
import testUtils, { GLOBAL } from '../test-utils'; import testUtils, { GLOBAL } from '../test-utils';
import { transformArguments } from './HVALS'; import HVALS from './HVALS';
describe('HVALS', () => { describe('HVALS', () => {
it('transformArguments', () => { it('transformArguments', () => {
assert.deepEqual( assert.deepEqual(
transformArguments('key'), HVALS.transformArguments('key'),
['HVALS', 'key'] ['HVALS', 'key']
); );
}); });
testUtils.testWithClient('client.hVals', async client => { testUtils.testAll('hVals', async client => {
assert.deepEqual( assert.deepEqual(
await client.hVals('key'), await client.hVals('key'),
[] []
); );
}, GLOBAL.SERVERS.OPEN); }, {
client: GLOBAL.SERVERS.OPEN,
cluster: GLOBAL.CLUSTERS.OPEN
});
}); });

View File

@@ -1,6 +1,7 @@
import { RedisArgument, VerbatimStringReply, Command } from '../RESP/types'; import { RedisArgument, VerbatimStringReply, Command } from '../RESP/types';
export default { export default {
FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: true, IS_READ_ONLY: true,
transformArguments(section?: RedisArgument) { transformArguments(section?: RedisArgument) {
const args: Array<RedisArgument> = ['INFO']; const args: Array<RedisArgument> = ['INFO'];

View File

@@ -2,7 +2,7 @@ import { strict as assert } from 'assert';
import testUtils, { GLOBAL } from '../test-utils'; import testUtils, { GLOBAL } from '../test-utils';
describe('KEYS', () => { describe('KEYS', () => {
testUtils.testAll('client.keys', async client => { testUtils.testAll('keys', async client => {
assert.deepEqual( assert.deepEqual(
await client.keys('pattern'), await client.keys('pattern'),
[] []

View File

@@ -1,28 +1,24 @@
import { strict as assert } from 'assert'; import { strict as assert } from 'assert';
import testUtils, { GLOBAL } from '../test-utils'; import testUtils, { GLOBAL } from '../test-utils';
import { transformArguments } from './LCS_LEN'; import LCS_LEN from './LCS_LEN';
describe('LCS_LEN', () => { describe('LCS_LEN', () => {
testUtils.isVersionGreaterThanHook([7]); testUtils.isVersionGreaterThanHook([7]);
it('transformArguments', () => { it('transformArguments', () => {
assert.deepEqual( assert.deepEqual(
transformArguments('1', '2'), LCS_LEN.transformArguments('1', '2'),
['LCS', '1', '2', 'LEN'] ['LCS', '1', '2', 'LEN']
); );
}); });
testUtils.testWithClient('client.lcsLen', async client => { testUtils.testAll('lcsLen', async client => {
assert.equal( assert.equal(
await client.lcsLen('1', '2'), await client.lcsLen('1', '2'),
0 0
); );
}, GLOBAL.SERVERS.OPEN); }, {
client: GLOBAL.SERVERS.OPEN,
testUtils.testWithCluster('cluster.lcsLen', async cluster => { cluster: GLOBAL.CLUSTERS.OPEN
assert.equal( });
await cluster.lcsLen('{tag}1', '{tag}2'),
0
);
}, GLOBAL.CLUSTERS.OPEN);
}); });

View File

@@ -1,36 +1,22 @@
import { strict as assert } from 'assert'; import { strict as assert } from 'assert';
import testUtils, { GLOBAL } from '../test-utils'; import testUtils, { GLOBAL } from '../test-utils';
import { transformArguments } from './LINDEX'; import LINDEX from './LINDEX';
describe('LINDEX', () => { describe('LINDEX', () => {
it('transformArguments', () => { it('transformArguments', () => {
assert.deepEqual( assert.deepEqual(
transformArguments('key', 0), LINDEX.transformArguments('key', 0),
['LINDEX', 'key', '0'] ['LINDEX', 'key', '0']
); );
}); });
describe('client.lIndex', () => { testUtils.testAll('lIndex', async client => {
testUtils.testWithClient('null', async client => { assert.equal(
assert.equal( await client.lIndex('key', 0),
await client.lIndex('key', 0), null
null );
); }, {
}, GLOBAL.SERVERS.OPEN); client: GLOBAL.SERVERS.OPEN,
cluster: GLOBAL.CLUSTERS.OPEN
testUtils.testWithClient('with value', async client => { });
const [, lIndexReply] = await Promise.all([
client.lPush('key', 'element'),
client.lIndex('key', 0)
]);
assert.equal(lIndexReply, 'element');
}, GLOBAL.SERVERS.OPEN);
});
testUtils.testWithCluster('cluster.lIndex', async cluster => {
assert.equal(
await cluster.lIndex('key', 0),
null
);
}, GLOBAL.CLUSTERS.OPEN);
}); });

View File

@@ -1,26 +1,22 @@
import { strict as assert } from 'assert'; import { strict as assert } from 'assert';
import testUtils, { GLOBAL } from '../test-utils'; import testUtils, { GLOBAL } from '../test-utils';
import { transformArguments } from './LINSERT'; import LINSERT from './LINSERT';
describe('LINSERT', () => { describe('LINSERT', () => {
it('transformArguments', () => { it('transformArguments', () => {
assert.deepEqual( assert.deepEqual(
transformArguments('key', 'BEFORE', 'pivot', 'element'), LINSERT.transformArguments('key', 'BEFORE', 'pivot', 'element'),
['LINSERT', 'key', 'BEFORE', 'pivot', 'element'] ['LINSERT', 'key', 'BEFORE', 'pivot', 'element']
); );
}); });
testUtils.testWithClient('client.lInsert', async client => { testUtils.testAll('lInsert', async client => {
assert.equal( assert.equal(
await client.lInsert('key', 'BEFORE', 'pivot', 'element'), await client.lInsert('key', 'BEFORE', 'pivot', 'element'),
0 0
); );
}, GLOBAL.SERVERS.OPEN); }, {
client: GLOBAL.SERVERS.OPEN,
testUtils.testWithCluster('cluster.lInsert', async cluster => { cluster: GLOBAL.CLUSTERS.OPEN
assert.equal( });
await cluster.lInsert('key', 'BEFORE', 'pivot', 'element'),
0
);
}, GLOBAL.CLUSTERS.OPEN);
}); });

View File

@@ -14,7 +14,7 @@ describe('LMOVE', () => {
testUtils.testAll('lMove', async client => { testUtils.testAll('lMove', async client => {
assert.equal( assert.equal(
await client.lMove('source', 'destination', 'LEFT', 'RIGHT'), await client.lMove('{tag}source', '{tag}destination', 'LEFT', 'RIGHT'),
null null
); );
}, { }, {

View File

@@ -23,7 +23,7 @@ describe('LMPOP', () => {
}); });
}); });
testUtils.testAll('client.lmPop', async client => { testUtils.testAll('lmPop', async client => {
assert.deepEqual( assert.deepEqual(
await client.lmPop('key', 'RIGHT'), await client.lmPop('key', 'RIGHT'),
null null

View File

@@ -11,6 +11,7 @@ describe('LSET', () => {
}); });
testUtils.testAll('lSet', async client => { testUtils.testAll('lSet', async client => {
await client.lPush('key', 'element');
assert.equal( assert.equal(
await client.lSet('key', 0, 'element'), await client.lSet('key', 0, 'element'),
'OK' 'OK'

View File

@@ -1,6 +1,7 @@
import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; import { RedisArgument, SimpleStringReply, Command } from '../RESP/types';
export default { export default {
FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: true, IS_READ_ONLY: true,
transformArguments(message?: RedisArgument) { transformArguments(message?: RedisArgument) {
const args: Array<RedisArgument> = ['PING']; const args: Array<RedisArgument> = ['PING'];

View File

@@ -1,6 +1,7 @@
import { NumberReply, Command } from '../RESP/types'; import { NumberReply, Command } from '../RESP/types';
export default { export default {
FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: true, IS_READ_ONLY: true,
transformArguments() { transformArguments() {
return ['RANDOMKEY']; return ['RANDOMKEY'];

View File

@@ -1,6 +1,7 @@
import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; import { RedisArgument, SimpleStringReply, Command } from '../RESP/types';
export default { export default {
FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: true, IS_READ_ONLY: true,
transformArguments(key: RedisArgument, newKey: RedisArgument) { transformArguments(key: RedisArgument, newKey: RedisArgument) {
return ['RENAME', key, newKey]; return ['RENAME', key, newKey];

View File

@@ -1,6 +1,7 @@
import { RedisArgument, NumberReply, Command } from '../RESP/types'; import { RedisArgument, NumberReply, Command } from '../RESP/types';
export default { export default {
FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: true, IS_READ_ONLY: true,
transformArguments(key: RedisArgument, newKey: RedisArgument) { transformArguments(key: RedisArgument, newKey: RedisArgument) {
return ['RENAMENX', key, newKey]; return ['RENAMENX', key, newKey];

View File

@@ -28,6 +28,7 @@ export interface ScanOptions extends ScanCommonOptions {
} }
export default { export default {
FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: true, IS_READ_ONLY: true,
transformArguments(cursor: number, options?: ScanOptions) { transformArguments(cursor: number, options?: ScanOptions) {
const args = pushScanArguments(['SCAN'], cursor, options); const args = pushScanArguments(['SCAN'], cursor, options);

View File

@@ -1,28 +1,22 @@
// import { strict as assert } from 'assert'; import { strict as assert } from 'assert';
// import testUtils, { GLOBAL } from '../test-utils'; import testUtils, { GLOBAL } from '../test-utils';
// import { transformArguments } from './SPOP'; import SPOP from './SPOP';
// describe('SPOP', () => { describe('SPOP', () => {
// describe('transformArguments', () => { it('transformArguments', () => {
// it('simple', () => { assert.deepEqual(
// assert.deepEqual( SPOP.transformArguments('key'),
// transformArguments('key'), ['SPOP', 'key']
// ['SPOP', 'key'] );
// ); });
// });
// it('with count', () => { testUtils.testAll('sPop', async client => {
// assert.deepEqual( assert.equal(
// transformArguments('key', 2), await client.sPop('key'),
// ['SPOP', 'key', '2'] null
// ); );
// }); }, {
// }); client: GLOBAL.SERVERS.OPEN,
cluster: GLOBAL.CLUSTERS.OPEN
// testUtils.testWithClient('client.sPop', async client => { });
// assert.equal( });
// await client.sPop('key'),
// null
// );
// }, GLOBAL.SERVERS.OPEN);
// });

View File

@@ -1,18 +1,10 @@
// import { RedisCommandArgument, RedisCommandArguments } from '.'; import { RedisArgument, BlobStringReply, NullReply, Command } from '../RESP/types';
// export const FIRST_KEY_INDEX = 1; export default {
FIRST_KEY_INDEX: 1,
// export function transformArguments( IS_READ_ONLY: false,
// key: RedisCommandArgument, transformArguments(key: RedisArgument) {
// count?: number return ['SPOP', key];
// ): RedisCommandArguments { },
// const args = ['SPOP', key]; transformReply: undefined as unknown as () => BlobStringReply | NullReply
} as const satisfies Command;
// if (typeof count === 'number') {
// args.push(count.toString());
// }
// return args;
// }
// export declare function transformReply(): Array<RedisCommandArgument>;

View File

@@ -0,0 +1,22 @@
import { strict as assert } from 'assert';
import testUtils, { GLOBAL } from '../test-utils';
import SPOP_COUNT from './SPOP_COUNT';
describe('SPOP_COUNT', () => {
it('transformArguments', () => {
assert.deepEqual(
SPOP_COUNT.transformArguments('key', 1),
['SPOP', 'key', '1']
);
});
testUtils.testAll('sPopCount', async client => {
assert.deepEqual(
await client.sPopCount('key', 1),
[]
);
}, {
client: GLOBAL.SERVERS.OPEN,
cluster: GLOBAL.CLUSTERS.OPEN
});
});

View File

@@ -0,0 +1,10 @@
import { RedisArgument, BlobStringReply, NullReply, Command } from '../RESP/types';
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: false,
transformArguments(key: RedisArgument, count: number) {
return ['SPOP', key, count.toString()];
},
transformReply: undefined as unknown as () => BlobStringReply | NullReply
} as const satisfies Command;

View File

@@ -19,7 +19,7 @@ describe('SREM', () => {
}); });
}); });
testUtils.testAll('client.sRem', async client => { testUtils.testAll('sRem', async client => {
assert.equal( assert.equal(
await client.sRem('key', 'member'), await client.sRem('key', 'member'),
0 0

View File

@@ -46,6 +46,7 @@ import DECRBY from './DECRBY';
import DEL from './DEL'; import DEL from './DEL';
import DUMP from './DUMP'; import DUMP from './DUMP';
import GET from './GET'; import GET from './GET';
import GETBIT from './GETBIT';
import GETDEL from './GETDEL'; import GETDEL from './GETDEL';
import GETEX from './GETEX'; import GETEX from './GETEX';
import GETRANGE from './GETRANGE'; import GETRANGE from './GETRANGE';
@@ -141,6 +142,8 @@ import SMISMEMBER from './SMISMEMBER';
import SORT_RO from './SORT_RO'; import SORT_RO from './SORT_RO';
import SORT_STORE from './SORT_STORE'; import SORT_STORE from './SORT_STORE';
import SORT from './SORT'; import SORT from './SORT';
import SPOP_COUNT from './SPOP_COUNT';
import SPOP from './SPOP';
import SPUBLISH from './SPUBLISH'; import SPUBLISH from './SPUBLISH';
import SRANDMEMBER_COUNT from './SRANDMEMBER_COUNT'; import SRANDMEMBER_COUNT from './SRANDMEMBER_COUNT';
import SRANDMEMBER from './SRANDMEMBER'; import SRANDMEMBER from './SRANDMEMBER';
@@ -289,6 +292,8 @@ export default {
dump: DUMP, dump: DUMP,
GET, GET,
get: GET, get: GET,
GETBIT,
getBit: GETBIT,
GETDEL, GETDEL,
getDel: GETDEL, getDel: GETDEL,
GETEX, GETEX,
@@ -328,7 +333,7 @@ export default {
HSET, HSET,
hSet: HSET, hSet: HSET,
HSETNX, HSETNX,
hSetNx: HSETNX, hSetNX: HSETNX,
HSTRLEN, HSTRLEN,
hStrLen: HSTRLEN, hStrLen: HSTRLEN,
HVALS, HVALS,
@@ -480,6 +485,10 @@ export default {
sortStore: SORT_STORE, sortStore: SORT_STORE,
SORT, SORT,
sort: SORT, sort: SORT,
SPOP_COUNT,
sPopCount: SPOP_COUNT,
SPOP,
sPop: SPOP,
SPUBLISH, SPUBLISH,
sPublish: SPUBLISH, sPublish: SPUBLISH,
SRANDMEMBER_COUNT, SRANDMEMBER_COUNT,