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

V5 bringing RESP3, Sentinel and TypeMapping to node-redis

RESP3 Support
   - Some commands responses in RESP3 aren't stable yet and therefore return an "untyped" ReplyUnion.
 
Sentinel

TypeMapping

Correctly types Multi commands

Note: some API changes to be further documented in v4-to-v5.md
This commit is contained in:
Shaya Potter
2024-10-15 17:46:52 +03:00
committed by GitHub
parent 2fc79bdfb3
commit b2d35c5286
1174 changed files with 45931 additions and 36274 deletions

View File

@@ -1,19 +1,19 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../../test-utils';
import { transformArguments } from './ADD';
import ADD from './ADD';
describe('BF ADD', () => {
it('transformArguments', () => {
assert.deepEqual(
transformArguments('key', 'item'),
['BF.ADD', 'key', 'item']
);
});
describe('BF.ADD', () => {
it('transformArguments', () => {
assert.deepEqual(
ADD.transformArguments('key', 'item'),
['BF.ADD', 'key', 'item']
);
});
testUtils.testWithClient('client.bf.add', async client => {
assert.equal(
await client.bf.add('key', 'item'),
true
);
}, GLOBAL.SERVERS.OPEN);
testUtils.testWithClient('client.bf.add', async client => {
assert.equal(
await client.bf.add('key', 'item'),
true
);
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,7 +1,11 @@
export const FIRST_KEY_INDEX = 1;
import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types';
import { transformBooleanReply } from '@redis/client/dist/lib/commands/generic-transformers';
export function transformArguments(key: string, item: string): Array<string> {
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: false,
transformArguments(key: RedisArgument, item: RedisArgument) {
return ['BF.ADD', key, item];
}
export { transformBooleanReply as transformReply } from '@redis/client/dist/lib/commands/generic-transformers';
},
transformReply: transformBooleanReply
} as const satisfies Command;

View File

@@ -1,19 +1,19 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../../test-utils';
import { transformArguments } from './CARD';
import CARD from './CARD';
describe('BF CARD', () => {
it('transformArguments', () => {
assert.deepEqual(
transformArguments('bloom'),
['BF.CARD', 'bloom']
);
});
describe('BF.CARD', () => {
it('transformArguments', () => {
assert.deepEqual(
CARD.transformArguments('bloom'),
['BF.CARD', 'bloom']
);
});
testUtils.testWithClient('client.bf.card', async client => {
assert.equal(
await client.bf.card('key'),
0
);
}, GLOBAL.SERVERS.OPEN);
testUtils.testWithClient('client.bf.card', async client => {
assert.equal(
await client.bf.card('key'),
0
);
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,9 +1,10 @@
export const FIRST_KEY_INDEX = 1;
import { RedisArgument, NumberReply, Command } from '@redis/client/dist/lib/RESP/types';
export const IS_READ_ONLY = true;
export function transformArguments(key: string): Array<string> {
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: true,
transformArguments(key: RedisArgument) {
return ['BF.CARD', key];
}
export declare function transformReply(): number;
},
transformReply: undefined as unknown as () => NumberReply
} as const satisfies Command;

View File

@@ -1,19 +1,19 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../../test-utils';
import { transformArguments } from './EXISTS';
import EXISTS from './EXISTS';
describe('BF EXISTS', () => {
it('transformArguments', () => {
assert.deepEqual(
transformArguments('key', 'item'),
['BF.EXISTS', 'key', 'item']
);
});
describe('BF.EXISTS', () => {
it('transformArguments', () => {
assert.deepEqual(
EXISTS.transformArguments('key', 'item'),
['BF.EXISTS', 'key', 'item']
);
});
testUtils.testWithClient('client.bf.exists', async client => {
assert.equal(
await client.bf.exists('key', 'item'),
false
);
}, GLOBAL.SERVERS.OPEN);
testUtils.testWithClient('client.bf.exists', async client => {
assert.equal(
await client.bf.exists('key', 'item'),
false
);
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,9 +1,11 @@
export const FIRST_KEY_INDEX = 1;
import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types';
import { transformBooleanReply } from '@redis/client/dist/lib/commands/generic-transformers';
export const IS_READ_ONLY = true;
export function transformArguments(key: string, item: string): Array<string> {
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: true,
transformArguments(key: RedisArgument, item: RedisArgument) {
return ['BF.EXISTS', key, item];
}
export { transformBooleanReply as transformReply } from '@redis/client/dist/lib/commands/generic-transformers';
},
transformReply: transformBooleanReply
} as const satisfies Command;

View File

@@ -1,24 +1,26 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../../test-utils';
import { transformArguments } from './INFO';
import INFO from './INFO';
describe('BF INFO', () => {
it('transformArguments', () => {
assert.deepEqual(
transformArguments('bloom'),
['BF.INFO', 'bloom']
);
});
describe('BF.INFO', () => {
it('transformArguments', () => {
assert.deepEqual(
INFO.transformArguments('bloom'),
['BF.INFO', 'bloom']
);
});
testUtils.testWithClient('client.bf.info', async client => {
await client.bf.reserve('key', 0.01, 100);
testUtils.testWithClient('client.bf.info', async client => {
const [, reply] = await Promise.all([
client.bf.reserve('key', 0.01, 100),
client.bf.info('key')
]);
const info = await client.bf.info('key');
assert.equal(typeof info, 'object');
assert.equal(info.capacity, 100);
assert.equal(typeof info.size, 'number');
assert.equal(typeof info.numberOfFilters, 'number');
assert.equal(typeof info.numberOfInsertedItems, 'number');
assert.equal(typeof info.expansionRate, 'number');
}, GLOBAL.SERVERS.OPEN);
assert.equal(typeof reply, 'object');
assert.equal(reply['Capacity'], 100);
assert.equal(typeof reply['Size'], 'number');
assert.equal(typeof reply['Number of filters'], 'number');
assert.equal(typeof reply['Number of items inserted'], 'number');
assert.equal(typeof reply['Expansion rate'], 'number');
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,38 +1,32 @@
export const FIRST_KEY_INDEX = 1;
import { RedisArgument, Command, UnwrapReply, NullReply, NumberReply, TuplesToMapReply, Resp2Reply, SimpleStringReply, TypeMapping } from '@redis/client/dist/lib/RESP/types';
import { transformInfoV2Reply } from '.';
export const IS_READ_ONLY = true;
export type BfInfoReplyMap = TuplesToMapReply<[
[SimpleStringReply<'Capacity'>, NumberReply],
[SimpleStringReply<'Size'>, NumberReply],
[SimpleStringReply<'Number of filters'>, NumberReply],
[SimpleStringReply<'Number of items inserted'>, NumberReply],
[SimpleStringReply<'Expansion rate'>, NullReply | NumberReply]
]>;
export function transformArguments(key: string): Array<string> {
export interface BfInfoReply {
capacity: NumberReply;
size: NumberReply;
numberOfFilters: NumberReply;
numberOfInsertedItems: NumberReply;
expansionRate: NullReply | NumberReply;
}
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: true,
transformArguments(key: RedisArgument) {
return ['BF.INFO', key];
}
export type InfoRawReply = [
_: string,
capacity: number,
_: string,
size: number,
_: string,
numberOfFilters: number,
_: string,
numberOfInsertedItems: number,
_: string,
expansionRate: number,
];
export interface InfoReply {
capacity: number;
size: number;
numberOfFilters: number;
numberOfInsertedItems: number;
expansionRate: number;
}
export function transformReply(reply: InfoRawReply): InfoReply {
return {
capacity: reply[1],
size: reply[3],
numberOfFilters: reply[5],
numberOfInsertedItems: reply[7],
expansionRate: reply[9]
};
}
},
transformReply: {
2: (reply: UnwrapReply<Resp2Reply<BfInfoReplyMap>>, _, typeMapping?: TypeMapping): BfInfoReplyMap => {
return transformInfoV2Reply<BfInfoReplyMap>(reply, typeMapping);
},
3: undefined as unknown as () => BfInfoReplyMap
}
} as const satisfies Command;

View File

@@ -1,69 +1,69 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../../test-utils';
import { transformArguments } from './INSERT';
import INSERT from './INSERT';
describe('BF INSERT', () => {
describe('transformArguments', () => {
it('simple', () => {
assert.deepEqual(
transformArguments('key', 'item'),
['BF.INSERT', 'key', 'ITEMS', 'item']
);
});
it('with CAPACITY', () => {
assert.deepEqual(
transformArguments('key', 'item', { CAPACITY: 100 }),
['BF.INSERT', 'key', 'CAPACITY', '100', 'ITEMS', 'item']
);
});
it('with ERROR', () => {
assert.deepEqual(
transformArguments('key', 'item', { ERROR: 0.01 }),
['BF.INSERT', 'key', 'ERROR', '0.01', 'ITEMS', 'item']
);
});
it('with EXPANSION', () => {
assert.deepEqual(
transformArguments('key', 'item', { EXPANSION: 1 }),
['BF.INSERT', 'key', 'EXPANSION', '1', 'ITEMS', 'item']
);
});
it('with NOCREATE', () => {
assert.deepEqual(
transformArguments('key', 'item', { NOCREATE: true }),
['BF.INSERT', 'key', 'NOCREATE', 'ITEMS', 'item']
);
});
it('with NONSCALING', () => {
assert.deepEqual(
transformArguments('key', 'item', { NONSCALING: true }),
['BF.INSERT', 'key', 'NONSCALING', 'ITEMS', 'item']
);
});
it('with CAPACITY, ERROR, EXPANSION, NOCREATE and NONSCALING', () => {
assert.deepEqual(
transformArguments('key', 'item', {
CAPACITY: 100,
ERROR: 0.01,
EXPANSION: 1,
NOCREATE: true,
NONSCALING: true
}),
['BF.INSERT', 'key', 'CAPACITY', '100', 'ERROR', '0.01', 'EXPANSION', '1', 'NOCREATE', 'NONSCALING', 'ITEMS', 'item']
);
});
describe('BF.INSERT', () => {
describe('transformArguments', () => {
it('simple', () => {
assert.deepEqual(
INSERT.transformArguments('key', 'item'),
['BF.INSERT', 'key', 'ITEMS', 'item']
);
});
testUtils.testWithClient('client.bf.insert', async client => {
assert.deepEqual(
await client.bf.insert('key', 'item'),
[true]
);
}, GLOBAL.SERVERS.OPEN);
it('with CAPACITY', () => {
assert.deepEqual(
INSERT.transformArguments('key', 'item', { CAPACITY: 100 }),
['BF.INSERT', 'key', 'CAPACITY', '100', 'ITEMS', 'item']
);
});
it('with ERROR', () => {
assert.deepEqual(
INSERT.transformArguments('key', 'item', { ERROR: 0.01 }),
['BF.INSERT', 'key', 'ERROR', '0.01', 'ITEMS', 'item']
);
});
it('with EXPANSION', () => {
assert.deepEqual(
INSERT.transformArguments('key', 'item', { EXPANSION: 1 }),
['BF.INSERT', 'key', 'EXPANSION', '1', 'ITEMS', 'item']
);
});
it('with NOCREATE', () => {
assert.deepEqual(
INSERT.transformArguments('key', 'item', { NOCREATE: true }),
['BF.INSERT', 'key', 'NOCREATE', 'ITEMS', 'item']
);
});
it('with NONSCALING', () => {
assert.deepEqual(
INSERT.transformArguments('key', 'item', { NONSCALING: true }),
['BF.INSERT', 'key', 'NONSCALING', 'ITEMS', 'item']
);
});
it('with CAPACITY, ERROR, EXPANSION, NOCREATE and NONSCALING', () => {
assert.deepEqual(
INSERT.transformArguments('key', 'item', {
CAPACITY: 100,
ERROR: 0.01,
EXPANSION: 1,
NOCREATE: true,
NONSCALING: true
}),
['BF.INSERT', 'key', 'CAPACITY', '100', 'ERROR', '0.01', 'EXPANSION', '1', 'NOCREATE', 'NONSCALING', 'ITEMS', 'item']
);
});
});
testUtils.testWithClient('client.bf.insert', async client => {
assert.deepEqual(
await client.bf.insert('key', 'item'),
[true]
);
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,45 +1,47 @@
import { pushVerdictArguments } from '@redis/client/dist/lib/commands/generic-transformers';
import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands';
import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types';
import { RedisVariadicArgument, pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers';
import { transformBooleanArrayReply } from '@redis/client/dist/lib/commands/generic-transformers';
export const FIRST_KEY_INDEX = 1;
interface InsertOptions {
CAPACITY?: number;
ERROR?: number;
EXPANSION?: number;
NOCREATE?: true;
NONSCALING?: true;
export interface BfInsertOptions {
CAPACITY?: number;
ERROR?: number;
EXPANSION?: number;
NOCREATE?: boolean;
NONSCALING?: boolean;
}
export function transformArguments(
key: string,
items: RedisCommandArgument | Array<RedisCommandArgument>,
options?: InsertOptions
): RedisCommandArguments {
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: false,
transformArguments(
key: RedisArgument,
items: RedisVariadicArgument,
options?: BfInsertOptions
) {
const args = ['BF.INSERT', key];
if (options?.CAPACITY) {
args.push('CAPACITY', options.CAPACITY.toString());
if (options?.CAPACITY !== undefined) {
args.push('CAPACITY', options.CAPACITY.toString());
}
if (options?.ERROR) {
args.push('ERROR', options.ERROR.toString());
if (options?.ERROR !== undefined) {
args.push('ERROR', options.ERROR.toString());
}
if (options?.EXPANSION) {
args.push('EXPANSION', options.EXPANSION.toString());
if (options?.EXPANSION !== undefined) {
args.push('EXPANSION', options.EXPANSION.toString());
}
if (options?.NOCREATE) {
args.push('NOCREATE');
args.push('NOCREATE');
}
if (options?.NONSCALING) {
args.push('NONSCALING');
args.push('NONSCALING');
}
args.push('ITEMS');
return pushVerdictArguments(args, items);
}
export { transformBooleanArrayReply as transformReply } from '@redis/client/dist/lib/commands/generic-transformers';
return pushVariadicArguments(args, items);
},
transformReply: transformBooleanArrayReply
} as const satisfies Command;

View File

@@ -1,28 +1,35 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../../test-utils';
import { transformArguments } from './LOADCHUNK';
import LOADCHUNK from './LOADCHUNK';
import { RESP_TYPES } from '@redis/client';
describe('BF LOADCHUNK', () => {
it('transformArguments', () => {
assert.deepEqual(
transformArguments('key', 0, ''),
['BF.LOADCHUNK', 'key', '0', '']
);
});
describe('BF.LOADCHUNK', () => {
it('transformArguments', () => {
assert.deepEqual(
LOADCHUNK.transformArguments('key', 0, ''),
['BF.LOADCHUNK', 'key', '0', '']
);
});
testUtils.testWithClient('client.bf.loadChunk', async client => {
const [, { iterator, chunk }] = await Promise.all([
client.bf.reserve('source', 0.01, 100),
client.bf.scanDump(
client.commandOptions({ returnBuffers: true }),
'source',
0
)
]);
testUtils.testWithClient('client.bf.loadChunk', async client => {
const [, { iterator, chunk }] = await Promise.all([
client.bf.reserve('source', 0.01, 100),
client.bf.scanDump('source', 0)
]);
assert.equal(
await client.bf.loadChunk('destination', iterator, chunk),
'OK'
);
}, GLOBAL.SERVERS.OPEN);
assert.equal(
await client.bf.loadChunk('destination', iterator, chunk),
'OK'
);
}, {
...GLOBAL.SERVERS.OPEN,
clientOptions: {
...GLOBAL.SERVERS.OPEN.clientOptions,
commandOptions: {
typeMapping: {
[RESP_TYPES.BLOB_STRING]: Buffer
}
}
}
});
});

View File

@@ -1,13 +1,10 @@
import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands';
import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types';
export const FIRST_KEY_INDEX = 1;
export function transformArguments(
key: string,
iteretor: number,
chunk: RedisCommandArgument
): RedisCommandArguments {
return ['BF.LOADCHUNK', key, iteretor.toString(), chunk];
}
export declare function transformReply(): 'OK';
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: false,
transformArguments(key: RedisArgument, iterator: number, chunk: RedisArgument) {
return ['BF.LOADCHUNK', key, iterator.toString(), chunk];
},
transformReply: undefined as unknown as () => SimpleStringReply<'OK'>
} as const satisfies Command;

View File

@@ -1,19 +1,19 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../../test-utils';
import { transformArguments } from './MADD';
import MADD from './MADD';
describe('BF MADD', () => {
it('transformArguments', () => {
assert.deepEqual(
transformArguments('key', ['1', '2']),
['BF.MADD', 'key', '1', '2']
);
});
describe('BF.MADD', () => {
it('transformArguments', () => {
assert.deepEqual(
MADD.transformArguments('key', ['1', '2']),
['BF.MADD', 'key', '1', '2']
);
});
testUtils.testWithClient('client.ts.mAdd', async client => {
assert.deepEqual(
await client.bf.mAdd('key', ['1', '2']),
[true, true]
);
}, GLOBAL.SERVERS.OPEN);
testUtils.testWithClient('client.ts.mAdd', async client => {
assert.deepEqual(
await client.bf.mAdd('key', ['1', '2']),
[true, true]
);
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,7 +1,12 @@
export const FIRST_KEY_INDEX = 1;
import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types';
import { RedisVariadicArgument, pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers';
import { transformBooleanArrayReply } from '@redis/client/dist/lib/commands/generic-transformers';
export function transformArguments(key: string, items: Array<string>): Array<string> {
return ['BF.MADD', key, ...items];
}
export { transformBooleanArrayReply as transformReply } from '@redis/client/dist/lib/commands/generic-transformers';
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: false,
transformArguments(key: RedisArgument, items: RedisVariadicArgument) {
return pushVariadicArguments(['BF.MADD', key], items);
},
transformReply: transformBooleanArrayReply
} as const satisfies Command;

View File

@@ -1,19 +1,19 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../../test-utils';
import { transformArguments } from './MEXISTS';
import MEXISTS from './MEXISTS';
describe('BF MEXISTS', () => {
it('transformArguments', () => {
assert.deepEqual(
transformArguments('key', ['1', '2']),
['BF.MEXISTS', 'key', '1', '2']
);
});
describe('BF.MEXISTS', () => {
it('transformArguments', () => {
assert.deepEqual(
MEXISTS.transformArguments('key', ['1', '2']),
['BF.MEXISTS', 'key', '1', '2']
);
});
testUtils.testWithClient('client.bf.mExists', async client => {
assert.deepEqual(
await client.bf.mExists('key', ['1', '2']),
[false, false]
);
}, GLOBAL.SERVERS.OPEN);
testUtils.testWithClient('client.bf.mExists', async client => {
assert.deepEqual(
await client.bf.mExists('key', ['1', '2']),
[false, false]
);
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,9 +1,12 @@
export const FIRST_KEY_INDEX = 1;
import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types';
import { RedisVariadicArgument, pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers';
import { transformBooleanArrayReply } from '@redis/client/dist/lib/commands/generic-transformers';
export const IS_READ_ONLY = true;
export function transformArguments(key: string, items: Array<string>): Array<string> {
return ['BF.MEXISTS', key, ...items];
}
export { transformBooleanArrayReply as transformReply } from '@redis/client/dist/lib/commands/generic-transformers';
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: true,
transformArguments(key: RedisArgument, items: RedisVariadicArgument) {
return pushVariadicArguments(['BF.MEXISTS', key], items);
},
transformReply: transformBooleanArrayReply
} as const satisfies Command;

View File

@@ -1,49 +1,49 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../../test-utils';
import { transformArguments } from './RESERVE';
import RESERVE from './RESERVE';
describe('BF RESERVE', () => {
describe('transformArguments', () => {
it('simple', () => {
assert.deepEqual(
transformArguments('key', 0.01, 100),
['BF.RESERVE', 'key', '0.01', '100']
);
});
it('with EXPANSION', () => {
assert.deepEqual(
transformArguments('key', 0.01, 100, {
EXPANSION: 1
}),
['BF.RESERVE', 'key', '0.01', '100', 'EXPANSION', '1']
);
});
it('with NONSCALING', () => {
assert.deepEqual(
transformArguments('key', 0.01, 100, {
NONSCALING: true
}),
['BF.RESERVE', 'key', '0.01', '100', 'NONSCALING']
);
});
it('with EXPANSION and NONSCALING', () => {
assert.deepEqual(
transformArguments('key', 0.01, 100, {
EXPANSION: 1,
NONSCALING: true
}),
['BF.RESERVE', 'key', '0.01', '100', 'EXPANSION', '1', 'NONSCALING']
);
});
describe('BF.RESERVE', () => {
describe('transformArguments', () => {
it('simple', () => {
assert.deepEqual(
RESERVE.transformArguments('key', 0.01, 100),
['BF.RESERVE', 'key', '0.01', '100']
);
});
testUtils.testWithClient('client.bf.reserve', async client => {
assert.equal(
await client.bf.reserve('bloom', 0.01, 100),
'OK'
);
}, GLOBAL.SERVERS.OPEN);
it('with EXPANSION', () => {
assert.deepEqual(
RESERVE.transformArguments('key', 0.01, 100, {
EXPANSION: 1
}),
['BF.RESERVE', 'key', '0.01', '100', 'EXPANSION', '1']
);
});
it('with NONSCALING', () => {
assert.deepEqual(
RESERVE.transformArguments('key', 0.01, 100, {
NONSCALING: true
}),
['BF.RESERVE', 'key', '0.01', '100', 'NONSCALING']
);
});
it('with EXPANSION and NONSCALING', () => {
assert.deepEqual(
RESERVE.transformArguments('key', 0.01, 100, {
EXPANSION: 1,
NONSCALING: true
}),
['BF.RESERVE', 'key', '0.01', '100', 'EXPANSION', '1', 'NONSCALING']
);
});
});
testUtils.testWithClient('client.bf.reserve', async client => {
assert.equal(
await client.bf.reserve('bloom', 0.01, 100),
'OK'
);
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,16 +1,19 @@
export const FIRST_KEY_INDEX = 1;
import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types';
interface ReserveOptions {
EXPANSION?: number;
NONSCALING?: true;
export interface BfReserveOptions {
EXPANSION?: number;
NONSCALING?: boolean;
}
export function transformArguments(
key: string,
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: true,
transformArguments(
key: RedisArgument,
errorRate: number,
capacity: number,
options?: ReserveOptions
): Array<string> {
options?: BfReserveOptions
) {
const args = ['BF.RESERVE', key, errorRate.toString(), capacity.toString()];
if (options?.EXPANSION) {
@@ -22,6 +25,6 @@ export function transformArguments(
}
return args;
}
export declare function transformReply(): 'OK';
},
transformReply: undefined as unknown as () => SimpleStringReply<'OK'>
} as const satisfies Command;

View File

@@ -1,22 +1,22 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../../test-utils';
import { transformArguments } from './SCANDUMP';
import SCANDUMP from './SCANDUMP';
describe('BF SCANDUMP', () => {
it('transformArguments', () => {
assert.deepEqual(
transformArguments('key', 0),
['BF.SCANDUMP', 'key', '0']
);
});
describe('BF.SCANDUMP', () => {
it('transformArguments', () => {
assert.deepEqual(
SCANDUMP.transformArguments('key', 0),
['BF.SCANDUMP', 'key', '0']
);
});
testUtils.testWithClient('client.bf.scanDump', async client => {
const [, dump] = await Promise.all([
client.bf.reserve('key', 0.01, 100),
client.bf.scanDump('key', 0)
]);
assert.equal(typeof dump, 'object');
assert.equal(typeof dump.iterator, 'number');
assert.equal(typeof dump.chunk, 'string');
}, GLOBAL.SERVERS.OPEN);
testUtils.testWithClient('client.bf.scanDump', async client => {
const [, dump] = await Promise.all([
client.bf.reserve('key', 0.01, 100),
client.bf.scanDump('key', 0)
]);
assert.equal(typeof dump, 'object');
assert.equal(typeof dump.iterator, 'number');
assert.equal(typeof dump.chunk, 'string');
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,24 +1,15 @@
export const FIRST_KEY_INDEX = 1;
import { RedisArgument, TuplesReply, NumberReply, BlobStringReply, UnwrapReply, Command } from '@redis/client/dist/lib/RESP/types';
export const IS_READ_ONLY = true;
export function transformArguments(key: string, iterator: number): Array<string> {
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: true,
transformArguments(key: RedisArgument, iterator: number) {
return ['BF.SCANDUMP', key, iterator.toString()];
}
type ScanDumpRawReply = [
iterator: number,
chunk: string
];
interface ScanDumpReply {
iterator: number;
chunk: string;
}
export function transformReply([iterator, chunk]: ScanDumpRawReply): ScanDumpReply {
},
transformReply(reply: UnwrapReply<TuplesReply<[NumberReply, BlobStringReply]>>) {
return {
iterator,
chunk
iterator: reply[0],
chunk: reply[1]
};
}
}
} as const satisfies Command;

View File

@@ -1,33 +1,64 @@
import * as ADD from './ADD';
import * as CARD from './CARD';
import * as EXISTS from './EXISTS';
import * as INFO from './INFO';
import * as INSERT from './INSERT';
import * as LOADCHUNK from './LOADCHUNK';
import * as MADD from './MADD';
import * as MEXISTS from './MEXISTS';
import * as RESERVE from './RESERVE';
import * as SCANDUMP from './SCANDUMP';
import type { RedisCommands, TypeMapping } from '@redis/client/dist/lib/RESP/types';
import ADD from './ADD';
import CARD from './CARD';
import EXISTS from './EXISTS';
import INFO from './INFO';
import INSERT from './INSERT';
import LOADCHUNK from './LOADCHUNK';
import MADD from './MADD';
import MEXISTS from './MEXISTS';
import RESERVE from './RESERVE';
import SCANDUMP from './SCANDUMP';
import { RESP_TYPES } from '@redis/client';
export default {
ADD,
add: ADD,
CARD,
card: CARD,
EXISTS,
exists: EXISTS,
INFO,
info: INFO,
INSERT,
insert: INSERT,
LOADCHUNK,
loadChunk: LOADCHUNK,
MADD,
mAdd: MADD,
MEXISTS,
mExists: MEXISTS,
RESERVE,
reserve: RESERVE,
SCANDUMP,
scanDump: SCANDUMP
};
ADD,
add: ADD,
CARD,
card: CARD,
EXISTS,
exists: EXISTS,
INFO,
info: INFO,
INSERT,
insert: INSERT,
LOADCHUNK,
loadChunk: LOADCHUNK,
MADD,
mAdd: MADD,
MEXISTS,
mExists: MEXISTS,
RESERVE,
reserve: RESERVE,
SCANDUMP,
scanDump: SCANDUMP
} as const satisfies RedisCommands;
export function transformInfoV2Reply<T>(reply: Array<any>, typeMapping?: TypeMapping): T {
const mapType = typeMapping ? typeMapping[RESP_TYPES.MAP] : undefined;
switch (mapType) {
case Array: {
return reply as unknown as T;
}
case Map: {
const ret = new Map<string, any>();
for (let i = 0; i < reply.length; i += 2) {
ret.set(reply[i].toString(), reply[i + 1]);
}
return ret as unknown as T;
}
default: {
const ret = Object.create(null);
for (let i = 0; i < reply.length; i += 2) {
ret[reply[i].toString()] = reply[i + 1];
}
return ret as unknown as T;
}
}
}

View File

@@ -1,41 +1,42 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../../test-utils';
import { transformArguments } from './INCRBY';
import INCRBY from './INCRBY';
describe('CMS INCRBY', () => {
describe('transformArguments', () => {
it('single item', () => {
assert.deepEqual(
transformArguments('key', {
item: 'item',
incrementBy: 1
}),
['CMS.INCRBY', 'key', 'item', '1']
);
});
it('multiple items', () => {
assert.deepEqual(
transformArguments('key', [{
item: 'a',
incrementBy: 1
}, {
item: 'b',
incrementBy: 2
}]),
['CMS.INCRBY', 'key', 'a', '1', 'b', '2']
);
});
describe('CMS.INCRBY', () => {
describe('transformArguments', () => {
it('single item', () => {
assert.deepEqual(
INCRBY.transformArguments('key', {
item: 'item',
incrementBy: 1
}),
['CMS.INCRBY', 'key', 'item', '1']
);
});
testUtils.testWithClient('client.cms.incrBy', async client => {
await client.cms.initByDim('key', 1000, 5);
assert.deepEqual(
await client.cms.incrBy('key', {
item: 'item',
incrementBy: 1
}),
[1]
);
}, GLOBAL.SERVERS.OPEN);
it('multiple items', () => {
assert.deepEqual(
INCRBY.transformArguments('key', [{
item: 'a',
incrementBy: 1
}, {
item: 'b',
incrementBy: 2
}]),
['CMS.INCRBY', 'key', 'a', '1', 'b', '2']
);
});
});
testUtils.testWithClient('client.cms.incrBy', async client => {
const [, reply] = await Promise.all([
client.cms.initByDim('key', 1000, 5),
client.cms.incrBy('key', {
item: 'item',
incrementBy: 1
})
]);
assert.deepEqual(reply, [1]);
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,29 +1,32 @@
export const FIRST_KEY_INDEX = 1;
import { RedisArgument, ArrayReply, NumberReply, Command } from '@redis/client/dist/lib/RESP/types';
interface IncrByItem {
item: string;
incrementBy: number;
export interface BfIncrByItem {
item: RedisArgument;
incrementBy: number;
}
export function transformArguments(
key: string,
items: IncrByItem | Array<IncrByItem>
): Array<string> {
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: false,
transformArguments(
key: RedisArgument,
items: BfIncrByItem | Array<BfIncrByItem>
) {
const args = ['CMS.INCRBY', key];
if (Array.isArray(items)) {
for (const item of items) {
pushIncrByItem(args, item);
}
for (const item of items) {
pushIncrByItem(args, item);
}
} else {
pushIncrByItem(args, items);
pushIncrByItem(args, items);
}
return args;
}
},
transformReply: undefined as unknown as () => ArrayReply<NumberReply>
} as const satisfies Command;
function pushIncrByItem(args: Array<string>, { item, incrementBy }: IncrByItem): void {
args.push(item, incrementBy.toString());
function pushIncrByItem(args: Array<RedisArgument>, { item, incrementBy }: BfIncrByItem): void {
args.push(item, incrementBy.toString());
}
export declare function transformReply(): Array<number>;

View File

@@ -1,25 +1,28 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../../test-utils';
import { transformArguments } from './INFO';
import INFO from './INFO';
describe('CMS INFO', () => {
it('transformArguments', () => {
assert.deepEqual(
transformArguments('key'),
['CMS.INFO', 'key']
);
});
describe('CMS.INFO', () => {
it('transformArguments', () => {
assert.deepEqual(
INFO.transformArguments('key'),
['CMS.INFO', 'key']
);
});
testUtils.testWithClient('client.cms.info', async client => {
await client.cms.initByDim('key', 1000, 5);
testUtils.testWithClient('client.cms.info', async client => {
const width = 1000,
depth = 5,
[, reply] = await Promise.all([
client.cms.initByDim('key', width, depth),
client.cms.info('key')
]);
assert.deepEqual(
await client.cms.info('key'),
{
width: 1000,
depth: 5,
count: 0
}
);
}, GLOBAL.SERVERS.OPEN);
const expected = Object.create(null);
expected['width'] = width;
expected['depth'] = depth;
expected['count'] = 0;
assert.deepEqual(reply, expected);
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,30 +1,28 @@
export const FIRST_KEY_INDEX = 1;
import { RedisArgument, TuplesToMapReply, NumberReply, UnwrapReply, Resp2Reply, Command, SimpleStringReply, TypeMapping } from '@redis/client/dist/lib/RESP/types';
import { transformInfoV2Reply } from '../bloom';
export const IS_READ_ONLY = true;
export type CmsInfoReplyMap = TuplesToMapReply<[
[SimpleStringReply<'width'>, NumberReply],
[SimpleStringReply<'depth'>, NumberReply],
[SimpleStringReply<'count'>, NumberReply]
]>;
export function transformArguments(key: string): Array<string> {
export interface CmsInfoReply {
width: NumberReply;
depth: NumberReply;
count: NumberReply;
}
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: true,
transformArguments(key: RedisArgument) {
return ['CMS.INFO', key];
}
export type InfoRawReply = [
_: string,
width: number,
_: string,
depth: number,
_: string,
count: number
];
export interface InfoReply {
width: number;
depth: number;
count: number;
}
export function transformReply(reply: InfoRawReply): InfoReply {
return {
width: reply[1],
depth: reply[3],
count: reply[5]
};
}
},
transformReply: {
2: (reply: UnwrapReply<Resp2Reply<CmsInfoReplyMap>>, _, typeMapping?: TypeMapping): CmsInfoReply => {
return transformInfoV2Reply<CmsInfoReply>(reply, typeMapping);
},
3: undefined as unknown as () => CmsInfoReply
}
} as const satisfies Command;

View File

@@ -1,19 +1,19 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../../test-utils';
import { transformArguments } from './INITBYDIM';
import INITBYDIM from './INITBYDIM';
describe('CMS INITBYDIM', () => {
it('transformArguments', () => {
assert.deepEqual(
transformArguments('key', 1000, 5),
['CMS.INITBYDIM', 'key', '1000', '5']
);
});
describe('CMS.INITBYDIM', () => {
it('transformArguments', () => {
assert.deepEqual(
INITBYDIM.transformArguments('key', 1000, 5),
['CMS.INITBYDIM', 'key', '1000', '5']
);
});
testUtils.testWithClient('client.cms.initByDim', async client => {
assert.equal(
await client.cms.initByDim('key', 1000, 5),
'OK'
);
}, GLOBAL.SERVERS.OPEN);
testUtils.testWithClient('client.cms.initByDim', async client => {
assert.equal(
await client.cms.initByDim('key', 1000, 5),
'OK'
);
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,7 +1,10 @@
export const FIRST_KEY_INDEX = 1;
import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types';
export function transformArguments(key: string, width: number, depth: number): Array<string> {
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: false,
transformArguments(key: RedisArgument, width: number, depth: number) {
return ['CMS.INITBYDIM', key, width.toString(), depth.toString()];
}
export declare function transformReply(): 'OK';
},
transformReply: undefined as unknown as () => SimpleStringReply<'OK'>
} as const satisfies Command;

View File

@@ -1,19 +1,19 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../../test-utils';
import { transformArguments } from './INITBYPROB';
import INITBYPROB from './INITBYPROB';
describe('CMS INITBYPROB', () => {
it('transformArguments', () => {
assert.deepEqual(
transformArguments('key', 0.001, 0.01),
['CMS.INITBYPROB', 'key', '0.001', '0.01']
);
});
describe('CMS.INITBYPROB', () => {
it('transformArguments', () => {
assert.deepEqual(
INITBYPROB.transformArguments('key', 0.001, 0.01),
['CMS.INITBYPROB', 'key', '0.001', '0.01']
);
});
testUtils.testWithClient('client.cms.initByProb', async client => {
assert.equal(
await client.cms.initByProb('key', 0.001, 0.01),
'OK'
);
}, GLOBAL.SERVERS.OPEN);
testUtils.testWithClient('client.cms.initByProb', async client => {
assert.equal(
await client.cms.initByProb('key', 0.001, 0.01),
'OK'
);
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,7 +1,10 @@
export const FIRST_KEY_INDEX = 1;
import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types';
export function transformArguments(key: string, error: number, probability: number): Array<string> {
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: false,
transformArguments(key: RedisArgument, error: number, probability: number) {
return ['CMS.INITBYPROB', key, error.toString(), probability.toString()];
}
export declare function transformReply(): 'OK';
},
transformReply: undefined as unknown as () => SimpleStringReply<'OK'>
} as const satisfies Command;

View File

@@ -1,36 +1,34 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../../test-utils';
import { transformArguments } from './MERGE';
import MERGE from './MERGE';
describe('CMS MERGE', () => {
describe('transformArguments', () => {
it('without WEIGHTS', () => {
assert.deepEqual(
transformArguments('dest', ['src']),
['CMS.MERGE', 'dest', '1', 'src']
);
});
it('with WEIGHTS', () => {
assert.deepEqual(
transformArguments('dest', [{
name: 'src',
weight: 1
}]),
['CMS.MERGE', 'dest', '1', 'src', 'WEIGHTS', '1']
);
});
describe('CMS.MERGE', () => {
describe('transformArguments', () => {
it('without WEIGHTS', () => {
assert.deepEqual(
MERGE.transformArguments('destination', ['source']),
['CMS.MERGE', 'destination', '1', 'source']
);
});
testUtils.testWithClient('client.cms.merge', async client => {
await Promise.all([
client.cms.initByDim('src', 1000, 5),
client.cms.initByDim('dest', 1000, 5),
]);
it('with WEIGHTS', () => {
assert.deepEqual(
MERGE.transformArguments('destination', [{
name: 'source',
weight: 1
}]),
['CMS.MERGE', 'destination', '1', 'source', 'WEIGHTS', '1']
);
});
});
assert.equal(
await client.cms.merge('dest', ['src']),
'OK'
);
}, GLOBAL.SERVERS.OPEN);
testUtils.testWithClient('client.cms.merge', async client => {
const [, , reply] = await Promise.all([
client.cms.initByDim('source', 1000, 5),
client.cms.initByDim('destination', 1000, 5),
client.cms.merge('destination', ['source'])
]);
assert.equal(reply, 'OK');
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,37 +1,37 @@
export const FIRST_KEY_INDEX = 1;
import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types';
interface Sketch {
name: string;
weight: number;
interface BfMergeSketch {
name: RedisArgument;
weight: number;
}
type Sketches = Array<string> | Array<Sketch>;
export type BfMergeSketches = Array<RedisArgument> | Array<BfMergeSketch>;
export function transformArguments(dest: string, src: Sketches): Array<string> {
const args = [
'CMS.MERGE',
dest,
src.length.toString()
];
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: false,
transformArguments(
destination: RedisArgument,
source: BfMergeSketches
) {
let args = ['CMS.MERGE', destination, source.length.toString()];
if (isStringSketches(src)) {
args.push(...src);
if (isPlainSketches(source)) {
args = args.concat(source);
} else {
for (const sketch of src) {
args.push(sketch.name);
}
args.push('WEIGHTS');
for (const sketch of src) {
args.push(sketch.weight.toString());
}
const { length } = args;
args[length + source.length] = 'WEIGHTS';
for (let i = 0; i < source.length; i++) {
args[length + i] = source[i].name;
args[length + source.length + i + 1] = source[i].weight.toString();
}
}
return args;
}
},
transformReply: undefined as unknown as () => SimpleStringReply<'OK'>
} as const satisfies Command;
function isStringSketches(src: Sketches): src is Array<string> {
return typeof src[0] === 'string';
function isPlainSketches(src: BfMergeSketches): src is Array<RedisArgument> {
return typeof src[0] === 'string' || src[0] instanceof Buffer;
}
export declare function transformReply(): 'OK';

View File

@@ -1,22 +1,21 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../../test-utils';
import { transformArguments } from './QUERY';
import QUERY from './QUERY';
describe('CMS QUERY', () => {
it('transformArguments', () => {
assert.deepEqual(
transformArguments('key', 'item'),
['CMS.QUERY', 'key', 'item']
);
});
describe('CMS.QUERY', () => {
it('transformArguments', () => {
assert.deepEqual(
QUERY.transformArguments('key', 'item'),
['CMS.QUERY', 'key', 'item']
);
});
testUtils.testWithClient('client.cms.query', async client => {
await client.cms.initByDim('key', 1000, 5);
testUtils.testWithClient('client.cms.query', async client => {
const [, reply] = await Promise.all([
client.cms.initByDim('key', 1000, 5),
client.cms.query('key', 'item')
]);
assert.deepEqual(
await client.cms.query('key', 'item'),
[0]
);
}, GLOBAL.SERVERS.OPEN);
assert.deepEqual(reply, [0]);
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,15 +1,11 @@
import { RedisCommandArguments } from '@redis/client/dist/lib/commands';
import { pushVerdictArguments } from '@redis/client/dist/lib/commands/generic-transformers';
import { ArrayReply, NumberReply, Command, RedisArgument } from '@redis/client/dist/lib/RESP/types';
import { RedisVariadicArgument, pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers';
export const FIRST_KEY_INDEX = 1;
export const IS_READ_ONLY = true;
export function transformArguments(
key: string,
items: string | Array<string>
): RedisCommandArguments {
return pushVerdictArguments(['CMS.QUERY', key], items);
}
export declare function transformReply(): Array<number>;
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: true,
transformArguments(key: RedisArgument, items: RedisVariadicArgument) {
return pushVariadicArguments(['CMS.QUERY', key], items);
},
transformReply: undefined as unknown as () => ArrayReply<NumberReply>
} as const satisfies Command;

View File

@@ -1,21 +1,22 @@
import * as INCRBY from './INCRBY';
import * as INFO from './INFO';
import * as INITBYDIM from './INITBYDIM';
import * as INITBYPROB from './INITBYPROB';
import * as MERGE from './MERGE';
import * as QUERY from './QUERY';
import type { RedisCommands } from '@redis/client/dist/lib/RESP/types';
import INCRBY from './INCRBY';
import INFO from './INFO';
import INITBYDIM from './INITBYDIM';
import INITBYPROB from './INITBYPROB';
import MERGE from './MERGE';
import QUERY from './QUERY';
export default {
INCRBY,
incrBy: INCRBY,
INFO,
info: INFO,
INITBYDIM,
initByDim: INITBYDIM,
INITBYPROB,
initByProb: INITBYPROB,
MERGE,
merge: MERGE,
QUERY,
query: QUERY
};
INCRBY,
incrBy: INCRBY,
INFO,
info: INFO,
INITBYDIM,
initByDim: INITBYDIM,
INITBYPROB,
initByProb: INITBYPROB,
MERGE,
merge: MERGE,
QUERY,
query: QUERY
} as const satisfies RedisCommands;

View File

@@ -1,19 +1,19 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../../test-utils';
import { transformArguments, transformReply } from './ADD';
import ADD from './ADD';
describe('CF ADD', () => {
it('transformArguments', () => {
assert.deepEqual(
transformArguments('key', 'item'),
['CF.ADD', 'key', 'item']
);
});
describe('CF.ADD', () => {
it('transformArguments', () => {
assert.deepEqual(
ADD.transformArguments('key', 'item'),
['CF.ADD', 'key', 'item']
);
});
testUtils.testWithClient('client.cf.add', async client => {
assert.equal(
await client.cf.add('key', 'item'),
true
);
}, GLOBAL.SERVERS.OPEN);
testUtils.testWithClient('client.cf.add', async client => {
assert.equal(
await client.cf.add('key', 'item'),
true
);
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,7 +1,11 @@
export const FIRST_KEY_INDEX = 1;
import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types';
import { transformBooleanReply } from '@redis/client/dist/lib/commands/generic-transformers';
export function transformArguments(key: string, item: string): Array<string> {
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: false,
transformArguments(key: RedisArgument, item: RedisArgument) {
return ['CF.ADD', key, item];
}
export { transformBooleanReply as transformReply } from '@redis/client/dist/lib/commands/generic-transformers';
},
transformReply: transformBooleanReply
} as const satisfies Command;

View File

@@ -1,21 +1,19 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../../test-utils';
import { transformArguments } from './ADDNX';
import ADDNX from './ADDNX';
describe('CF ADDNX', () => {
describe('transformArguments', () => {
it('basic add', () => {
assert.deepEqual(
transformArguments('key', 'item'),
['CF.ADDNX', 'key', 'item']
);
});
});
describe('CF.ADDNX', () => {
it('transformArguments', () => {
assert.deepEqual(
ADDNX.transformArguments('key', 'item'),
['CF.ADDNX', 'key', 'item']
);
});
testUtils.testWithClient('client.cf.add', async client => {
assert.equal(
await client.cf.addNX('key', 'item'),
true
);
}, GLOBAL.SERVERS.OPEN);
testUtils.testWithClient('client.cf.add', async client => {
assert.equal(
await client.cf.addNX('key', 'item'),
true
);
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,7 +1,11 @@
export const FIRST_KEY_INDEX = 1;
import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types';
import { transformBooleanReply } from '@redis/client/dist/lib/commands/generic-transformers';
export function transformArguments(key: string, item: string): Array<string> {
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: false,
transformArguments(key: RedisArgument, item: RedisArgument) {
return ['CF.ADDNX', key, item];
}
export { transformBooleanReply as transformReply } from '@redis/client/dist/lib/commands/generic-transformers';
},
transformReply: transformBooleanReply
} as const satisfies Command;

View File

@@ -1,19 +1,19 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../../test-utils';
import { transformArguments } from './COUNT';
import COUNT from './COUNT';
describe('CF COUNT', () => {
it('transformArguments', () => {
assert.deepEqual(
transformArguments('key', 'item'),
['CF.COUNT', 'key', 'item']
);
});
describe('CF.COUNT', () => {
it('transformArguments', () => {
assert.deepEqual(
COUNT.transformArguments('key', 'item'),
['CF.COUNT', 'key', 'item']
);
});
testUtils.testWithClient('client.cf.count', async client => {
assert.equal(
await client.cf.count('key', 'item'),
0
);
}, GLOBAL.SERVERS.OPEN);
testUtils.testWithClient('client.cf.count', async client => {
assert.equal(
await client.cf.count('key', 'item'),
0
);
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,7 +1,10 @@
export const FIRST_KEY_INDEX = 1;
import { RedisArgument, NumberReply, Command } from '@redis/client/dist/lib/RESP/types';
export function transformArguments(key: string, item: string): Array<string> {
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: true,
transformArguments(key: RedisArgument, item: RedisArgument) {
return ['CF.COUNT', key, item];
}
export declare function transformReply(): number;
},
transformReply: undefined as unknown as () => NumberReply
} as const satisfies Command;

View File

@@ -1,21 +1,21 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../../test-utils';
import { transformArguments } from './DEL';
import DEL from './DEL';
describe('CF DEL', () => {
it('transformArguments', () => {
assert.deepEqual(
transformArguments('key', 'item'),
['CF.DEL', 'key', 'item']
);
});
describe('CF.DEL', () => {
it('transformArguments', () => {
assert.deepEqual(
DEL.transformArguments('key', 'item'),
['CF.DEL', 'key', 'item']
);
});
testUtils.testWithClient('client.cf.del', async client => {
await client.cf.reserve('key', 4);
testUtils.testWithClient('client.cf.del', async client => {
const [, reply] = await Promise.all([
client.cf.reserve('key', 4),
client.cf.del('key', 'item')
]);
assert.equal(
await client.cf.del('key', 'item'),
false
);
}, GLOBAL.SERVERS.OPEN);
assert.equal(reply, false);
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,7 +1,11 @@
export const FIRST_KEY_INDEX = 1;
import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types';
import { transformBooleanReply } from '@redis/client/dist/lib/commands/generic-transformers';
export function transformArguments(key: string, item: string): Array<string> {
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: false,
transformArguments(key: RedisArgument, item: RedisArgument) {
return ['CF.DEL', key, item];
}
export { transformBooleanReply as transformReply } from '@redis/client/dist/lib/commands/generic-transformers';
},
transformReply: transformBooleanReply
} as const satisfies Command;

View File

@@ -1,19 +1,19 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../../test-utils';
import { transformArguments } from './EXISTS';
import EXISTS from './EXISTS';
describe('CF EXISTS', () => {
it('transformArguments', () => {
assert.deepEqual(
transformArguments('key', 'item'),
['CF.EXISTS', 'key', 'item']
);
});
describe('CF.EXISTS', () => {
it('transformArguments', () => {
assert.deepEqual(
EXISTS.transformArguments('key', 'item'),
['CF.EXISTS', 'key', 'item']
);
});
testUtils.testWithClient('client.cf.exists', async client => {
assert.equal(
await client.cf.exists('key', 'item'),
false
);
}, GLOBAL.SERVERS.OPEN);
testUtils.testWithClient('client.cf.exists', async client => {
assert.equal(
await client.cf.exists('key', 'item'),
false
);
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,9 +1,11 @@
export const FIRST_KEY_INDEX = 1;
import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types';
import { transformBooleanReply } from '@redis/client/dist/lib/commands/generic-transformers';
export const IS_READ_ONLY = true;
export function transformArguments(key: string, item: string): Array<string> {
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: false,
transformArguments(key: RedisArgument, item: RedisArgument) {
return ['CF.EXISTS', key, item];
}
export { transformBooleanReply as transformReply } from '@redis/client/dist/lib/commands/generic-transformers';
},
transformReply: transformBooleanReply
} as const satisfies Command;

View File

@@ -1,27 +1,29 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../../test-utils';
import { transformArguments } from './INFO';
import INFO from './INFO';
describe('CF INFO', () => {
it('transformArguments', () => {
assert.deepEqual(
transformArguments('cuckoo'),
['CF.INFO', 'cuckoo']
);
});
describe('CF.INFO', () => {
it('transformArguments', () => {
assert.deepEqual(
INFO.transformArguments('cuckoo'),
['CF.INFO', 'cuckoo']
);
});
testUtils.testWithClient('client.cf.info', async client => {
await client.cf.reserve('key', 4);
testUtils.testWithClient('client.cf.info', async client => {
const [, reply] = await Promise.all([
client.cf.reserve('key', 4),
client.cf.info('key')
]);
const info = await client.cf.info('key');
assert.equal(typeof info, 'object');
assert.equal(typeof info.size, 'number');
assert.equal(typeof info.numberOfBuckets, 'number');
assert.equal(typeof info.numberOfFilters, 'number');
assert.equal(typeof info.numberOfInsertedItems, 'number');
assert.equal(typeof info.numberOfDeletedItems, 'number');
assert.equal(typeof info.bucketSize, 'number');
assert.equal(typeof info.expansionRate, 'number');
assert.equal(typeof info.maxIteration, 'number');
}, GLOBAL.SERVERS.OPEN);
assert.equal(typeof reply, 'object');
assert.equal(typeof reply['Size'], 'number');
assert.equal(typeof reply['Number of buckets'], 'number');
assert.equal(typeof reply['Number of filters'], 'number');
assert.equal(typeof reply['Number of items inserted'], 'number');
assert.equal(typeof reply['Number of items deleted'], 'number');
assert.equal(typeof reply['Bucket size'], 'number');
assert.equal(typeof reply['Expansion rate'], 'number');
assert.equal(typeof reply['Max iterations'], 'number');
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,50 +1,27 @@
export const FIRST_KEY_INDEX = 1;
import { RedisArgument, Command, NumberReply, TuplesToMapReply, UnwrapReply, Resp2Reply, SimpleStringReply, TypeMapping } from '@redis/client/dist/lib/RESP/types';
import { transformInfoV2Reply } from '../bloom';
export const IS_READ_ONLY = true;
export type CfInfoReplyMap = TuplesToMapReply<[
[SimpleStringReply<'Size'>, NumberReply],
[SimpleStringReply<'Number of buckets'>, NumberReply],
[SimpleStringReply<'Number of filters'>, NumberReply],
[SimpleStringReply<'Number of items inserted'>, NumberReply],
[SimpleStringReply<'Number of items deleted'>, NumberReply],
[SimpleStringReply<'Bucket size'>, NumberReply],
[SimpleStringReply<'Expansion rate'>, NumberReply],
[SimpleStringReply<'Max iterations'>, NumberReply]
]>;
export function transformArguments(key: string): Array<string> {
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: true,
transformArguments(key: RedisArgument) {
return ['CF.INFO', key];
}
export type InfoRawReply = [
_: string,
size: number,
_: string,
numberOfBuckets: number,
_: string,
numberOfFilters: number,
_: string,
numberOfInsertedItems: number,
_: string,
numberOfDeletedItems: number,
_: string,
bucketSize: number,
_: string,
expansionRate: number,
_: string,
maxIteration: number
];
export interface InfoReply {
size: number;
numberOfBuckets: number;
numberOfFilters: number;
numberOfInsertedItems: number;
numberOfDeletedItems: number;
bucketSize: number;
expansionRate: number;
maxIteration: number;
}
export function transformReply(reply: InfoRawReply): InfoReply {
return {
size: reply[1],
numberOfBuckets: reply[3],
numberOfFilters: reply[5],
numberOfInsertedItems: reply[7],
numberOfDeletedItems: reply[9],
bucketSize: reply[11],
expansionRate: reply[13],
maxIteration: reply[15]
};
}
},
transformReply: {
2: (reply: UnwrapReply<Resp2Reply<CfInfoReplyMap>>, _, typeMapping?: TypeMapping): CfInfoReplyMap => {
return transformInfoV2Reply<CfInfoReplyMap>(reply, typeMapping);
},
3: undefined as unknown as () => CfInfoReplyMap
}
} as const satisfies Command;

View File

@@ -1,22 +1,22 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../../test-utils';
import { transformArguments } from './INSERT';
import INSERT from './INSERT';
describe('CF INSERT', () => {
it('transformArguments', () => {
assert.deepEqual(
transformArguments('key', 'item', {
CAPACITY: 100,
NOCREATE: true
}),
['CF.INSERT', 'key', 'CAPACITY', '100', 'NOCREATE', 'ITEMS', 'item']
);
});
describe('CF.INSERT', () => {
it('transformArguments', () => {
assert.deepEqual(
INSERT.transformArguments('key', 'item', {
CAPACITY: 100,
NOCREATE: true
}),
['CF.INSERT', 'key', 'CAPACITY', '100', 'NOCREATE', 'ITEMS', 'item']
);
});
testUtils.testWithClient('client.cf.insert', async client => {
assert.deepEqual(
await client.cf.insert('key', 'item'),
[true]
);
}, GLOBAL.SERVERS.OPEN);
testUtils.testWithClient('client.cf.insert', async client => {
assert.deepEqual(
await client.cf.insert('key', 'item'),
[true]
);
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,18 +1,34 @@
import { RedisCommandArguments } from '@redis/client/dist/lib/commands';
import { InsertOptions, pushInsertOptions } from ".";
import { Command, RedisArgument } from '@redis/client/dist/lib/RESP/types';
import { RedisVariadicArgument, pushVariadicArguments, transformBooleanArrayReply } from '@redis/client/dist/lib/commands/generic-transformers';
export const FIRST_KEY_INDEX = 1;
export function transformArguments(
key: string,
items: string | Array<string>,
options?: InsertOptions
): RedisCommandArguments {
return pushInsertOptions(
['CF.INSERT', key],
items,
options
);
export interface CfInsertOptions {
CAPACITY?: number;
NOCREATE?: boolean;
}
export { transformBooleanArrayReply as transformReply } from '@redis/client/dist/lib/commands/generic-transformers';
export function transofrmCfInsertArguments(
command: RedisArgument,
key: RedisArgument,
items: RedisVariadicArgument,
options?: CfInsertOptions
) {
const args = [command, key];
if (options?.CAPACITY !== undefined) {
args.push('CAPACITY', options.CAPACITY.toString());
}
if (options?.NOCREATE) {
args.push('NOCREATE');
}
args.push('ITEMS');
return pushVariadicArguments(args, items);
}
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: false,
transformArguments: transofrmCfInsertArguments.bind(undefined, 'CF.INSERT'),
transformReply: transformBooleanArrayReply
} as const satisfies Command;

View File

@@ -1,22 +1,22 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../../test-utils';
import { transformArguments } from './INSERTNX';
import INSERTNX from './INSERTNX';
describe('CF INSERTNX', () => {
it('transformArguments', () => {
assert.deepEqual(
transformArguments('key', 'item', {
CAPACITY: 100,
NOCREATE: true
}),
['CF.INSERTNX', 'key', 'CAPACITY', '100', 'NOCREATE', 'ITEMS', 'item']
);
});
describe('CF.INSERTNX', () => {
it('transformArguments', () => {
assert.deepEqual(
INSERTNX.transformArguments('key', 'item', {
CAPACITY: 100,
NOCREATE: true
}),
['CF.INSERTNX', 'key', 'CAPACITY', '100', 'NOCREATE', 'ITEMS', 'item']
);
});
testUtils.testWithClient('client.cf.insertnx', async client => {
assert.deepEqual(
await client.cf.insertNX('key', 'item'),
[true]
);
}, GLOBAL.SERVERS.OPEN);
testUtils.testWithClient('client.cf.insertnx', async client => {
assert.deepEqual(
await client.cf.insertNX('key', 'item'),
[true]
);
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,18 +1,9 @@
import { RedisCommandArguments } from '@redis/client/dist/lib/commands';
import { InsertOptions, pushInsertOptions } from ".";
import { Command } from '@redis/client/dist/lib/RESP/types';
import INSERT, { transofrmCfInsertArguments } from './INSERT';
export const FIRST_KEY_INDEX = 1;
export function transformArguments(
key: string,
items: string | Array<string>,
options?: InsertOptions
): RedisCommandArguments {
return pushInsertOptions(
['CF.INSERTNX', key],
items,
options
);
}
export { transformBooleanArrayReply as transformReply } from '@redis/client/dist/lib/commands/generic-transformers';
export default {
FIRST_KEY_INDEX: INSERT.FIRST_KEY_INDEX,
IS_READ_ONLY: INSERT.IS_READ_ONLY,
transformArguments: transofrmCfInsertArguments.bind(undefined, 'CF.INSERTNX'),
transformReply: INSERT.transformReply
} as const satisfies Command;

View File

@@ -1,31 +1,36 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../../test-utils';
import { transformArguments } from './LOADCHUNK';
import LOADCHUNK from './LOADCHUNK';
import { RESP_TYPES } from '@redis/client';
describe('CF LOADCHUNK', () => {
it('transformArguments', () => {
assert.deepEqual(
transformArguments('item', 0, ''),
['CF.LOADCHUNK', 'item', '0', '']
);
});
describe('CF.LOADCHUNK', () => {
it('transformArguments', () => {
assert.deepEqual(
LOADCHUNK.transformArguments('item', 0, ''),
['CF.LOADCHUNK', 'item', '0', '']
);
});
testUtils.testWithClient('client.cf.loadChunk', async client => {
const [,, { iterator, chunk }] = await Promise.all([
client.cf.reserve('source', 4),
client.cf.add('source', 'item'),
client.cf.scanDump(
client.commandOptions({ returnBuffers: true }),
'source',
0
)
]);
testUtils.testWithClient('client.cf.loadChunk', async client => {
const [, , { iterator, chunk }] = await Promise.all([
client.cf.reserve('source', 4),
client.cf.add('source', 'item'),
client.cf.scanDump('source', 0)
]);
assert.ok(Buffer.isBuffer(chunk));
assert.equal(
await client.cf.loadChunk('destination', iterator, chunk),
'OK'
);
}, GLOBAL.SERVERS.OPEN);
assert.equal(
await client.cf.loadChunk('destination', iterator, chunk!),
'OK'
);
}, {
...GLOBAL.SERVERS.OPEN,
clientOptions: {
...GLOBAL.SERVERS.OPEN.clientOptions,
commandOptions: {
typeMapping: {
[RESP_TYPES.BLOB_STRING]: Buffer
}
}
}
});
});

View File

@@ -1,13 +1,10 @@
import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands';
import { SimpleStringReply, Command, RedisArgument } from '@redis/client/dist/lib/RESP/types';
export const FIRST_KEY_INDEX = 1;
export function transformArguments(
key: string,
iterator: number,
chunk: RedisCommandArgument
): RedisCommandArguments {
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: false,
transformArguments(key: RedisArgument, iterator: number, chunk: RedisArgument) {
return ['CF.LOADCHUNK', key, iterator.toString(), chunk];
}
export declare function transformReply(): 'OK';
},
transformReply: undefined as unknown as () => SimpleStringReply<'OK'>
} as const satisfies Command;

View File

@@ -1,48 +1,48 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../../test-utils';
import { transformArguments } from './RESERVE';
import RESERVE from './RESERVE';
describe('CF RESERVE', () => {
describe('transformArguments', () => {
it('simple', () => {
assert.deepEqual(
transformArguments('key', 4),
['CF.RESERVE', 'key', '4']
);
});
it('with EXPANSION', () => {
assert.deepEqual(
transformArguments('key', 4, {
EXPANSION: 1
}),
['CF.RESERVE', 'key', '4', 'EXPANSION', '1']
);
});
it('with BUCKETSIZE', () => {
assert.deepEqual(
transformArguments('key', 4, {
BUCKETSIZE: 2
}),
['CF.RESERVE', 'key', '4', 'BUCKETSIZE', '2']
);
});
it('with MAXITERATIONS', () => {
assert.deepEqual(
transformArguments('key', 4, {
MAXITERATIONS: 1
}),
['CF.RESERVE', 'key', '4', 'MAXITERATIONS', '1']
);
});
describe('CF.RESERVE', () => {
describe('transformArguments', () => {
it('simple', () => {
assert.deepEqual(
RESERVE.transformArguments('key', 4),
['CF.RESERVE', 'key', '4']
);
});
testUtils.testWithClient('client.cf.reserve', async client => {
assert.equal(
await client.cf.reserve('key', 4),
'OK'
);
}, GLOBAL.SERVERS.OPEN);
it('with EXPANSION', () => {
assert.deepEqual(
RESERVE.transformArguments('key', 4, {
EXPANSION: 1
}),
['CF.RESERVE', 'key', '4', 'EXPANSION', '1']
);
});
it('with BUCKETSIZE', () => {
assert.deepEqual(
RESERVE.transformArguments('key', 4, {
BUCKETSIZE: 2
}),
['CF.RESERVE', 'key', '4', 'BUCKETSIZE', '2']
);
});
it('with MAXITERATIONS', () => {
assert.deepEqual(
RESERVE.transformArguments('key', 4, {
MAXITERATIONS: 1
}),
['CF.RESERVE', 'key', '4', 'MAXITERATIONS', '1']
);
});
});
testUtils.testWithClient('client.cf.reserve', async client => {
assert.equal(
await client.cf.reserve('key', 4),
'OK'
);
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,31 +1,34 @@
export const FIRST_KEY_INDEX = 1;
import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types';
interface ReserveOptions {
BUCKETSIZE?: number;
MAXITERATIONS?: number;
EXPANSION?: number;
export interface CfReserveOptions {
BUCKETSIZE?: number;
MAXITERATIONS?: number;
EXPANSION?: number;
}
export function transformArguments(
key: string,
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: false,
transformArguments(
key: RedisArgument,
capacity: number,
options?: ReserveOptions
): Array<string> {
options?: CfReserveOptions
) {
const args = ['CF.RESERVE', key, capacity.toString()];
if (options?.BUCKETSIZE) {
args.push('BUCKETSIZE', options.BUCKETSIZE.toString());
if (options?.BUCKETSIZE !== undefined) {
args.push('BUCKETSIZE', options.BUCKETSIZE.toString());
}
if (options?.MAXITERATIONS) {
args.push('MAXITERATIONS', options.MAXITERATIONS.toString());
if (options?.MAXITERATIONS !== undefined) {
args.push('MAXITERATIONS', options.MAXITERATIONS.toString());
}
if (options?.EXPANSION) {
args.push('EXPANSION', options.EXPANSION.toString());
if (options?.EXPANSION !== undefined) {
args.push('EXPANSION', options.EXPANSION.toString());
}
return args;
}
export declare function transformReply(): 'OK';
},
transformReply: undefined as unknown as () => SimpleStringReply<'OK'>
} as const satisfies Command;

View File

@@ -1,23 +1,24 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../../test-utils';
import { transformArguments } from './SCANDUMP';
import SCANDUMP from './SCANDUMP';
describe('CF SCANDUMP', () => {
it('transformArguments', () => {
assert.deepEqual(
transformArguments('key', 0),
['CF.SCANDUMP', 'key', '0']
);
describe('CF.SCANDUMP', () => {
it('transformArguments', () => {
assert.deepEqual(
SCANDUMP.transformArguments('key', 0),
['CF.SCANDUMP', 'key', '0']
);
});
testUtils.testWithClient('client.cf.scanDump', async client => {
const [, reply] = await Promise.all([
client.cf.reserve('key', 4),
client.cf.scanDump('key', 0)
]);
assert.deepEqual(reply, {
iterator: 0,
chunk: null
});
testUtils.testWithClient('client.cf.scanDump', async client => {
await client.cf.reserve('key', 4);
assert.deepEqual(
await client.cf.scanDump('key', 0),
{
iterator: 0,
chunk: null
}
);
}, GLOBAL.SERVERS.OPEN);
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,22 +1,15 @@
export const FIRST_KEY_INDEX = 1;
import { RedisArgument, TuplesReply, NumberReply, BlobStringReply, NullReply, UnwrapReply, Command } from '@redis/client/dist/lib/RESP/types';
export function transformArguments(key: string, iterator: number): Array<string> {
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: true,
transformArguments(key: RedisArgument, iterator: number) {
return ['CF.SCANDUMP', key, iterator.toString()];
}
type ScanDumpRawReply = [
iterator: number,
chunk: string | null
];
interface ScanDumpReply {
iterator: number;
chunk: string | null;
}
export function transformReply([iterator, chunk]: ScanDumpRawReply): ScanDumpReply {
},
transformReply(reply: UnwrapReply<TuplesReply<[NumberReply, BlobStringReply | NullReply]>>) {
return {
iterator,
chunk
iterator: reply[0],
chunk: reply[1]
};
}
}
} as const satisfies Command;

View File

@@ -1,48 +0,0 @@
import { strict as assert } from 'assert';
import { pushInsertOptions } from '.';
describe('pushInsertOptions', () => {
describe('single item', () => {
it('single item', () => {
assert.deepEqual(
pushInsertOptions([], 'item'),
['ITEMS', 'item']
);
});
it('multiple items', () => {
assert.deepEqual(
pushInsertOptions([], ['1', '2']),
['ITEMS', '1', '2']
);
});
});
it('with CAPACITY', () => {
assert.deepEqual(
pushInsertOptions([], 'item', {
CAPACITY: 100
}),
['CAPACITY', '100', 'ITEMS', 'item']
);
});
it('with NOCREATE', () => {
assert.deepEqual(
pushInsertOptions([], 'item', {
NOCREATE: true
}),
['NOCREATE', 'ITEMS', 'item']
);
});
it('with CAPACITY and NOCREATE', () => {
assert.deepEqual(
pushInsertOptions([], 'item', {
CAPACITY: 100,
NOCREATE: true
}),
['CAPACITY', '100', 'NOCREATE', 'ITEMS', 'item']
);
});
});

View File

@@ -1,62 +1,37 @@
import * as ADD from './ADD';
import * as ADDNX from './ADDNX';
import * as COUNT from './COUNT';
import * as DEL from './DEL';
import * as EXISTS from './EXISTS';
import * as INFO from './INFO';
import * as INSERT from './INSERT';
import * as INSERTNX from './INSERTNX';
import * as LOADCHUNK from './LOADCHUNK';
import * as RESERVE from './RESERVE';
import * as SCANDUMP from './SCANDUMP';
import { pushVerdictArguments } from '@redis/client/dist/lib/commands/generic-transformers';
import { RedisCommandArguments } from '@redis/client/dist/lib/commands';
import type { RedisCommands } from '@redis/client/dist/lib/RESP/types';
import ADD from './ADD';
import ADDNX from './ADDNX';
import COUNT from './COUNT';
import DEL from './DEL';
import EXISTS from './EXISTS';
import INFO from './INFO';
import INSERT from './INSERT';
import INSERTNX from './INSERTNX';
import LOADCHUNK from './LOADCHUNK';
import RESERVE from './RESERVE';
import SCANDUMP from './SCANDUMP';
export default {
ADD,
add: ADD,
ADDNX,
addNX: ADDNX,
COUNT,
count: COUNT,
DEL,
del: DEL,
EXISTS,
exists: EXISTS,
INFO,
info: INFO,
INSERT,
insert: INSERT,
INSERTNX,
insertNX: INSERTNX,
LOADCHUNK,
loadChunk: LOADCHUNK,
RESERVE,
reserve: RESERVE,
SCANDUMP,
scanDump: SCANDUMP
};
export interface InsertOptions {
CAPACITY?: number;
NOCREATE?: true;
}
export function pushInsertOptions(
args: RedisCommandArguments,
items: string | Array<string>,
options?: InsertOptions
): RedisCommandArguments {
if (options?.CAPACITY) {
args.push('CAPACITY');
args.push(options.CAPACITY.toString());
}
if (options?.NOCREATE) {
args.push('NOCREATE');
}
args.push('ITEMS');
return pushVerdictArguments(args, items);
}
ADD,
add: ADD,
ADDNX,
addNX: ADDNX,
COUNT,
count: COUNT,
DEL,
del: DEL,
EXISTS,
exists: EXISTS,
INFO,
info: INFO,
INSERT,
insert: INSERT,
INSERTNX,
insertNX: INSERTNX,
LOADCHUNK,
loadChunk: LOADCHUNK,
RESERVE,
reserve: RESERVE,
SCANDUMP,
scanDump: SCANDUMP
} as const satisfies RedisCommands;

View File

@@ -1,3 +1,4 @@
import { RedisModules } from '@redis/client';
import bf from './bloom';
import cms from './count-min-sketch';
import cf from './cuckoo';
@@ -5,9 +6,9 @@ import tDigest from './t-digest';
import topK from './top-k';
export default {
bf,
cms,
cf,
tDigest,
topK
};
bf,
cms,
cf,
tDigest,
topK
} as const satisfies RedisModules;

View File

@@ -1,21 +1,21 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../../test-utils';
import { transformArguments } from './ADD';
import ADD from './ADD';
describe('TDIGEST.ADD', () => {
it('transformArguments', () => {
assert.deepEqual(
transformArguments('key', [1, 2]),
['TDIGEST.ADD', 'key', '1', '2']
);
});
it('transformArguments', () => {
assert.deepEqual(
ADD.transformArguments('key', [1, 2]),
['TDIGEST.ADD', 'key', '1', '2']
);
});
testUtils.testWithClient('client.tDigest.add', async client => {
const [ , reply ] = await Promise.all([
client.tDigest.create('key'),
client.tDigest.add('key', [1])
]);
testUtils.testWithClient('client.tDigest.add', async client => {
const [, reply] = await Promise.all([
client.tDigest.create('key'),
client.tDigest.add('key', [1])
]);
assert.equal(reply, 'OK');
}, GLOBAL.SERVERS.OPEN);
assert.equal(reply, 'OK');
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,17 +1,16 @@
import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands';
import { SimpleStringReply, Command, RedisArgument } from '@redis/client/dist/lib/RESP/types';
export const FIRST_KEY_INDEX = 1;
export function transformArguments(
key: RedisCommandArgument,
values: Array<number>
): RedisCommandArguments {
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: false,
transformArguments(key: RedisArgument, values: Array<number>) {
const args = ['TDIGEST.ADD', key];
for (const item of values) {
args.push(item.toString());
for (const value of values) {
args.push(value.toString());
}
return args;
}
export declare function transformReply(): 'OK';
},
transformReply: undefined as unknown as () => SimpleStringReply<'OK'>
} as const satisfies Command;

View File

@@ -1,21 +1,21 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../../test-utils';
import { transformArguments } from './BYRANK';
import BYRANK from './BYRANK';
describe('TDIGEST.BYRANK', () => {
it('transformArguments', () => {
assert.deepEqual(
transformArguments('key', [1, 2]),
['TDIGEST.BYRANK', 'key', '1', '2']
);
});
it('transformArguments', () => {
assert.deepEqual(
BYRANK.transformArguments('key', [1, 2]),
['TDIGEST.BYRANK', 'key', '1', '2']
);
});
testUtils.testWithClient('client.tDigest.byRank', async client => {
const [ , reply ] = await Promise.all([
client.tDigest.create('key'),
client.tDigest.byRank('key', [1])
]);
testUtils.testWithClient('client.tDigest.byRank', async client => {
const [, reply] = await Promise.all([
client.tDigest.create('key'),
client.tDigest.byRank('key', [1])
]);
assert.deepEqual(reply, [NaN]);
}, GLOBAL.SERVERS.OPEN);
assert.deepEqual(reply, [NaN]);
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,19 +1,24 @@
import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands';
import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types';
import { transformDoubleArrayReply } from '@redis/client/dist/lib/commands/generic-transformers';
export const FIRST_KEY_INDEX = 1;
export function transformByRankArguments(
command: RedisArgument,
key: RedisArgument,
ranks: Array<number>
) {
const args = [command, key];
export const IS_READ_ONLY = true;
for (const rank of ranks) {
args.push(rank.toString());
}
export function transformArguments(
key: RedisCommandArgument,
ranks: Array<number>
): RedisCommandArguments {
const args = ['TDIGEST.BYRANK', key];
for (const rank of ranks) {
args.push(rank.toString());
}
return args;
return args;
}
export { transformDoublesReply as transformReply } from '.';
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: true,
transformArguments: transformByRankArguments.bind(undefined, 'TDIGEST.BYRANK'),
transformReply: transformDoubleArrayReply
} as const satisfies Command;

View File

@@ -1,21 +1,21 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../../test-utils';
import { transformArguments } from './BYREVRANK';
import BYREVRANK from './BYREVRANK';
describe('TDIGEST.BYREVRANK', () => {
it('transformArguments', () => {
assert.deepEqual(
transformArguments('key', [1, 2]),
['TDIGEST.BYREVRANK', 'key', '1', '2']
);
});
it('transformArguments', () => {
assert.deepEqual(
BYREVRANK.transformArguments('key', [1, 2]),
['TDIGEST.BYREVRANK', 'key', '1', '2']
);
});
testUtils.testWithClient('client.tDigest.byRevRank', async client => {
const [ , reply ] = await Promise.all([
client.tDigest.create('key'),
client.tDigest.byRevRank('key', [1])
]);
testUtils.testWithClient('client.tDigest.byRevRank', async client => {
const [, reply] = await Promise.all([
client.tDigest.create('key'),
client.tDigest.byRevRank('key', [1])
]);
assert.deepEqual(reply, [NaN]);
}, GLOBAL.SERVERS.OPEN);
assert.deepEqual(reply, [NaN]);
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,19 +1,9 @@
import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands';
import { Command } from '@redis/client/dist/lib/RESP/types';
import BYRANK, { transformByRankArguments } from './BYRANK';
export const FIRST_KEY_INDEX = 1;
export const IS_READ_ONLY = true;
export function transformArguments(
key: RedisCommandArgument,
ranks: Array<number>
): RedisCommandArguments {
const args = ['TDIGEST.BYREVRANK', key];
for (const rank of ranks) {
args.push(rank.toString());
}
return args;
}
export { transformDoublesReply as transformReply } from '.';
export default {
FIRST_KEY_INDEX: BYRANK.FIRST_KEY_INDEX,
IS_READ_ONLY: BYRANK.IS_READ_ONLY,
transformArguments: transformByRankArguments.bind(undefined, 'TDIGEST.BYREVRANK'),
transformReply: BYRANK.transformReply
} as const satisfies Command;

View File

@@ -1,21 +1,21 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../../test-utils';
import { transformArguments } from './CDF';
import CDF from './CDF';
describe('TDIGEST.CDF', () => {
it('transformArguments', () => {
assert.deepEqual(
transformArguments('key', [1, 2]),
['TDIGEST.CDF', 'key', '1', '2']
);
});
it('transformArguments', () => {
assert.deepEqual(
CDF.transformArguments('key', [1, 2]),
['TDIGEST.CDF', 'key', '1', '2']
);
});
testUtils.testWithClient('client.tDigest.cdf', async client => {
const [ , reply ] = await Promise.all([
client.tDigest.create('key'),
client.tDigest.cdf('key', [1])
]);
testUtils.testWithClient('client.tDigest.cdf', async client => {
const [, reply] = await Promise.all([
client.tDigest.create('key'),
client.tDigest.cdf('key', [1])
]);
assert.deepEqual(reply, [NaN]);
}, GLOBAL.SERVERS.OPEN);
assert.deepEqual(reply, [NaN]);
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,19 +1,17 @@
import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands';
import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types';
import { transformDoubleArrayReply } from '@redis/client/dist/lib/commands/generic-transformers';
export const FIRST_KEY_INDEX = 1;
export const IS_READ_ONLY = true;
export function transformArguments(
key: RedisCommandArgument,
values: Array<number>
): RedisCommandArguments {
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: true,
transformArguments(key: RedisArgument, values: Array<number>) {
const args = ['TDIGEST.CDF', key];
for (const item of values) {
args.push(item.toString());
args.push(item.toString());
}
return args;
}
export { transformDoublesReply as transformReply } from '.';
},
transformReply: transformDoubleArrayReply
} as const satisfies Command;

View File

@@ -1,30 +1,30 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../../test-utils';
import { transformArguments } from './CREATE';
import CREATE from './CREATE';
describe('TDIGEST.CREATE', () => {
describe('transformArguments', () => {
it('without options', () => {
assert.deepEqual(
transformArguments('key'),
['TDIGEST.CREATE', 'key']
);
});
it('with COMPRESSION', () => {
assert.deepEqual(
transformArguments('key', {
COMPRESSION: 100
}),
['TDIGEST.CREATE', 'key', 'COMPRESSION', '100']
);
});
describe('transformArguments', () => {
it('without options', () => {
assert.deepEqual(
CREATE.transformArguments('key'),
['TDIGEST.CREATE', 'key']
);
});
testUtils.testWithClient('client.tDigest.create', async client => {
assert.equal(
await client.tDigest.create('key'),
'OK'
);
}, GLOBAL.SERVERS.OPEN);
it('with COMPRESSION', () => {
assert.deepEqual(
CREATE.transformArguments('key', {
COMPRESSION: 100
}),
['TDIGEST.CREATE', 'key', 'COMPRESSION', '100']
);
});
});
testUtils.testWithClient('client.tDigest.create', async client => {
assert.equal(
await client.tDigest.create('key'),
'OK'
);
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,16 +1,20 @@
import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands';
import { CompressionOption, pushCompressionArgument } from '.';
import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types';
export const FIRST_KEY_INDEX = 1;
export function transformArguments(
key: RedisCommandArgument,
options?: CompressionOption
): RedisCommandArguments {
return pushCompressionArgument(
['TDIGEST.CREATE', key],
options
);
export interface TDigestCreateOptions {
COMPRESSION?: number;
}
export declare function transformReply(): 'OK';
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: false,
transformArguments(key: RedisArgument, options?: TDigestCreateOptions) {
const args = ['TDIGEST.CREATE', key];
if (options?.COMPRESSION !== undefined) {
args.push('COMPRESSION', options.COMPRESSION.toString());
}
return args;
},
transformReply: undefined as unknown as () => SimpleStringReply<'OK'>
} as const satisfies Command;

View File

@@ -1,25 +1,30 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../../test-utils';
import { transformArguments } from './INFO';
import INFO from './INFO';
describe('TDIGEST.INFO', () => {
it('transformArguments', () => {
assert.deepEqual(
transformArguments('key'),
['TDIGEST.INFO', 'key']
);
});
it('transformArguments', () => {
assert.deepEqual(
INFO.transformArguments('key'),
['TDIGEST.INFO', 'key']
);
});
testUtils.testWithClient('client.tDigest.info', async client => {
await client.tDigest.create('key');
testUtils.testWithClient('client.tDigest.info', async client => {
const [, reply] = await Promise.all([
client.tDigest.create('key'),
client.tDigest.info('key')
]);
const info = await client.tDigest.info('key');
assert(typeof info.capacity, 'number');
assert(typeof info.mergedNodes, 'number');
assert(typeof info.unmergedNodes, 'number');
assert(typeof info.mergedWeight, 'number');
assert(typeof info.unmergedWeight, 'number');
assert(typeof info.totalCompression, 'number');
assert(typeof info.totalCompression, 'number');
}, GLOBAL.SERVERS.OPEN);
assert(typeof reply, 'object');
assert(typeof reply['Compression'], 'number');
assert(typeof reply['Capacity'], 'number');
assert(typeof reply['Merged nodes'], 'number');
assert(typeof reply['Unmerged nodes'], 'number');
assert(typeof reply['Merged weight'], 'number');
assert(typeof reply['Unmerged weight'], 'number');
assert(typeof reply['Observations'], 'number');
assert(typeof reply['Total compressions'], 'number');
assert(typeof reply['Memory usage'], 'number');
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,51 +1,28 @@
import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands';
import { RedisArgument, Command, NumberReply, TuplesToMapReply, UnwrapReply, Resp2Reply, SimpleStringReply, TypeMapping } from '@redis/client/dist/lib/RESP/types';
import { transformInfoV2Reply } from '../bloom';
export const FIRST_KEY_INDEX = 1;
export type TdInfoReplyMap = TuplesToMapReply<[
[SimpleStringReply<'Compression'>, NumberReply],
[SimpleStringReply<'Capacity'>, NumberReply],
[SimpleStringReply<'Merged nodes'>, NumberReply],
[SimpleStringReply<'Unmerged nodes'>, NumberReply],
[SimpleStringReply<'Merged weight'>, NumberReply],
[SimpleStringReply<'Unmerged weight'>, NumberReply],
[SimpleStringReply<'Observations'>, NumberReply],
[SimpleStringReply<'Total compressions'>, NumberReply],
[SimpleStringReply<'Memory usage'>, NumberReply]
]>;
export const IS_READ_ONLY = true;
export function transformArguments(key: RedisCommandArgument): RedisCommandArguments {
return [
'TDIGEST.INFO',
key
];
}
type InfoRawReply = [
'Compression',
number,
'Capacity',
number,
'Merged nodes',
number,
'Unmerged nodes',
number,
'Merged weight',
string,
'Unmerged weight',
string,
'Total compressions',
number
];
interface InfoReply {
comperssion: number;
capacity: number;
mergedNodes: number;
unmergedNodes: number;
mergedWeight: number;
unmergedWeight: number;
totalCompression: number;
}
export function transformReply(reply: InfoRawReply): InfoReply {
return {
comperssion: reply[1],
capacity: reply[3],
mergedNodes: reply[5],
unmergedNodes: reply[7],
mergedWeight: Number(reply[9]),
unmergedWeight: Number(reply[11]),
totalCompression: reply[13]
};
}
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: true,
transformArguments(key: RedisArgument) {
return ['TDIGEST.INFO', key];
},
transformReply: {
2: (reply: UnwrapReply<Resp2Reply<TdInfoReplyMap>>, _, typeMapping?: TypeMapping): TdInfoReplyMap => {
return transformInfoV2Reply<TdInfoReplyMap>(reply, typeMapping);
},
3: undefined as unknown as () => TdInfoReplyMap
}
} as const satisfies Command;

View File

@@ -1,21 +1,21 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../../test-utils';
import { transformArguments, transformReply } from './MAX';
import MAX from './MAX';
describe('TDIGEST.MAX', () => {
it('transformArguments', () => {
assert.deepEqual(
transformArguments('key'),
['TDIGEST.MAX', 'key']
);
});
it('transformArguments', () => {
assert.deepEqual(
MAX.transformArguments('key'),
['TDIGEST.MAX', 'key']
);
});
testUtils.testWithClient('client.tDigest.max', async client => {
const [ , reply ] = await Promise.all([
client.tDigest.create('key'),
client.tDigest.max('key')
]);
testUtils.testWithClient('client.tDigest.max', async client => {
const [, reply] = await Promise.all([
client.tDigest.create('key'),
client.tDigest.max('key')
]);
assert.deepEqual(reply, NaN);
}, GLOBAL.SERVERS.OPEN);
assert.deepEqual(reply, NaN);
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,14 +1,11 @@
import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands';
import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types';
import { transformDoubleReply } from '@redis/client/dist/lib/commands/generic-transformers';
export const FIRST_KEY_INDEX = 1;
export const IS_READ_ONLY = true;
export function transformArguments(key: RedisCommandArgument): RedisCommandArguments {
return [
'TDIGEST.MAX',
key
];
}
export { transformDoubleReply as transformReply } from '.';
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: true,
transformArguments(key: RedisArgument) {
return ['TDIGEST.MAX', key];
},
transformReply: transformDoubleReply
} as const satisfies Command;

View File

@@ -1,50 +1,50 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../../test-utils';
import { transformArguments, transformReply } from './MERGE';
import MERGE from './MERGE';
describe('TDIGEST.MERGE', () => {
describe('transformArguments', () => {
describe('srcKeys', () => {
it('string', () => {
assert.deepEqual(
transformArguments('dest', 'src'),
['TDIGEST.MERGE', 'dest', '1', 'src']
);
});
describe('transformArguments', () => {
describe('source', () => {
it('string', () => {
assert.deepEqual(
MERGE.transformArguments('destination', 'source'),
['TDIGEST.MERGE', 'destination', '1', 'source']
);
});
it('Array', () => {
assert.deepEqual(
transformArguments('dest', ['1', '2']),
['TDIGEST.MERGE', 'dest', '2', '1', '2']
);
});
});
it('with COMPRESSION', () => {
assert.deepEqual(
transformArguments('dest', 'src', {
COMPRESSION: 100
}),
['TDIGEST.MERGE', 'dest', '1', 'src', 'COMPRESSION', '100']
);
});
it('with OVERRIDE', () => {
assert.deepEqual(
transformArguments('dest', 'src', {
OVERRIDE: true
}),
['TDIGEST.MERGE', 'dest', '1', 'src', 'OVERRIDE']
);
});
it('Array', () => {
assert.deepEqual(
MERGE.transformArguments('destination', ['1', '2']),
['TDIGEST.MERGE', 'destination', '2', '1', '2']
);
});
});
testUtils.testWithClient('client.tDigest.merge', async client => {
const [ , reply ] = await Promise.all([
client.tDigest.create('src'),
client.tDigest.merge('dest', 'src')
]);
it('with COMPRESSION', () => {
assert.deepEqual(
MERGE.transformArguments('destination', 'source', {
COMPRESSION: 100
}),
['TDIGEST.MERGE', 'destination', '1', 'source', 'COMPRESSION', '100']
);
});
assert.equal(reply, 'OK');
}, GLOBAL.SERVERS.OPEN);
it('with OVERRIDE', () => {
assert.deepEqual(
MERGE.transformArguments('destination', 'source', {
OVERRIDE: true
}),
['TDIGEST.MERGE', 'destination', '1', 'source', 'OVERRIDE']
);
});
});
testUtils.testWithClient('client.tDigest.merge', async client => {
const [, reply] = await Promise.all([
client.tDigest.create('source'),
client.tDigest.merge('destination', 'source')
]);
assert.equal(reply, 'OK');
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,30 +1,30 @@
import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands';
import { pushVerdictArgument } from '@redis/client/dist/lib/commands/generic-transformers';
import { CompressionOption, pushCompressionArgument } from '.';
import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types';
import { RedisVariadicArgument, pushVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers';
export const FIRST_KEY_INDEX = 1;
interface MergeOptions extends CompressionOption {
OVERRIDE?: boolean;
export interface TDigestMergeOptions {
COMPRESSION?: number;
OVERRIDE?: boolean;
}
export function transformArguments(
destKey: RedisCommandArgument,
srcKeys: RedisCommandArgument | Array<RedisCommandArgument>,
options?: MergeOptions
): RedisCommandArguments {
const args = pushVerdictArgument(
['TDIGEST.MERGE', destKey],
srcKeys
);
export default {
FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: false,
transformArguments(
destination: RedisArgument,
source: RedisVariadicArgument,
options?: TDigestMergeOptions
) {
const args = pushVariadicArgument(['TDIGEST.MERGE', destination], source);
pushCompressionArgument(args, options);
if (options?.COMPRESSION !== undefined) {
args.push('COMPRESSION', options.COMPRESSION.toString());
}
if (options?.OVERRIDE) {
args.push('OVERRIDE');
args.push('OVERRIDE');
}
return args;
}
export declare function transformReply(): 'OK';
},
transformReply: undefined as unknown as () => SimpleStringReply<'OK'>
} as const satisfies Command;

View File

@@ -1,21 +1,21 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../../test-utils';
import { transformArguments, transformReply } from './MIN';
import MIN from './MIN';
describe('TDIGEST.MIN', () => {
it('transformArguments', () => {
assert.deepEqual(
transformArguments('key'),
['TDIGEST.MIN', 'key']
);
});
it('transformArguments', () => {
assert.deepEqual(
MIN.transformArguments('key'),
['TDIGEST.MIN', 'key']
);
});
testUtils.testWithClient('client.tDigest.min', async client => {
const [ , reply ] = await Promise.all([
client.tDigest.create('key'),
client.tDigest.min('key')
]);
testUtils.testWithClient('client.tDigest.min', async client => {
const [, reply] = await Promise.all([
client.tDigest.create('key'),
client.tDigest.min('key')
]);
assert.equal(reply, NaN);
}, GLOBAL.SERVERS.OPEN);
assert.equal(reply, NaN);
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,14 +1,11 @@
import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands';
import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types';
import { transformDoubleReply } from '@redis/client/dist/lib/commands/generic-transformers';
export const FIRST_KEY_INDEX = 1;
export const IS_READ_ONLY = true;
export function transformArguments(key: RedisCommandArgument): RedisCommandArguments {
return [
'TDIGEST.MIN',
key
];
}
export { transformDoubleReply as transformReply } from '.';
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: true,
transformArguments(key: RedisArgument) {
return ['TDIGEST.MIN', key];
},
transformReply: transformDoubleReply
} as const satisfies Command;

View File

@@ -1,24 +1,24 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../../test-utils';
import { transformArguments } from './QUANTILE';
import QUANTILE from './QUANTILE';
describe('TDIGEST.QUANTILE', () => {
it('transformArguments', () => {
assert.deepEqual(
transformArguments('key', [1, 2]),
['TDIGEST.QUANTILE', 'key', '1', '2']
);
});
it('transformArguments', () => {
assert.deepEqual(
QUANTILE.transformArguments('key', [1, 2]),
['TDIGEST.QUANTILE', 'key', '1', '2']
);
});
testUtils.testWithClient('client.tDigest.quantile', async client => {
const [, reply] = await Promise.all([
client.tDigest.create('key'),
client.tDigest.quantile('key', [1])
]);
testUtils.testWithClient('client.tDigest.quantile', async client => {
const [, reply] = await Promise.all([
client.tDigest.create('key'),
client.tDigest.quantile('key', [1])
]);
assert.deepEqual(
reply,
[NaN]
);
}, GLOBAL.SERVERS.OPEN);
assert.deepEqual(
reply,
[NaN]
);
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,23 +1,17 @@
import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands';
import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types';
import { transformDoubleArrayReply } from '@redis/client/dist/lib/commands/generic-transformers';
export const FIRST_KEY_INDEX = 1;
export const IS_READ_ONLY = true;
export function transformArguments(
key: RedisCommandArgument,
quantiles: Array<number>
): RedisCommandArguments {
const args = [
'TDIGEST.QUANTILE',
key
];
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: true,
transformArguments(key: RedisArgument, quantiles: Array<number>) {
const args = ['TDIGEST.QUANTILE', key];
for (const quantile of quantiles) {
args.push(quantile.toString());
args.push(quantile.toString());
}
return args;
}
export { transformDoublesReply as transformReply } from '.';
},
transformReply: transformDoubleArrayReply
} as const satisfies Command;

View File

@@ -1,21 +1,21 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../../test-utils';
import { transformArguments } from './RANK';
import RANK from './RANK';
describe('TDIGEST.RANK', () => {
it('transformArguments', () => {
assert.deepEqual(
transformArguments('key', [1, 2]),
['TDIGEST.RANK', 'key', '1', '2']
);
});
it('transformArguments', () => {
assert.deepEqual(
RANK.transformArguments('key', [1, 2]),
['TDIGEST.RANK', 'key', '1', '2']
);
});
testUtils.testWithClient('client.tDigest.rank', async client => {
const [ , reply ] = await Promise.all([
client.tDigest.create('key'),
client.tDigest.rank('key', [1])
]);
testUtils.testWithClient('client.tDigest.rank', async client => {
const [, reply] = await Promise.all([
client.tDigest.create('key'),
client.tDigest.rank('key', [1])
]);
assert.deepEqual(reply, [-2]);
}, GLOBAL.SERVERS.OPEN);
assert.deepEqual(reply, [-2]);
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,19 +1,22 @@
import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands';
import { RedisArgument, ArrayReply, NumberReply, Command } from '@redis/client/dist/lib/RESP/types';
export const FIRST_KEY_INDEX = 1;
export function transformRankArguments(
command: RedisArgument,
key: RedisArgument,
values: Array<number>
) {
const args = [command, key];
export const IS_READ_ONLY = true;
for (const value of values) {
args.push(value.toString());
}
export function transformArguments(
key: RedisCommandArgument,
values: Array<number>
): RedisCommandArguments {
const args = ['TDIGEST.RANK', key];
for (const item of values) {
args.push(item.toString());
}
return args;
return args;
}
export declare function transformReply(): Array<number>;
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: true,
transformArguments: transformRankArguments.bind(undefined, 'TDIGEST.RANK'),
transformReply: undefined as unknown as () => ArrayReply<NumberReply>
} as const satisfies Command;

View File

@@ -1,21 +1,21 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../../test-utils';
import { transformArguments } from './RESET';
import RESET from './RESET';
describe('TDIGEST.RESET', () => {
it('transformArguments', () => {
assert.deepEqual(
transformArguments('key'),
['TDIGEST.RESET', 'key']
);
});
it('transformArguments', () => {
assert.deepEqual(
RESET.transformArguments('key'),
['TDIGEST.RESET', 'key']
);
});
testUtils.testWithClient('client.tDigest.reset', async client => {
const [, reply] = await Promise.all([
client.tDigest.create('key'),
client.tDigest.reset('key')
]);
testUtils.testWithClient('client.tDigest.reset', async client => {
const [, reply] = await Promise.all([
client.tDigest.create('key'),
client.tDigest.reset('key')
]);
assert.equal(reply, 'OK');
}, GLOBAL.SERVERS.OPEN);
assert.equal(reply, 'OK');
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,9 +1,10 @@
import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands';
import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types';
export const FIRST_KEY_INDEX = 1;
export function transformArguments(key: RedisCommandArgument): RedisCommandArguments {
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: false,
transformArguments(key: RedisArgument) {
return ['TDIGEST.RESET', key];
}
export declare function transformReply(): 'OK';
},
transformReply: undefined as unknown as () => SimpleStringReply<'OK'>
} as const satisfies Command;

View File

@@ -1,21 +1,21 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../../test-utils';
import { transformArguments } from './REVRANK';
import REVRANK from './REVRANK';
describe('TDIGEST.REVRANK', () => {
it('transformArguments', () => {
assert.deepEqual(
transformArguments('key', [1, 2]),
['TDIGEST.REVRANK', 'key', '1', '2']
);
});
it('transformArguments', () => {
assert.deepEqual(
REVRANK.transformArguments('key', [1, 2]),
['TDIGEST.REVRANK', 'key', '1', '2']
);
});
testUtils.testWithClient('client.tDigest.revRank', async client => {
const [ , reply ] = await Promise.all([
client.tDigest.create('key'),
client.tDigest.revRank('key', [1])
]);
testUtils.testWithClient('client.tDigest.revRank', async client => {
const [, reply] = await Promise.all([
client.tDigest.create('key'),
client.tDigest.revRank('key', [1])
]);
assert.deepEqual(reply, [-2]);
}, GLOBAL.SERVERS.OPEN);
assert.deepEqual(reply, [-2]);
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,19 +1,9 @@
import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands';
import { Command } from '@redis/client/dist/lib/RESP/types';
import RANK, { transformRankArguments } from './RANK';
export const FIRST_KEY_INDEX = 1;
export const IS_READ_ONLY = true;
export function transformArguments(
key: RedisCommandArgument,
values: Array<number>
): RedisCommandArguments {
const args = ['TDIGEST.REVRANK', key];
for (const item of values) {
args.push(item.toString());
}
return args;
}
export declare function transformReply(): Array<number>;
export default {
FIRST_KEY_INDEX: RANK.FIRST_KEY_INDEX,
IS_READ_ONLY: RANK.IS_READ_ONLY,
transformArguments: transformRankArguments.bind(undefined, 'TDIGEST.REVRANK'),
transformReply: RANK.transformReply
} as const satisfies Command;

View File

@@ -1,21 +1,21 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../../test-utils';
import { transformArguments, transformReply } from './TRIMMED_MEAN';
import TRIMMED_MEAN from './TRIMMED_MEAN';
describe('TDIGEST.RESET', () => {
it('transformArguments', () => {
assert.deepEqual(
transformArguments('key', 0, 1),
['TDIGEST.TRIMMED_MEAN', 'key', '0', '1']
);
});
describe('TDIGEST.TRIMMED_MEAN', () => {
it('transformArguments', () => {
assert.deepEqual(
TRIMMED_MEAN.transformArguments('key', 0, 1),
['TDIGEST.TRIMMED_MEAN', 'key', '0', '1']
);
});
testUtils.testWithClient('client.tDigest.trimmedMean', async client => {
const [, reply] = await Promise.all([
client.tDigest.create('key'),
client.tDigest.trimmedMean('key', 0, 1)
]);
testUtils.testWithClient('client.tDigest.trimmedMean', async client => {
const [, reply] = await Promise.all([
client.tDigest.create('key'),
client.tDigest.trimmedMean('key', 0, 1)
]);
assert.equal(reply, NaN);
}, GLOBAL.SERVERS.OPEN);
assert.equal(reply, NaN);
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,20 +1,20 @@
import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands';
import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types';
import { transformDoubleReply } from '@redis/client/dist/lib/commands/generic-transformers';
export const FIRST_KEY_INDEX = 1;
export const IS_READ_ONLY = true;
export function transformArguments(
key: RedisCommandArgument,
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: true,
transformArguments(
key: RedisArgument,
lowCutPercentile: number,
highCutPercentile: number
): RedisCommandArguments {
) {
return [
'TDIGEST.TRIMMED_MEAN',
key,
lowCutPercentile.toString(),
highCutPercentile.toString()
'TDIGEST.TRIMMED_MEAN',
key,
lowCutPercentile.toString(),
highCutPercentile.toString()
];
}
export { transformDoubleReply as transformReply } from '.';
},
transformReply: transformDoubleReply
} as const satisfies Command;

View File

@@ -1,55 +0,0 @@
import { strict as assert } from 'assert';
import { pushCompressionArgument, transformDoubleReply, transformDoublesReply } from '.';
describe('pushCompressionArgument', () => {
it('undefined', () => {
assert.deepEqual(
pushCompressionArgument([]),
[]
);
});
it('100', () => {
assert.deepEqual(
pushCompressionArgument([], { COMPRESSION: 100 }),
['COMPRESSION', '100']
);
});
});
describe('transformDoubleReply', () => {
it('inf', () => {
assert.equal(
transformDoubleReply('inf'),
Infinity
);
});
it('-inf', () => {
assert.equal(
transformDoubleReply('-inf'),
-Infinity
);
});
it('nan', () => {
assert.equal(
transformDoubleReply('nan'),
NaN
);
});
it('0', () => {
assert.equal(
transformDoubleReply('0'),
0
);
});
});
it('transformDoublesReply', () => {
assert.deepEqual(
transformDoublesReply(['inf', '-inf', 'nan', '0']),
[Infinity, -Infinity, NaN, 0]
);
});

View File

@@ -1,81 +1,46 @@
import { RedisCommandArguments } from '@redis/client/dist/lib/commands';
import * as ADD from './ADD';
import * as BYRANK from './BYRANK';
import * as BYREVRANK from './BYREVRANK';
import * as CDF from './CDF';
import * as CREATE from './CREATE';
import * as INFO from './INFO';
import * as MAX from './MAX';
import * as MERGE from './MERGE';
import * as MIN from './MIN';
import * as QUANTILE from './QUANTILE';
import * as RANK from './RANK';
import * as RESET from './RESET';
import * as REVRANK from './REVRANK';
import * as TRIMMED_MEAN from './TRIMMED_MEAN';
import type { RedisCommands } from '@redis/client/dist/lib/RESP/types';
import ADD from './ADD';
import BYRANK from './BYRANK';
import BYREVRANK from './BYREVRANK';
import CDF from './CDF';
import CREATE from './CREATE';
import INFO from './INFO';
import MAX from './MAX';
import MERGE from './MERGE';
import MIN from './MIN';
import QUANTILE from './QUANTILE';
import RANK from './RANK';
import RESET from './RESET';
import REVRANK from './REVRANK';
import TRIMMED_MEAN from './TRIMMED_MEAN';
export default {
ADD,
add: ADD,
BYRANK,
byRank: BYRANK,
BYREVRANK,
byRevRank: BYREVRANK,
CDF,
cdf: CDF,
CREATE,
create: CREATE,
INFO,
info: INFO,
MAX,
max: MAX,
MERGE,
merge: MERGE,
MIN,
min: MIN,
QUANTILE,
quantile: QUANTILE,
RANK,
rank: RANK,
RESET,
reset: RESET,
REVRANK,
revRank: REVRANK,
TRIMMED_MEAN,
trimmedMean: TRIMMED_MEAN
};
export interface CompressionOption {
COMPRESSION?: number;
}
export function pushCompressionArgument(
args: RedisCommandArguments,
options?: CompressionOption
): RedisCommandArguments {
if (options?.COMPRESSION) {
args.push('COMPRESSION', options.COMPRESSION.toString());
}
return args;
}
export function transformDoubleReply(reply: string): number {
switch (reply) {
case 'inf':
return Infinity;
case '-inf':
return -Infinity;
case 'nan':
return NaN;
default:
return parseFloat(reply);
}
}
export function transformDoublesReply(reply: Array<string>): Array<number> {
return reply.map(transformDoubleReply);
}
ADD,
add: ADD,
BYRANK,
byRank: BYRANK,
BYREVRANK,
byRevRank: BYREVRANK,
CDF,
cdf: CDF,
CREATE,
create: CREATE,
INFO,
info: INFO,
MAX,
max: MAX,
MERGE,
merge: MERGE,
MIN,
min: MIN,
QUANTILE,
quantile: QUANTILE,
RANK,
rank: RANK,
RESET,
reset: RESET,
REVRANK,
revRank: REVRANK,
TRIMMED_MEAN,
trimmedMean: TRIMMED_MEAN
} as const satisfies RedisCommands;

View File

@@ -1,22 +1,21 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../../test-utils';
import { transformArguments } from './ADD';
import ADD from './ADD';
describe('TOPK ADD', () => {
it('transformArguments', () => {
assert.deepEqual(
transformArguments('key', 'item'),
['TOPK.ADD', 'key', 'item']
);
});
describe('TOPK.ADD', () => {
it('transformArguments', () => {
assert.deepEqual(
ADD.transformArguments('key', 'item'),
['TOPK.ADD', 'key', 'item']
);
});
testUtils.testWithClient('client.topK.add', async client => {
await client.topK.reserve('topK', 3);
testUtils.testWithClient('client.topK.add', async client => {
const [, reply] = await Promise.all([
client.topK.reserve('topK', 3),
client.topK.add('topK', 'item')
]);
assert.deepEqual(
await client.topK.add('topK', 'item'),
[null]
);
}, GLOBAL.SERVERS.OPEN);
assert.deepEqual(reply, [null]);
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,13 +1,11 @@
import { RedisCommandArguments } from '@redis/client/dist/lib/commands';
import { pushVerdictArguments } from '@redis/client/dist/lib/commands/generic-transformers';
import { RedisArgument, ArrayReply, BlobStringReply, Command } from '@redis/client/dist/lib/RESP/types';
import { RedisVariadicArgument, pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers';
export const FIRST_KEY_INDEX = 1;
export function transformArguments(
key: string,
items: string | Array<string>
): RedisCommandArguments {
return pushVerdictArguments(['TOPK.ADD', key], items);
}
export declare function transformReply(): Array<null | string>;
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: false,
transformArguments(key: RedisArgument, items: RedisVariadicArgument) {
return pushVariadicArguments(['TOPK.ADD', key], items);
},
transformReply: undefined as unknown as () => ArrayReply<BlobStringReply>
} as const satisfies Command;

View File

@@ -1,21 +1,21 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../../test-utils';
import { transformArguments } from './COUNT';
import COUNT from './COUNT';
describe('TOPK COUNT', () => {
it('transformArguments', () => {
assert.deepEqual(
transformArguments('key', 'item'),
['TOPK.COUNT', 'key', 'item']
);
});
describe('TOPK.COUNT', () => {
it('transformArguments', () => {
assert.deepEqual(
COUNT.transformArguments('key', 'item'),
['TOPK.COUNT', 'key', 'item']
);
});
testUtils.testWithClient('client.topK.count', async client => {
await client.topK.reserve('key', 3);
testUtils.testWithClient('client.topK.count', async client => {
const [, reply] = await Promise.all([
client.topK.reserve('key', 3),
client.topK.count('key', 'item')
]);
assert.deepEqual(
await client.topK.count('key', 'item'),
[0]
);
}, GLOBAL.SERVERS.OPEN);
assert.deepEqual(reply, [0]);
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,15 +1,11 @@
import { RedisCommandArguments } from '@redis/client/dist/lib/commands';
import { pushVerdictArguments } from '@redis/client/dist/lib/commands/generic-transformers';
import { RedisArgument, ArrayReply, NumberReply, Command } from '@redis/client/dist/lib/RESP/types';
import { RedisVariadicArgument, pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers';
export const FIRST_KEY_INDEX = 1;
export const IS_READ_ONLY = true;
export function transformArguments(
key: string,
items: string | Array<string>
): RedisCommandArguments {
return pushVerdictArguments(['TOPK.COUNT', key], items);
}
export declare function transformReply(): Array<number>;
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: true,
transformArguments(key: RedisArgument, items: RedisVariadicArgument) {
return pushVariadicArguments(['TOPK.COUNT', key], items);
},
transformReply: undefined as unknown as () => ArrayReply<NumberReply>
} as const satisfies Command;

View File

@@ -1,42 +1,42 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../../test-utils';
import { transformArguments } from './INCRBY';
import INCRBY from './INCRBY';
describe('TOPK INCRBY', () => {
describe('transformArguments', () => {
it('single item', () => {
assert.deepEqual(
transformArguments('key', {
item: 'item',
incrementBy: 1
}),
['TOPK.INCRBY', 'key', 'item', '1']
);
});
it('multiple items', () => {
assert.deepEqual(
transformArguments('key', [{
item: 'a',
incrementBy: 1
}, {
item: 'b',
incrementBy: 2
}]),
['TOPK.INCRBY', 'key', 'a', '1', 'b', '2']
);
});
describe('TOPK.INCRBY', () => {
describe('transformArguments', () => {
it('single item', () => {
assert.deepEqual(
INCRBY.transformArguments('key', {
item: 'item',
incrementBy: 1
}),
['TOPK.INCRBY', 'key', 'item', '1']
);
});
testUtils.testWithClient('client.topK.incrby', async client => {
await client.topK.reserve('key', 5);
it('multiple items', () => {
assert.deepEqual(
INCRBY.transformArguments('key', [{
item: 'a',
incrementBy: 1
}, {
item: 'b',
incrementBy: 2
}]),
['TOPK.INCRBY', 'key', 'a', '1', 'b', '2']
);
});
});
assert.deepEqual(
await client.topK.incrBy('key', {
item: 'item',
incrementBy: 1
}),
[null]
);
}, GLOBAL.SERVERS.OPEN);
testUtils.testWithClient('client.topK.incrby', async client => {
const [, reply] = await Promise.all([
client.topK.reserve('key', 5),
client.topK.incrBy('key', {
item: 'item',
incrementBy: 1
})
]);
assert.deepEqual(reply, [null]);
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,29 +1,32 @@
export const FIRST_KEY_INDEX = 1;
import { RedisArgument, ArrayReply, SimpleStringReply, NullReply, Command } from '@redis/client/dist/lib/RESP/types';
interface IncrByItem {
item: string;
incrementBy: number;
export interface TopKIncrByItem {
item: string;
incrementBy: number;
}
export function transformArguments(
key: string,
items: IncrByItem | Array<IncrByItem>
): Array<string> {
function pushIncrByItem(args: Array<RedisArgument>, { item, incrementBy }: TopKIncrByItem) {
args.push(item, incrementBy.toString());
}
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: false,
transformArguments(
key: RedisArgument,
items: TopKIncrByItem | Array<TopKIncrByItem>
) {
const args = ['TOPK.INCRBY', key];
if (Array.isArray(items)) {
for (const item of items) {
pushIncrByItem(args, item);
}
for (const item of items) {
pushIncrByItem(args, item);
}
} else {
pushIncrByItem(args, items);
pushIncrByItem(args, items);
}
return args;
}
function pushIncrByItem(args: Array<string>, { item, incrementBy }: IncrByItem): void {
args.push(item, incrementBy.toString());
}
export declare function transformReply(): Array<string | null>;
},
transformReply: undefined as unknown as () => ArrayReply<SimpleStringReply | NullReply>
} as const satisfies Command;

View File

@@ -1,23 +1,26 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../../test-utils';
import { transformArguments } from './INFO';
import INFO from './INFO';
describe('TOPK INFO', () => {
it('transformArguments', () => {
assert.deepEqual(
transformArguments('key'),
['TOPK.INFO', 'key']
);
});
it('transformArguments', () => {
assert.deepEqual(
INFO.transformArguments('key'),
['TOPK.INFO', 'key']
);
});
testUtils.testWithClient('client.topK.info', async client => {
await client.topK.reserve('key', 3);
testUtils.testWithClient('client.topK.info', async client => {
const k = 3,
[, reply] = await Promise.all([
client.topK.reserve('key', 3),
client.topK.info('key')
]);
const info = await client.topK.info('key');
assert.equal(typeof info, 'object');
assert.equal(info.k, 3);
assert.equal(typeof info.width, 'number');
assert.equal(typeof info.depth, 'number');
assert.equal(typeof info.decay, 'number');
}, GLOBAL.SERVERS.OPEN);
assert.equal(typeof reply, 'object');
assert.equal(reply.k, k);
assert.equal(typeof reply.width, 'number');
assert.equal(typeof reply.depth, 'number');
assert.equal(typeof reply.decay, 'number');
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,34 +1,26 @@
export const FIRST_KEY_INDEX = 1;
import { transformDoubleReply } from '@redis/client/dist/lib/commands/generic-transformers';
import { RedisArgument, TuplesToMapReply, NumberReply, DoubleReply, UnwrapReply, Resp2Reply, Command, SimpleStringReply, TypeMapping } from '@redis/client/dist/lib/RESP/types';
import { transformInfoV2Reply } from '../bloom';
export const IS_READ_ONLY = true;
export type TopKInfoReplyMap = TuplesToMapReply<[
[SimpleStringReply<'k'>, NumberReply],
[SimpleStringReply<'width'>, NumberReply],
[SimpleStringReply<'depth'>, NumberReply],
[SimpleStringReply<'decay'>, DoubleReply]
]>;
export function transformArguments(key: string): Array<string> {
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: true,
transformArguments(key: RedisArgument) {
return ['TOPK.INFO', key];
}
},
transformReply: {
2: (reply: UnwrapReply<Resp2Reply<TopKInfoReplyMap>>, preserve?: any, typeMapping?: TypeMapping): TopKInfoReplyMap => {
reply[7] = transformDoubleReply[2](reply[7], preserve, typeMapping) as any;
export type InfoRawReply = [
_: string,
k: number,
_: string,
width: number,
_: string,
depth: number,
_: string,
decay: string
];
export interface InfoReply {
k: number,
width: number;
depth: number;
decay: number;
}
export function transformReply(reply: InfoRawReply): InfoReply {
return {
k: reply[1],
width: reply[3],
depth: reply[5],
decay: Number(reply[7])
};
}
return transformInfoV2Reply<TopKInfoReplyMap>(reply, typeMapping);
},
3: undefined as unknown as () => TopKInfoReplyMap
}
} as const satisfies Command

View File

@@ -1,21 +1,21 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../../test-utils';
import { transformArguments } from './LIST';
import LIST from './LIST';
describe('TOPK LIST', () => {
it('transformArguments', () => {
assert.deepEqual(
transformArguments('key'),
['TOPK.LIST', 'key']
);
});
describe('TOPK.LIST', () => {
it('transformArguments', () => {
assert.deepEqual(
LIST.transformArguments('key'),
['TOPK.LIST', 'key']
);
});
testUtils.testWithClient('client.topK.list', async client => {
await client.topK.reserve('key', 3);
testUtils.testWithClient('client.topK.list', async client => {
const [, reply] = await Promise.all([
client.topK.reserve('key', 3),
client.topK.list('key')
]);
assert.deepEqual(
await client.topK.list('key'),
[]
);
}, GLOBAL.SERVERS.OPEN);
assert.deepEqual(reply, []);
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,9 +1,10 @@
export const FIRST_KEY_INDEX = 1;
import { RedisArgument, ArrayReply, BlobStringReply, Command } from '@redis/client/dist/lib/RESP/types';
export const IS_READ_ONLY = true;
export function transformArguments(key: string): Array<string> {
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: true,
transformArguments(key: RedisArgument) {
return ['TOPK.LIST', key];
}
export declare function transformReply(): Array<string | null>;
},
transformReply: undefined as unknown as () => ArrayReply<BlobStringReply>
} as const satisfies Command;

View File

@@ -1,30 +1,27 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../../test-utils';
import { transformArguments } from './LIST_WITHCOUNT';
import LIST_WITHCOUNT from './LIST_WITHCOUNT';
describe('TOPK LIST WITHCOUNT', () => {
testUtils.isVersionGreaterThanHook([2, 2, 9]);
it('transformArguments', () => {
assert.deepEqual(
transformArguments('key'),
['TOPK.LIST', 'key', 'WITHCOUNT']
);
});
describe('TOPK.LIST WITHCOUNT', () => {
testUtils.isVersionGreaterThanHook([2, 2, 9]);
testUtils.testWithClient('client.topK.listWithCount', async client => {
const [,, list] = await Promise.all([
client.topK.reserve('key', 3),
client.topK.add('key', 'item'),
client.topK.listWithCount('key')
]);
it('transformArguments', () => {
assert.deepEqual(
LIST_WITHCOUNT.transformArguments('key'),
['TOPK.LIST', 'key', 'WITHCOUNT']
);
});
assert.deepEqual(
list,
[{
item: 'item',
count: 1
}]
);
}, GLOBAL.SERVERS.OPEN);
testUtils.testWithClient('client.topK.listWithCount', async client => {
const [, , list] = await Promise.all([
client.topK.reserve('key', 3),
client.topK.add('key', 'item'),
client.topK.listWithCount('key')
]);
assert.deepEqual(list, [{
item: 'item',
count: 1
}]);
}, GLOBAL.SERVERS.OPEN);
});

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