You've already forked node-redis
mirror of
https://github.com/redis/node-redis.git
synced 2025-08-17 19:41:06 +03:00
add support for all set commands (including sScanIterator)
This commit is contained in:
@@ -323,4 +323,23 @@ describe('Client', () => {
|
||||
keys.sort()
|
||||
);
|
||||
});
|
||||
|
||||
itWithClient(TestRedisServers.OPEN, 'sScanIterator', async client => {
|
||||
const keys = [];
|
||||
for (let i = 0; i < 100; i++) {
|
||||
keys.push(i.toString());
|
||||
}
|
||||
|
||||
await client.sAdd('key', keys);
|
||||
|
||||
const set = new Set();
|
||||
for await (const key of client.sScanIterator('key')) {
|
||||
set.add(key);
|
||||
}
|
||||
|
||||
assert.deepEqual(
|
||||
[...set].sort(),
|
||||
keys.sort()
|
||||
);
|
||||
});
|
||||
});
|
@@ -6,7 +6,8 @@ import RedisMultiCommand, { MultiQueuedCommand, RedisMultiCommandType } from './
|
||||
import EventEmitter from 'events';
|
||||
import { CommandOptions, commandOptions, isCommandOptions } from './command-options';
|
||||
import { RedisLuaScript, RedisLuaScripts } from './lua-script';
|
||||
import { ScanOptions } from './commands/SCAN';
|
||||
import { ScanOptions } from './commands/generic-transformers';
|
||||
import { ScanCommandOptions } from './commands/SCAN';
|
||||
|
||||
export interface RedisClientOptions<M = RedisModules, S = RedisLuaScripts> {
|
||||
socket?: RedisSocketOptions;
|
||||
@@ -348,7 +349,7 @@ export default class RedisClient<M extends RedisModules = RedisModules, S extend
|
||||
return new this.#Multi();
|
||||
}
|
||||
|
||||
async* scanIterator(options?: ScanOptions): AsyncIterable<string> {
|
||||
async* scanIterator(options?: ScanCommandOptions): AsyncIterable<string> {
|
||||
let cursor = 0;
|
||||
do {
|
||||
const reply = await (this as any).scan(cursor, options);
|
||||
@@ -359,6 +360,17 @@ export default class RedisClient<M extends RedisModules = RedisModules, S extend
|
||||
} while (cursor !== 0)
|
||||
}
|
||||
|
||||
async* sScanIterator(key: string, options?: ScanOptions): AsyncIterable<string> {
|
||||
let cursor = 0;
|
||||
do {
|
||||
const reply = await (this as any).sScan(key, cursor, options);
|
||||
cursor = reply.cursor;
|
||||
for (const key of reply.keys) {
|
||||
yield key;
|
||||
}
|
||||
} while (cursor !== 0)
|
||||
}
|
||||
|
||||
disconnect(): Promise<void> {
|
||||
this.#queue.flushAll(new Error('Disconnecting'));
|
||||
return this.#socket.disconnect();
|
||||
|
28
lib/commands/SADD.spec.ts
Normal file
28
lib/commands/SADD.spec.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import { TestRedisServers, itWithClient } from '../test-utils';
|
||||
import { transformArguments } from './SADD';
|
||||
|
||||
describe('SADD', () => {
|
||||
describe('transformArguments', () => {
|
||||
it('string', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key', 'member'),
|
||||
['SADD', 'key', 'member']
|
||||
);
|
||||
});
|
||||
|
||||
it('array', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key', ['1', '2']),
|
||||
['SADD', 'key', '1', '2']
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
itWithClient(TestRedisServers.OPEN, 'client.sAdd', async client => {
|
||||
assert.equal(
|
||||
await client.sAdd('key', 'member'),
|
||||
1
|
||||
);
|
||||
});
|
||||
});
|
17
lib/commands/SADD.ts
Normal file
17
lib/commands/SADD.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { transformReplyNumber } from './generic-transformers';
|
||||
|
||||
export const FIRST_KEY_INDEX = 1;
|
||||
|
||||
export function transformArguments(key: string, members: string | Array<string>): Array<string> {
|
||||
const args = ['SADD', key];
|
||||
|
||||
if (typeof members === 'string') {
|
||||
args.push(members);
|
||||
} else {
|
||||
args.push(...members);
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
export const transformReply = transformReplyNumber;
|
@@ -1,21 +1,16 @@
|
||||
import { ScanOptions, transformScanArguments, transformScanReply } from './generic-transformers';
|
||||
|
||||
export const IS_READ_ONLY = true;
|
||||
|
||||
export interface ScanOptions {
|
||||
MATCH?: string;
|
||||
COUNT?: number;
|
||||
export interface ScanCommandOptions extends ScanOptions {
|
||||
TYPE?: string;
|
||||
}
|
||||
|
||||
export function transformArguments(cursor: number, options?: ScanOptions): Array<string> {
|
||||
const args = ['SCAN', cursor.toString()];
|
||||
|
||||
if (options?.MATCH) {
|
||||
args.push('MATCH', options.MATCH);
|
||||
}
|
||||
|
||||
if (options?.COUNT) {
|
||||
args.push('COUNT', options.COUNT.toString());
|
||||
}
|
||||
export function transformArguments(cursor: number, options?: ScanCommandOptions): Array<string> {
|
||||
const args = [
|
||||
'SCAN',
|
||||
...transformScanArguments(cursor, options)
|
||||
];
|
||||
|
||||
if (options?.TYPE) {
|
||||
args.push('TYPE', options.TYPE);
|
||||
@@ -24,14 +19,4 @@ export function transformArguments(cursor: number, options?: ScanOptions): Array
|
||||
return args;
|
||||
}
|
||||
|
||||
interface ScanReply {
|
||||
cursor: number;
|
||||
keys: Array<string>
|
||||
}
|
||||
|
||||
export function transformReply(reply: [string, Array<string>]): ScanReply {
|
||||
return {
|
||||
cursor: Number(reply[0]),
|
||||
keys: reply[1]
|
||||
};
|
||||
}
|
||||
export const transformReply = transformScanReply;
|
||||
|
19
lib/commands/SCARD.spec.ts
Normal file
19
lib/commands/SCARD.spec.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import { TestRedisServers, itWithClient } from '../test-utils';
|
||||
import { transformArguments } from './SCARD';
|
||||
|
||||
describe('SCARD', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key'),
|
||||
['SCARD', 'key']
|
||||
);
|
||||
});
|
||||
|
||||
itWithClient(TestRedisServers.OPEN, 'client.sCard', async client => {
|
||||
assert.equal(
|
||||
await client.sCard('key'),
|
||||
0
|
||||
);
|
||||
});
|
||||
});
|
9
lib/commands/SCARD.ts
Normal file
9
lib/commands/SCARD.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { transformReplyNumber } from './generic-transformers';
|
||||
|
||||
export const FIRST_KEY_INDEX = 1;
|
||||
|
||||
export function transformArguments(key: string): Array<string> {
|
||||
return ['SCARD', key];
|
||||
}
|
||||
|
||||
export const transformReply = transformReplyNumber;
|
28
lib/commands/SDIFF.spec.ts
Normal file
28
lib/commands/SDIFF.spec.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import { TestRedisServers, itWithClient } from '../test-utils';
|
||||
import { transformArguments } from './SDIFF';
|
||||
|
||||
describe('SDIFF', () => {
|
||||
describe('transformArguments', () => {
|
||||
it('string', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key'),
|
||||
['SDIFF', 'key']
|
||||
);
|
||||
});
|
||||
|
||||
it('array', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments(['1', '2']),
|
||||
['SDIFF', '1', '2']
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
itWithClient(TestRedisServers.OPEN, 'client.sDiff', async client => {
|
||||
assert.deepEqual(
|
||||
await client.sDiff('key'),
|
||||
[]
|
||||
);
|
||||
});
|
||||
});
|
17
lib/commands/SDIFF.ts
Normal file
17
lib/commands/SDIFF.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { transformReplyStringArray } from './generic-transformers';
|
||||
|
||||
export const FIRST_KEY_INDEX = 1;
|
||||
|
||||
export function transformArguments(keys: string | Array<string>): Array<string> {
|
||||
const args = ['SDIFF'];
|
||||
|
||||
if (typeof keys === 'string') {
|
||||
args.push(keys);
|
||||
} else {
|
||||
args.push(...keys);
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
export const transformReply = transformReplyStringArray;
|
28
lib/commands/SDIFFSTORE.spec.ts
Normal file
28
lib/commands/SDIFFSTORE.spec.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import { TestRedisServers, itWithClient } from '../test-utils';
|
||||
import { transformArguments } from './SDIFFSTORE';
|
||||
|
||||
describe('SDIFFSTORE', () => {
|
||||
describe('transformArguments', () => {
|
||||
it('string', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('destination', 'key'),
|
||||
['SDIFFSTORE', 'destination', 'key']
|
||||
);
|
||||
});
|
||||
|
||||
it('array', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('destination', ['1', '2']),
|
||||
['SDIFFSTORE', 'destination', '1', '2']
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
itWithClient(TestRedisServers.OPEN, 'client.sDiffStore', async client => {
|
||||
assert.equal(
|
||||
await client.sDiffStore('destination', 'key'),
|
||||
0
|
||||
);
|
||||
});
|
||||
});
|
17
lib/commands/SDIFFSTORE.ts
Normal file
17
lib/commands/SDIFFSTORE.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { transformReplyNumber } from './generic-transformers';
|
||||
|
||||
export const FIRST_KEY_INDEX = 1;
|
||||
|
||||
export function transformArguments(destination: string, keys: string | Array<string>): Array<string> {
|
||||
const args = ['SDIFFSTORE', destination];
|
||||
|
||||
if (typeof keys === 'string') {
|
||||
args.push(keys);
|
||||
} else {
|
||||
args.push(...keys);
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
export const transformReply = transformReplyNumber;
|
28
lib/commands/SINTER.spec.ts
Normal file
28
lib/commands/SINTER.spec.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import { TestRedisServers, itWithClient } from '../test-utils';
|
||||
import { transformArguments } from './SINTER';
|
||||
|
||||
describe('SINTER', () => {
|
||||
describe('transformArguments', () => {
|
||||
it('string', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key'),
|
||||
['SINTER', 'key']
|
||||
);
|
||||
});
|
||||
|
||||
it('array', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments(['1', '2']),
|
||||
['SINTER', '1', '2']
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
itWithClient(TestRedisServers.OPEN, 'client.sInter', async client => {
|
||||
assert.deepEqual(
|
||||
await client.sInter('key'),
|
||||
[]
|
||||
);
|
||||
});
|
||||
});
|
17
lib/commands/SINTER.ts
Normal file
17
lib/commands/SINTER.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { transformReplyStringArray } from './generic-transformers';
|
||||
|
||||
export const FIRST_KEY_INDEX = 1;
|
||||
|
||||
export function transformArguments(keys: string | Array<string>): Array<string> {
|
||||
const args = ['SINTER'];
|
||||
|
||||
if (typeof keys === 'string') {
|
||||
args.push(keys);
|
||||
} else {
|
||||
args.push(...keys);
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
export const transformReply = transformReplyStringArray;
|
28
lib/commands/SINTERSTORE.spec.ts
Normal file
28
lib/commands/SINTERSTORE.spec.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import { TestRedisServers, itWithClient } from '../test-utils';
|
||||
import { transformArguments } from './SINTERSTORE';
|
||||
|
||||
describe('SINTERSTORE', () => {
|
||||
describe('transformArguments', () => {
|
||||
it('string', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('destination', 'key'),
|
||||
['SINTERSTORE', 'destination', 'key']
|
||||
);
|
||||
});
|
||||
|
||||
it('array', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('destination', ['1', '2']),
|
||||
['SINTERSTORE', 'destination', '1', '2']
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
itWithClient(TestRedisServers.OPEN, 'client.sInterStore', async client => {
|
||||
assert.equal(
|
||||
await client.sInterStore('destination', 'key'),
|
||||
0
|
||||
);
|
||||
});
|
||||
});
|
17
lib/commands/SINTERSTORE.ts
Normal file
17
lib/commands/SINTERSTORE.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { transformReplyStringArray } from './generic-transformers';
|
||||
|
||||
export const FIRST_KEY_INDEX = 1;
|
||||
|
||||
export function transformArguments(destination: string, keys: string | Array<string>): Array<string> {
|
||||
const args = ['SINTERSTORE', destination];
|
||||
|
||||
if (typeof keys === 'string') {
|
||||
args.push(keys);
|
||||
} else {
|
||||
args.push(...keys);
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
export const transformReply = transformReplyStringArray;
|
19
lib/commands/SISMEMBER.spec.ts
Normal file
19
lib/commands/SISMEMBER.spec.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import { TestRedisServers, itWithClient } from '../test-utils';
|
||||
import { transformArguments } from './SISMEMBER';
|
||||
|
||||
describe('SISMEMBER', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key', 'member'),
|
||||
['SISMEMBER', 'key', 'member']
|
||||
);
|
||||
});
|
||||
|
||||
itWithClient(TestRedisServers.OPEN, 'client.sIsMember', async client => {
|
||||
assert.equal(
|
||||
await client.sIsMember('key', 'member'),
|
||||
false
|
||||
);
|
||||
});
|
||||
});
|
9
lib/commands/SISMEMBER.ts
Normal file
9
lib/commands/SISMEMBER.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { transformReplyBoolean, transformReplyNumber } from './generic-transformers';
|
||||
|
||||
export const FIRST_KEY_INDEX = 1;
|
||||
|
||||
export function transformArguments(key: string, member: string): Array<string> {
|
||||
return ['SISMEMBER', key, member];
|
||||
}
|
||||
|
||||
export const transformReply = transformReplyBoolean;
|
19
lib/commands/SMEMBERS.spec.ts
Normal file
19
lib/commands/SMEMBERS.spec.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import { TestRedisServers, itWithClient } from '../test-utils';
|
||||
import { transformArguments } from './SMEMBERS';
|
||||
|
||||
describe('SMEMBERS', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key'),
|
||||
['SMEMBERS', 'key']
|
||||
);
|
||||
});
|
||||
|
||||
itWithClient(TestRedisServers.OPEN, 'client.sMembers', async client => {
|
||||
assert.deepEqual(
|
||||
await client.sMembers('key'),
|
||||
[]
|
||||
);
|
||||
});
|
||||
});
|
9
lib/commands/SMEMBERS.ts
Normal file
9
lib/commands/SMEMBERS.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { transformReplyNumber, transformReplyStringArray } from './generic-transformers';
|
||||
|
||||
export const FIRST_KEY_INDEX = 1;
|
||||
|
||||
export function transformArguments(key: string): Array<string> {
|
||||
return ['SMEMBERS', key];
|
||||
}
|
||||
|
||||
export const transformReply = transformReplyStringArray;
|
19
lib/commands/SMISMEMBER.spec.ts
Normal file
19
lib/commands/SMISMEMBER.spec.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import { TestRedisServers, itWithClient } from '../test-utils';
|
||||
import { transformArguments } from './SMISMEMBER';
|
||||
|
||||
describe('SMISMEMBER', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key', ['1', '2']),
|
||||
['SMISMEMBER', 'key', '1', '2']
|
||||
);
|
||||
});
|
||||
|
||||
itWithClient(TestRedisServers.OPEN, 'client.smIsMember', async client => {
|
||||
assert.deepEqual(
|
||||
await client.smIsMember('key', ['1', '2']),
|
||||
[false, false]
|
||||
);
|
||||
});
|
||||
});
|
9
lib/commands/SMISMEMBER.ts
Normal file
9
lib/commands/SMISMEMBER.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { transformReplyBooleanArray } from './generic-transformers';
|
||||
|
||||
export const FIRST_KEY_INDEX = 1;
|
||||
|
||||
export function transformArguments(key: string, members: Array<string>): Array<string> {
|
||||
return ['SMISMEMBER', key, ...members];
|
||||
}
|
||||
|
||||
export const transformReply = transformReplyBooleanArray;
|
19
lib/commands/SMOVE.spec.ts
Normal file
19
lib/commands/SMOVE.spec.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import { TestRedisServers, itWithClient } from '../test-utils';
|
||||
import { transformArguments } from './SMOVE';
|
||||
|
||||
describe('SMOVE', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('source', 'destination', 'member'),
|
||||
['SMOVE', 'source', 'destination', 'member']
|
||||
);
|
||||
});
|
||||
|
||||
itWithClient(TestRedisServers.OPEN, 'client.sMove', async client => {
|
||||
assert.equal(
|
||||
await client.sMove('source', 'destination', 'member'),
|
||||
false
|
||||
);
|
||||
});
|
||||
});
|
9
lib/commands/SMOVE.ts
Normal file
9
lib/commands/SMOVE.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { transformReplyBoolean } from './generic-transformers';
|
||||
|
||||
export const FIRST_KEY_INDEX = 1;
|
||||
|
||||
export function transformArguments(source: string, destination: string, member: string): Array<string> {
|
||||
return ['SMOVE', source, destination, member];
|
||||
}
|
||||
|
||||
export const transformReply = transformReplyBoolean;
|
28
lib/commands/SPOP.spec.ts
Normal file
28
lib/commands/SPOP.spec.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import { TestRedisServers, itWithClient } from '../test-utils';
|
||||
import { transformArguments } from './SPOP';
|
||||
|
||||
describe('SPOP', () => {
|
||||
describe('transformArguments', () => {
|
||||
it('simple', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key'),
|
||||
['SPOP', 'key']
|
||||
);
|
||||
});
|
||||
|
||||
it('with count', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key', 2),
|
||||
['SPOP', 'key', '2']
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
itWithClient(TestRedisServers.OPEN, 'client.sPop', async client => {
|
||||
assert.equal(
|
||||
await client.sPop('key'),
|
||||
null
|
||||
);
|
||||
});
|
||||
});
|
15
lib/commands/SPOP.ts
Normal file
15
lib/commands/SPOP.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { transformReplyStringArray } from './generic-transformers';
|
||||
|
||||
export const FIRST_KEY_INDEX = 1;
|
||||
|
||||
export function transformArguments(key: string, count?: number): Array<string> {
|
||||
const args = ['SPOP', key];
|
||||
|
||||
if (typeof count === 'number') {
|
||||
args.push(count.toString());
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
export const transformReply = transformReplyStringArray;
|
28
lib/commands/SRANDMEMBER.spec.ts
Normal file
28
lib/commands/SRANDMEMBER.spec.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import { TestRedisServers, itWithClient } from '../test-utils';
|
||||
import { transformArguments } from './SRANDMEMBER';
|
||||
|
||||
describe('SRANDMEMBER', () => {
|
||||
describe('transformArguments', () => {
|
||||
it('simple', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key'),
|
||||
['SRANDMEMBER', 'key']
|
||||
);
|
||||
});
|
||||
|
||||
it('with count', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key', 2),
|
||||
['SRANDMEMBER', 'key', '2']
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
itWithClient(TestRedisServers.OPEN, 'client.sRandMember', async client => {
|
||||
assert.equal(
|
||||
await client.sRandMember('key'),
|
||||
null
|
||||
);
|
||||
});
|
||||
});
|
16
lib/commands/SRANDMEMBER.ts
Normal file
16
lib/commands/SRANDMEMBER.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { transformReplyStringArray } from './generic-transformers';
|
||||
|
||||
export const FIRST_KEY_INDEX = 1;
|
||||
|
||||
export function transformArguments(key: string, count?: number): Array<string> {
|
||||
const args = ['SRANDMEMBER', key];
|
||||
|
||||
if (typeof count === 'number') {
|
||||
args.push(count.toString());
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
// TODO: without `count` it'll return "bulk string" and not "array"
|
||||
export const transformReply = transformReplyStringArray;
|
28
lib/commands/SREM.spec.ts
Normal file
28
lib/commands/SREM.spec.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import { TestRedisServers, itWithClient } from '../test-utils';
|
||||
import { transformArguments } from './SREM';
|
||||
|
||||
describe('SREM', () => {
|
||||
describe('transformArguments', () => {
|
||||
it('string', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key', 'member'),
|
||||
['SREM', 'key', 'member']
|
||||
);
|
||||
});
|
||||
|
||||
it('array', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key', ['1', '2']),
|
||||
['SREM', 'key', '1', '2']
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
itWithClient(TestRedisServers.OPEN, 'client.sRem', async client => {
|
||||
assert.equal(
|
||||
await client.sRem('key', 'member'),
|
||||
0
|
||||
);
|
||||
});
|
||||
});
|
17
lib/commands/SREM.ts
Normal file
17
lib/commands/SREM.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { transformReplyNumber } from './generic-transformers';
|
||||
|
||||
export const FIRST_KEY_INDEX = 1;
|
||||
|
||||
export function transformArguments(key: string, members: string | Array<string>): Array<string> {
|
||||
const args = ['SREM', key];
|
||||
|
||||
if (typeof members === 'string') {
|
||||
args.push(members);
|
||||
} else {
|
||||
args.push(...members);
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
export const transformReply = transformReplyNumber;
|
13
lib/commands/SSCAN.ts
Normal file
13
lib/commands/SSCAN.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { ScanOptions, transformScanArguments, transformScanReply } from './generic-transformers';
|
||||
|
||||
export const IS_READ_ONLY = true;
|
||||
|
||||
export function transformArguments(key: string, cursor: number, options?: ScanOptions): Array<string> {
|
||||
return [
|
||||
'SSCAN',
|
||||
key,
|
||||
...transformScanArguments(cursor, options)
|
||||
];
|
||||
}
|
||||
|
||||
export const transformReply = transformScanReply;
|
28
lib/commands/SUNION.spec.ts
Normal file
28
lib/commands/SUNION.spec.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import { TestRedisServers, itWithClient } from '../test-utils';
|
||||
import { transformArguments } from './SUNION';
|
||||
|
||||
describe('SUNION', () => {
|
||||
describe('transformArguments', () => {
|
||||
it('string', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key'),
|
||||
['SUNION', 'key']
|
||||
);
|
||||
});
|
||||
|
||||
it('array', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments(['1', '2']),
|
||||
['SUNION', '1', '2']
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
itWithClient(TestRedisServers.OPEN, 'client.sUnion', async client => {
|
||||
assert.deepEqual(
|
||||
await client.sUnion('key'),
|
||||
[]
|
||||
);
|
||||
});
|
||||
});
|
19
lib/commands/SUNION.ts
Normal file
19
lib/commands/SUNION.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { transformReplyStringArray } from './generic-transformers';
|
||||
|
||||
export const FIRST_KEY_INDEX = 1;
|
||||
|
||||
export const IS_READ_ONLY = true;
|
||||
|
||||
export function transformArguments(keys: string | Array<string>): Array<string> {
|
||||
const args = ['SUNION'];
|
||||
|
||||
if (typeof keys === 'string') {
|
||||
args.push(keys);
|
||||
} else {
|
||||
args.push(...keys);
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
export const transformReply = transformReplyStringArray;
|
28
lib/commands/SUNIONSTORE.spec.ts
Normal file
28
lib/commands/SUNIONSTORE.spec.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import { TestRedisServers, itWithClient } from '../test-utils';
|
||||
import { transformArguments } from './SUNIONSTORE';
|
||||
|
||||
describe('SUNIONSTORE', () => {
|
||||
describe('transformArguments', () => {
|
||||
it('string', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('destination', 'key'),
|
||||
['SUNIONSTORE', 'destination', 'key']
|
||||
);
|
||||
});
|
||||
|
||||
it('array', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('destination', ['1', '2']),
|
||||
['SUNIONSTORE', 'destination', '1', '2']
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
itWithClient(TestRedisServers.OPEN, 'client.sUnionStore', async client => {
|
||||
assert.equal(
|
||||
await client.sUnionStore('destination', 'key'),
|
||||
0
|
||||
);
|
||||
});
|
||||
});
|
17
lib/commands/SUNIONSTORE.ts
Normal file
17
lib/commands/SUNIONSTORE.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { transformReplyNumber } from './generic-transformers';
|
||||
|
||||
export const FIRST_KEY_INDEX = 1;
|
||||
|
||||
export function transformArguments(destination: string, keys: string | Array<string>): Array<string> {
|
||||
const args = ['SUNIONSTORE', destination];
|
||||
|
||||
if (typeof keys === 'string') {
|
||||
args.push(keys);
|
||||
} else {
|
||||
args.push(...keys);
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
export const transformReply = transformReplyNumber;
|
@@ -13,3 +13,38 @@ export function transformReplyStringArray(reply: Array<string>): Array<string> {
|
||||
export function transformReplyBoolean(reply: number): boolean {
|
||||
return reply === 1;
|
||||
}
|
||||
|
||||
export function transformReplyBooleanArray(reply: Array<number>): Array<boolean> {
|
||||
return reply.map(transformReplyBoolean);
|
||||
}
|
||||
|
||||
export interface ScanOptions {
|
||||
MATCH?: string;
|
||||
COUNT?: number;
|
||||
}
|
||||
|
||||
export function transformScanArguments(cursor: number, options?: ScanOptions): Array<string> {
|
||||
const args = [cursor.toString()];
|
||||
|
||||
if (options?.MATCH) {
|
||||
args.push('MATCH', options.MATCH);
|
||||
}
|
||||
|
||||
if (options?.COUNT) {
|
||||
args.push('COUNT', options.COUNT.toString());
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
export interface ScanReply {
|
||||
cursor: number;
|
||||
keys: Array<string>
|
||||
}
|
||||
|
||||
export function transformScanReply([cursor, keys]: [string, Array<string>]): ScanReply {
|
||||
return {
|
||||
cursor: Number(cursor),
|
||||
keys
|
||||
};
|
||||
}
|
||||
|
@@ -35,7 +35,23 @@ import * as LPUSH from './LPUSH';
|
||||
import * as PING from './PING';
|
||||
import * as PUBLISH from './PUBLISH';
|
||||
import * as READONLY from './READONLY';
|
||||
import * as SADD from './SADD';
|
||||
import * as SCAN from './SCAN';
|
||||
import * as SCARD from './SCARD';
|
||||
import * as SDIFF from './SDIFF';
|
||||
import * as SDIFFSTORE from './SDIFFSTORE';
|
||||
import * as SINTER from './SINTER';
|
||||
import * as SINTERSTORE from './SINTERSTORE';
|
||||
import * as SISMEMBER from './SISMEMBER';
|
||||
import * as SMEMBERS from './SMEMBERS';
|
||||
import * as SMISMEMBER from './SMISMEMBER';
|
||||
import * as SMOVE from './SMOVE';
|
||||
import * as SPOP from './SPOP';
|
||||
import * as SRANDMEMBER from './SRANDMEMBER';
|
||||
import * as SREM from './SREM';
|
||||
import * as SSCAN from './SSCAN';
|
||||
import * as SUNION from './SUNION';
|
||||
import * as SUNIONSTORE from './SUNIONSTORE';
|
||||
import * as SET from './SET';
|
||||
|
||||
export default {
|
||||
@@ -113,8 +129,40 @@ export default {
|
||||
publish: PUBLISH,
|
||||
READONLY,
|
||||
readOnly: READONLY,
|
||||
SADD,
|
||||
sAdd: SADD,
|
||||
SCAN,
|
||||
scan: SCAN,
|
||||
SCARD,
|
||||
sCard: SCARD,
|
||||
SDIFF,
|
||||
sDiff: SDIFF,
|
||||
SDIFFSTORE,
|
||||
sDiffStore: SDIFFSTORE,
|
||||
SINTER,
|
||||
sInter: SINTER,
|
||||
SINTERSTORE,
|
||||
sInterStore: SINTERSTORE,
|
||||
SISMEMBER,
|
||||
sIsMember: SISMEMBER,
|
||||
SMEMBERS,
|
||||
sMembers: SMEMBERS,
|
||||
SMISMEMBER,
|
||||
smIsMember: SMISMEMBER,
|
||||
SMOVE,
|
||||
sMove: SMOVE,
|
||||
SPOP,
|
||||
sPop: SPOP,
|
||||
SRANDMEMBER,
|
||||
sRandMember: SRANDMEMBER,
|
||||
SREM,
|
||||
sRem: SREM,
|
||||
SSCAN,
|
||||
sScan: SSCAN,
|
||||
SUNION,
|
||||
sUnion: SUNION,
|
||||
SUNIONSTORE,
|
||||
sUnionStore: SUNIONSTORE,
|
||||
SET,
|
||||
set: SET
|
||||
};
|
||||
|
Reference in New Issue
Block a user