You've already forked node-redis
mirror of
https://github.com/redis/node-redis.git
synced 2025-08-04 15:02:09 +03:00
fix: fix various command import issues (#2944)
* fix: fix various command import issues there was some sort of a circular dependency in <module>/lib/commands/index.ts for various modules fixes #2937 fixes #2941 * remove redundant definition
This commit is contained in:
committed by
GitHub
parent
bc4b2101ee
commit
7b737821b2
@@ -1,6 +1,6 @@
|
|||||||
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
||||||
import { RedisArgument, Command, UnwrapReply, NullReply, NumberReply, TuplesToMapReply, Resp2Reply, SimpleStringReply, TypeMapping } from '@redis/client/dist/lib/RESP/types';
|
import { RedisArgument, Command, UnwrapReply, NullReply, NumberReply, TuplesToMapReply, Resp2Reply, SimpleStringReply, TypeMapping } from '@redis/client/dist/lib/RESP/types';
|
||||||
import { transformInfoV2Reply } from '.';
|
import { transformInfoV2Reply } from './helpers';
|
||||||
|
|
||||||
export type BfInfoReplyMap = TuplesToMapReply<[
|
export type BfInfoReplyMap = TuplesToMapReply<[
|
||||||
[SimpleStringReply<'Capacity'>, NumberReply],
|
[SimpleStringReply<'Capacity'>, NumberReply],
|
||||||
|
29
packages/bloom/lib/commands/bloom/helpers.ts
Normal file
29
packages/bloom/lib/commands/bloom/helpers.ts
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import { RESP_TYPES, TypeMapping } from "@redis/client";
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -1,4 +1,4 @@
|
|||||||
import type { RedisCommands, TypeMapping } from '@redis/client/dist/lib/RESP/types';
|
import type { RedisCommands } from '@redis/client/dist/lib/RESP/types';
|
||||||
|
|
||||||
import ADD from './ADD';
|
import ADD from './ADD';
|
||||||
import CARD from './CARD';
|
import CARD from './CARD';
|
||||||
@@ -10,7 +10,8 @@ import MADD from './MADD';
|
|||||||
import MEXISTS from './MEXISTS';
|
import MEXISTS from './MEXISTS';
|
||||||
import RESERVE from './RESERVE';
|
import RESERVE from './RESERVE';
|
||||||
import SCANDUMP from './SCANDUMP';
|
import SCANDUMP from './SCANDUMP';
|
||||||
import { RESP_TYPES } from '@redis/client';
|
|
||||||
|
export * from './helpers';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
ADD,
|
ADD,
|
||||||
@@ -34,31 +35,3 @@ export default {
|
|||||||
SCANDUMP,
|
SCANDUMP,
|
||||||
scanDump: SCANDUMP
|
scanDump: SCANDUMP
|
||||||
} as const satisfies RedisCommands;
|
} 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -704,7 +704,8 @@ export default class RedisClient<
|
|||||||
const reply = await this.sendCommand(parser.redisArgs, commandOptions);
|
const reply = await this.sendCommand(parser.redisArgs, commandOptions);
|
||||||
|
|
||||||
if (transformReply) {
|
if (transformReply) {
|
||||||
return transformReply(reply, parser.preserve, commandOptions?.typeMapping);
|
const res = transformReply(reply, parser.preserve, commandOptions?.typeMapping);
|
||||||
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
return reply;
|
return reply;
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
||||||
import { RedisJSON, transformRedisJsonArgument } from '.';
|
import { RedisJSON, transformRedisJsonArgument } from './helpers';
|
||||||
import { RedisArgument, NumberReply, ArrayReply, NullReply, Command } from '@redis/client/dist/lib/RESP/types';
|
import { RedisArgument, NumberReply, ArrayReply, NullReply, Command } from '@redis/client/dist/lib/RESP/types';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
||||||
import { RedisArgument, NumberReply, ArrayReply, NullReply, Command } from '@redis/client/dist/lib/RESP/types';
|
import { RedisArgument, NumberReply, ArrayReply, NullReply, Command } from '@redis/client/dist/lib/RESP/types';
|
||||||
import { RedisJSON, transformRedisJsonArgument } from '.';
|
import { RedisJSON, transformRedisJsonArgument } from './helpers';
|
||||||
|
|
||||||
export interface JsonArrIndexOptions {
|
export interface JsonArrIndexOptions {
|
||||||
range?: {
|
range?: {
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
||||||
import { RedisArgument, NumberReply, ArrayReply, NullReply, Command } from '@redis/client/dist/lib/RESP/types';
|
import { RedisArgument, NumberReply, ArrayReply, NullReply, Command } from '@redis/client/dist/lib/RESP/types';
|
||||||
import { RedisJSON, transformRedisJsonArgument } from '.';
|
import { RedisJSON, transformRedisJsonArgument } from './helpers';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
IS_READ_ONLY: false,
|
IS_READ_ONLY: false,
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
||||||
import { RedisArgument, ArrayReply, NullReply, BlobStringReply, Command, UnwrapReply } from '@redis/client/dist/lib/RESP/types';
|
import { RedisArgument, ArrayReply, NullReply, BlobStringReply, Command, UnwrapReply } from '@redis/client/dist/lib/RESP/types';
|
||||||
import { isArrayReply } from '@redis/client/dist/lib/commands/generic-transformers';
|
import { isArrayReply } from '@redis/client/dist/lib/commands/generic-transformers';
|
||||||
import { transformRedisJsonNullReply } from '.';
|
import { transformRedisJsonNullReply } from './helpers';
|
||||||
|
|
||||||
export interface RedisArrPopOptions {
|
export interface RedisArrPopOptions {
|
||||||
path: RedisArgument;
|
path: RedisArgument;
|
||||||
|
@@ -34,5 +34,11 @@ describe('JSON.GET', () => {
|
|||||||
await client.json.get('key'),
|
await client.json.get('key'),
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
|
|
||||||
|
await client.json.set('noderedis:users:1', '$', { name: 'Alice', age: 32, })
|
||||||
|
const res = await client.json.get('noderedis:users:1');
|
||||||
|
assert.equal(typeof res, 'object')
|
||||||
|
assert.deepEqual(res, { name: 'Alice', age: 32, })
|
||||||
|
|
||||||
}, GLOBAL.SERVERS.OPEN);
|
}, GLOBAL.SERVERS.OPEN);
|
||||||
});
|
});
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
||||||
import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types';
|
import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types';
|
||||||
import { RedisVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers';
|
import { RedisVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers';
|
||||||
import { transformRedisJsonNullReply } from '.';
|
import { transformRedisJsonNullReply } from './helpers';
|
||||||
|
|
||||||
export interface JsonGetOptions {
|
export interface JsonGetOptions {
|
||||||
path?: RedisVariadicArgument;
|
path?: RedisVariadicArgument;
|
||||||
@@ -9,12 +9,16 @@ export interface JsonGetOptions {
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
IS_READ_ONLY: false,
|
IS_READ_ONLY: false,
|
||||||
parseCommand(parser: CommandParser, key: RedisArgument, options?: JsonGetOptions) {
|
parseCommand(
|
||||||
|
parser: CommandParser,
|
||||||
|
key: RedisArgument,
|
||||||
|
options?: JsonGetOptions
|
||||||
|
) {
|
||||||
parser.push('JSON.GET');
|
parser.push('JSON.GET');
|
||||||
parser.pushKey(key);
|
parser.pushKey(key);
|
||||||
if (options?.path !== undefined) {
|
if (options?.path !== undefined) {
|
||||||
parser.pushVariadic(options.path)
|
parser.pushVariadic(options.path);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
transformReply: transformRedisJsonNullReply
|
transformReply: transformRedisJsonNullReply
|
||||||
} as const satisfies Command;
|
} as const satisfies Command;
|
@@ -1,6 +1,6 @@
|
|||||||
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
||||||
import { SimpleStringReply, Command, RedisArgument } from '@redis/client/dist/lib/RESP/types';
|
import { SimpleStringReply, Command, RedisArgument } from '@redis/client/dist/lib/RESP/types';
|
||||||
import { RedisJSON, transformRedisJsonArgument } from '.';
|
import { RedisJSON, transformRedisJsonArgument } from './helpers';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
IS_READ_ONLY: false,
|
IS_READ_ONLY: false,
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
||||||
import { RedisArgument, UnwrapReply, ArrayReply, NullReply, BlobStringReply, Command } from '@redis/client/dist/lib/RESP/types';
|
import { RedisArgument, UnwrapReply, ArrayReply, NullReply, BlobStringReply, Command } from '@redis/client/dist/lib/RESP/types';
|
||||||
import { transformRedisJsonNullReply } from '.';
|
import { transformRedisJsonNullReply } from './helpers';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
IS_READ_ONLY: true,
|
IS_READ_ONLY: true,
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
||||||
import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types';
|
import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types';
|
||||||
import { RedisJSON, transformRedisJsonArgument } from '.';
|
import { RedisJSON, transformRedisJsonArgument } from './helpers';
|
||||||
|
|
||||||
export interface JsonMSetItem {
|
export interface JsonMSetItem {
|
||||||
key: RedisArgument;
|
key: RedisArgument;
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
||||||
import { RedisArgument, SimpleStringReply, NullReply, Command } from '@redis/client/dist/lib/RESP/types';
|
import { RedisArgument, SimpleStringReply, NullReply, Command } from '@redis/client/dist/lib/RESP/types';
|
||||||
import { RedisJSON, transformRedisJsonArgument } from '.';
|
import { RedisJSON, transformRedisJsonArgument } from './helpers';
|
||||||
|
|
||||||
export interface JsonSetOptions {
|
export interface JsonSetOptions {
|
||||||
condition?: 'NX' | 'XX';
|
condition?: 'NX' | 'XX';
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
||||||
import { RedisArgument, Command, NullReply, NumberReply, ArrayReply } from '@redis/client/dist/lib/RESP/types';
|
import { RedisArgument, Command, NullReply, NumberReply, ArrayReply } from '@redis/client/dist/lib/RESP/types';
|
||||||
import { transformRedisJsonArgument } from '.';
|
import { transformRedisJsonArgument } from './helpers';
|
||||||
|
|
||||||
export interface JsonStrAppendOptions {
|
export interface JsonStrAppendOptions {
|
||||||
path?: RedisArgument;
|
path?: RedisArgument;
|
||||||
|
22
packages/json/lib/commands/helpers.ts
Normal file
22
packages/json/lib/commands/helpers.ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { isNullReply } from "@redis/client/dist/lib/commands/generic-transformers";
|
||||||
|
import { BlobStringReply, NullReply, UnwrapReply } from "@redis/client/dist/lib/RESP/types";
|
||||||
|
|
||||||
|
export function transformRedisJsonNullReply(json: NullReply | BlobStringReply): NullReply | RedisJSON {
|
||||||
|
console.log('transformRedisJsonNullReply', json)
|
||||||
|
return isNullReply(json) ? json : transformRedisJsonReply(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
export type RedisJSON = null | boolean | number | string | Date | Array<RedisJSON> | {
|
||||||
|
[key: string]: RedisJSON;
|
||||||
|
[key: number]: RedisJSON;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function transformRedisJsonArgument(json: RedisJSON): string {
|
||||||
|
return JSON.stringify(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function transformRedisJsonReply(json: BlobStringReply): RedisJSON {
|
||||||
|
const res = JSON.parse((json as unknown as UnwrapReply<typeof json>).toString());
|
||||||
|
console.log('transformRedisJsonReply', json, res)
|
||||||
|
return res;
|
||||||
|
}
|
@@ -1,4 +1,3 @@
|
|||||||
import { BlobStringReply, NullReply, UnwrapReply } from '@redis/client/dist/lib/RESP/types';
|
|
||||||
import ARRAPPEND from './ARRAPPEND';
|
import ARRAPPEND from './ARRAPPEND';
|
||||||
import ARRINDEX from './ARRINDEX';
|
import ARRINDEX from './ARRINDEX';
|
||||||
import ARRINSERT from './ARRINSERT';
|
import ARRINSERT from './ARRINSERT';
|
||||||
@@ -23,7 +22,8 @@ import STRAPPEND from './STRAPPEND';
|
|||||||
import STRLEN from './STRLEN';
|
import STRLEN from './STRLEN';
|
||||||
import TOGGLE from './TOGGLE';
|
import TOGGLE from './TOGGLE';
|
||||||
import TYPE from './TYPE';
|
import TYPE from './TYPE';
|
||||||
import { isNullReply } from '@redis/client/dist/lib/commands/generic-transformers';
|
|
||||||
|
export * from './helpers';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
ARRAPPEND,
|
ARRAPPEND,
|
||||||
@@ -82,19 +82,3 @@ export default {
|
|||||||
type: TYPE
|
type: TYPE
|
||||||
};
|
};
|
||||||
|
|
||||||
export type RedisJSON = null | boolean | number | string | Date | Array<RedisJSON> | {
|
|
||||||
[key: string]: RedisJSON;
|
|
||||||
[key: number]: RedisJSON;
|
|
||||||
};
|
|
||||||
|
|
||||||
export function transformRedisJsonArgument(json: RedisJSON): string {
|
|
||||||
return JSON.stringify(json);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function transformRedisJsonReply(json: BlobStringReply): RedisJSON {
|
|
||||||
return JSON.parse((json as unknown as UnwrapReply<typeof json>).toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
export function transformRedisJsonNullReply(json: NullReply | BlobStringReply): NullReply | RedisJSON {
|
|
||||||
return isNullReply(json) ? json : transformRedisJsonReply(json);
|
|
||||||
}
|
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import { strict as assert } from 'node:assert';
|
import { strict as assert } from 'node:assert';
|
||||||
import testUtils, { GLOBAL } from '../test-utils';
|
import testUtils, { GLOBAL } from '../test-utils';
|
||||||
import ADD from './ADD';
|
import ADD from './ADD';
|
||||||
import { TIME_SERIES_ENCODING, TIME_SERIES_DUPLICATE_POLICIES } from '.';
|
import { TIME_SERIES_ENCODING, TIME_SERIES_DUPLICATE_POLICIES } from './helpers';
|
||||||
import { parseArgs } from '@redis/client/lib/commands/generic-transformers';
|
import { parseArgs } from '@redis/client/lib/commands/generic-transformers';
|
||||||
|
|
||||||
describe('TS.ADD', () => {
|
describe('TS.ADD', () => {
|
||||||
|
@@ -11,7 +11,7 @@ import {
|
|||||||
parseLabelsArgument,
|
parseLabelsArgument,
|
||||||
Timestamp,
|
Timestamp,
|
||||||
parseIgnoreArgument
|
parseIgnoreArgument
|
||||||
} from '.';
|
} from './helpers';
|
||||||
|
|
||||||
export interface TsIgnoreOptions {
|
export interface TsIgnoreOptions {
|
||||||
maxTimeDiff: number;
|
maxTimeDiff: number;
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import { strict as assert } from 'node:assert';
|
import { strict as assert } from 'node:assert';
|
||||||
import testUtils, { GLOBAL } from '../test-utils';
|
import testUtils, { GLOBAL } from '../test-utils';
|
||||||
import ALTER from './ALTER';
|
import ALTER from './ALTER';
|
||||||
import { TIME_SERIES_DUPLICATE_POLICIES } from '.';
|
import { TIME_SERIES_DUPLICATE_POLICIES } from './helpers';
|
||||||
import { parseArgs } from '@redis/client/lib/commands/generic-transformers';
|
import { parseArgs } from '@redis/client/lib/commands/generic-transformers';
|
||||||
|
|
||||||
describe('TS.ALTER', () => {
|
describe('TS.ALTER', () => {
|
||||||
|
@@ -1,7 +1,8 @@
|
|||||||
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
||||||
import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types';
|
import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types';
|
||||||
import { TsCreateOptions } from './CREATE';
|
import { TsCreateOptions } from './CREATE';
|
||||||
import { parseRetentionArgument, parseChunkSizeArgument, parseDuplicatePolicy, parseLabelsArgument, parseIgnoreArgument } from '.';
|
import { parseRetentionArgument, parseChunkSizeArgument, parseDuplicatePolicy, parseLabelsArgument, parseIgnoreArgument } from './helpers';
|
||||||
|
|
||||||
|
|
||||||
export type TsAlterOptions = Pick<TsCreateOptions, 'RETENTION' | 'CHUNK_SIZE' | 'DUPLICATE_POLICY' | 'LABELS' | 'IGNORE'>;
|
export type TsAlterOptions = Pick<TsCreateOptions, 'RETENTION' | 'CHUNK_SIZE' | 'DUPLICATE_POLICY' | 'LABELS' | 'IGNORE'>;
|
||||||
|
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import { strict as assert } from 'node:assert';
|
import { strict as assert } from 'node:assert';
|
||||||
import testUtils, { GLOBAL } from '../test-utils';
|
import testUtils, { GLOBAL } from '../test-utils';
|
||||||
import CREATE from './CREATE';
|
import CREATE from './CREATE';
|
||||||
import { TIME_SERIES_ENCODING, TIME_SERIES_DUPLICATE_POLICIES } from '.';
|
import { TIME_SERIES_ENCODING, TIME_SERIES_DUPLICATE_POLICIES } from './helpers';
|
||||||
import { parseArgs } from '@redis/client/lib/commands/generic-transformers';
|
import { parseArgs } from '@redis/client/lib/commands/generic-transformers';
|
||||||
|
|
||||||
describe('TS.CREATE', () => {
|
describe('TS.CREATE', () => {
|
||||||
|
@@ -10,7 +10,7 @@ import {
|
|||||||
Labels,
|
Labels,
|
||||||
parseLabelsArgument,
|
parseLabelsArgument,
|
||||||
parseIgnoreArgument
|
parseIgnoreArgument
|
||||||
} from '.';
|
} from './helpers';
|
||||||
import { TsIgnoreOptions } from './ADD';
|
import { TsIgnoreOptions } from './ADD';
|
||||||
|
|
||||||
export interface TsCreateOptions {
|
export interface TsCreateOptions {
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
||||||
import { Timestamp, transformTimestampArgument } from '.';
|
import { Timestamp, transformTimestampArgument } from './helpers';
|
||||||
import { RedisArgument, NumberReply, Command, } from '@redis/client/dist/lib/RESP/types';
|
import { RedisArgument, NumberReply, Command, } from '@redis/client/dist/lib/RESP/types';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
||||||
import { RedisArgument, NumberReply, Command } from '@redis/client/dist/lib/RESP/types';
|
import { RedisArgument, NumberReply, Command } from '@redis/client/dist/lib/RESP/types';
|
||||||
import { Timestamp, transformTimestampArgument, parseRetentionArgument, parseChunkSizeArgument, Labels, parseLabelsArgument, parseIgnoreArgument } from '.';
|
import { Timestamp, transformTimestampArgument, parseRetentionArgument, parseChunkSizeArgument, Labels, parseLabelsArgument, parseIgnoreArgument } from './helpers';
|
||||||
import { TsIgnoreOptions } from './ADD';
|
import { TsIgnoreOptions } from './ADD';
|
||||||
|
|
||||||
export interface TsIncrByOptions {
|
export interface TsIncrByOptions {
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { strict as assert } from 'node:assert';
|
import { strict as assert } from 'node:assert';
|
||||||
import { TIME_SERIES_DUPLICATE_POLICIES } from '.';
|
import { TIME_SERIES_DUPLICATE_POLICIES } from './helpers';
|
||||||
import testUtils, { GLOBAL } from '../test-utils';
|
import testUtils, { GLOBAL } from '../test-utils';
|
||||||
import INFO, { InfoReply } from './INFO';
|
import INFO, { InfoReply } from './INFO';
|
||||||
import { TIME_SERIES_AGGREGATION_TYPE } from './CREATERULE';
|
import { TIME_SERIES_AGGREGATION_TYPE } from './CREATERULE';
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
||||||
import { ArrayReply, BlobStringReply, Command, DoubleReply, NumberReply, ReplyUnion, SimpleStringReply, TypeMapping } from "@redis/client/dist/lib/RESP/types";
|
import { ArrayReply, BlobStringReply, Command, DoubleReply, NumberReply, ReplyUnion, SimpleStringReply, TypeMapping } from "@redis/client/dist/lib/RESP/types";
|
||||||
import { TimeSeriesDuplicatePolicies } from ".";
|
import { TimeSeriesDuplicatePolicies } from "./helpers";
|
||||||
import { TimeSeriesAggregationType } from "./CREATERULE";
|
import { TimeSeriesAggregationType } from "./CREATERULE";
|
||||||
import { transformDoubleReply } from '@redis/client/dist/lib/commands/generic-transformers';
|
import { transformDoubleReply } from '@redis/client/dist/lib/commands/generic-transformers';
|
||||||
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { strict as assert } from 'node:assert';
|
import { strict as assert } from 'node:assert';
|
||||||
import { TIME_SERIES_DUPLICATE_POLICIES } from '.';
|
import { TIME_SERIES_DUPLICATE_POLICIES } from './helpers';
|
||||||
import testUtils, { GLOBAL } from '../test-utils';
|
import testUtils, { GLOBAL } from '../test-utils';
|
||||||
import { assertInfo } from './INFO.spec';
|
import { assertInfo } from './INFO.spec';
|
||||||
import INFO_DEBUG from './INFO_DEBUG';
|
import INFO_DEBUG from './INFO_DEBUG';
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
||||||
import { Timestamp, transformTimestampArgument } from '.';
|
import { Timestamp, transformTimestampArgument } from './helpers';
|
||||||
import { ArrayReply, NumberReply, SimpleErrorReply, Command } from '@redis/client/dist/lib/RESP/types';
|
import { ArrayReply, NumberReply, SimpleErrorReply, Command } from '@redis/client/dist/lib/RESP/types';
|
||||||
|
|
||||||
export interface TsMAddSample {
|
export interface TsMAddSample {
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
||||||
import { Command, BlobStringReply, ArrayReply, Resp2Reply, MapReply, TuplesReply, TypeMapping } from '@redis/client/dist/lib/RESP/types';
|
import { Command, BlobStringReply, ArrayReply, Resp2Reply, MapReply, TuplesReply, TypeMapping } from '@redis/client/dist/lib/RESP/types';
|
||||||
import { resp2MapToValue, resp3MapToValue, SampleRawReply, transformSampleReply } from '.';
|
import { resp2MapToValue, resp3MapToValue, SampleRawReply, transformSampleReply } from './helpers';
|
||||||
import { RedisVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers';
|
import { RedisVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers';
|
||||||
|
|
||||||
export interface TsMGetOptions {
|
export interface TsMGetOptions {
|
||||||
|
@@ -2,7 +2,7 @@ import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
|||||||
import { Command, BlobStringReply, NullReply } from '@redis/client/dist/lib/RESP/types';
|
import { Command, BlobStringReply, NullReply } from '@redis/client/dist/lib/RESP/types';
|
||||||
import { RedisVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers';
|
import { RedisVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers';
|
||||||
import { TsMGetOptions, parseLatestArgument, parseFilterArgument } from './MGET';
|
import { TsMGetOptions, parseLatestArgument, parseFilterArgument } from './MGET';
|
||||||
import { parseSelectedLabelsArguments } from '.';
|
import { parseSelectedLabelsArguments } from './helpers';
|
||||||
import { createTransformMGetLabelsReply } from './MGET_WITHLABELS';
|
import { createTransformMGetLabelsReply } from './MGET_WITHLABELS';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@@ -2,7 +2,7 @@ import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
|||||||
import { Command, BlobStringReply, ArrayReply, Resp2Reply, MapReply, TuplesReply, TypeMapping } from '@redis/client/dist/lib/RESP/types';
|
import { Command, BlobStringReply, ArrayReply, Resp2Reply, MapReply, TuplesReply, TypeMapping } from '@redis/client/dist/lib/RESP/types';
|
||||||
import { RedisVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers';
|
import { RedisVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers';
|
||||||
import { TsMGetOptions, parseLatestArgument, parseFilterArgument } from './MGET';
|
import { TsMGetOptions, parseLatestArgument, parseFilterArgument } from './MGET';
|
||||||
import { RawLabelValue, resp2MapToValue, resp3MapToValue, SampleRawReply, transformRESP2Labels, transformSampleReply } from '.';
|
import { RawLabelValue, resp2MapToValue, resp3MapToValue, SampleRawReply, transformRESP2Labels, transformSampleReply } from './helpers';
|
||||||
|
|
||||||
export interface TsMGetWithLabelsOptions extends TsMGetOptions {
|
export interface TsMGetWithLabelsOptions extends TsMGetOptions {
|
||||||
SELECTED_LABELS?: RedisVariadicArgument;
|
SELECTED_LABELS?: RedisVariadicArgument;
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
||||||
import { Command, ArrayReply, BlobStringReply, Resp2Reply, MapReply, TuplesReply, TypeMapping, RedisArgument } from '@redis/client/dist/lib/RESP/types';
|
import { Command, ArrayReply, BlobStringReply, Resp2Reply, MapReply, TuplesReply, TypeMapping, RedisArgument } from '@redis/client/dist/lib/RESP/types';
|
||||||
import { RedisVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers';
|
import { RedisVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers';
|
||||||
import { resp2MapToValue, resp3MapToValue, SampleRawReply, Timestamp, transformSamplesReply } from '.';
|
import { resp2MapToValue, resp3MapToValue, SampleRawReply, Timestamp, transformSamplesReply } from './helpers';
|
||||||
import { TsRangeOptions, parseRangeArguments } from './RANGE';
|
import { TsRangeOptions, parseRangeArguments } from './RANGE';
|
||||||
import { parseFilterArgument } from './MGET';
|
import { parseFilterArgument } from './MGET';
|
||||||
|
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
||||||
import { Command, ArrayReply, BlobStringReply, Resp2Reply, MapReply, TuplesReply, TypeMapping, RedisArgument, TuplesToMapReply, UnwrapReply } from '@redis/client/dist/lib/RESP/types';
|
import { Command, ArrayReply, BlobStringReply, Resp2Reply, MapReply, TuplesReply, TypeMapping, RedisArgument, TuplesToMapReply, UnwrapReply } from '@redis/client/dist/lib/RESP/types';
|
||||||
import { RedisVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers';
|
import { RedisVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers';
|
||||||
import { resp2MapToValue, resp3MapToValue, SampleRawReply, Timestamp, transformSamplesReply } from '.';
|
import { resp2MapToValue, resp3MapToValue, SampleRawReply, Timestamp, transformSamplesReply } from './helpers';
|
||||||
import { TsRangeOptions, parseRangeArguments } from './RANGE';
|
import { TsRangeOptions, parseRangeArguments } from './RANGE';
|
||||||
import { parseFilterArgument } from './MGET';
|
import { parseFilterArgument } from './MGET';
|
||||||
|
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
||||||
import { Command, ArrayReply, BlobStringReply, Resp2Reply, MapReply, TuplesReply, TypeMapping, NullReply, RedisArgument } from '@redis/client/dist/lib/RESP/types';
|
import { Command, ArrayReply, BlobStringReply, Resp2Reply, MapReply, TuplesReply, TypeMapping, NullReply, RedisArgument } from '@redis/client/dist/lib/RESP/types';
|
||||||
import { RedisVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers';
|
import { RedisVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers';
|
||||||
import { parseSelectedLabelsArguments, resp2MapToValue, resp3MapToValue, SampleRawReply, Timestamp, transformRESP2Labels, transformSamplesReply } from '.';
|
import { parseSelectedLabelsArguments, resp2MapToValue, resp3MapToValue, SampleRawReply, Timestamp, transformRESP2Labels, transformSamplesReply } from './helpers';
|
||||||
import { TsRangeOptions, parseRangeArguments } from './RANGE';
|
import { TsRangeOptions, parseRangeArguments } from './RANGE';
|
||||||
import { parseFilterArgument } from './MGET';
|
import { parseFilterArgument } from './MGET';
|
||||||
|
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
||||||
import { Command, ArrayReply, BlobStringReply, MapReply, TuplesReply, RedisArgument, NullReply } from '@redis/client/dist/lib/RESP/types';
|
import { Command, ArrayReply, BlobStringReply, MapReply, TuplesReply, RedisArgument, NullReply } from '@redis/client/dist/lib/RESP/types';
|
||||||
import { RedisVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers';
|
import { RedisVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers';
|
||||||
import { parseSelectedLabelsArguments, resp3MapToValue, SampleRawReply, Timestamp, transformSamplesReply } from '.';
|
import { parseSelectedLabelsArguments, resp3MapToValue, SampleRawReply, Timestamp, transformSamplesReply } from './helpers';
|
||||||
import { TsRangeOptions, parseRangeArguments } from './RANGE';
|
import { TsRangeOptions, parseRangeArguments } from './RANGE';
|
||||||
import { extractResp3MRangeSources, parseGroupByArguments, TsMRangeGroupBy, TsMRangeGroupByRawMetadataReply3 } from './MRANGE_GROUPBY';
|
import { extractResp3MRangeSources, parseGroupByArguments, TsMRangeGroupBy, TsMRangeGroupByRawMetadataReply3 } from './MRANGE_GROUPBY';
|
||||||
import { parseFilterArgument } from './MGET';
|
import { parseFilterArgument } from './MGET';
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
||||||
import { Command, UnwrapReply, ArrayReply, BlobStringReply, Resp2Reply, MapReply, TuplesReply, TypeMapping, RedisArgument } from '@redis/client/dist/lib/RESP/types';
|
import { Command, UnwrapReply, ArrayReply, BlobStringReply, Resp2Reply, MapReply, TuplesReply, TypeMapping, RedisArgument } from '@redis/client/dist/lib/RESP/types';
|
||||||
import { RedisVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers';
|
import { RedisVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers';
|
||||||
import { resp2MapToValue, resp3MapToValue, SampleRawReply, Timestamp, transformSamplesReply } from '.';
|
import { resp2MapToValue, resp3MapToValue, SampleRawReply, Timestamp, transformSamplesReply } from './helpers';
|
||||||
import { TsRangeOptions, parseRangeArguments } from './RANGE';
|
import { TsRangeOptions, parseRangeArguments } from './RANGE';
|
||||||
import { parseFilterArgument } from './MGET';
|
import { parseFilterArgument } from './MGET';
|
||||||
|
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
||||||
import { Command, ArrayReply, BlobStringReply, Resp2Reply, MapReply, TuplesReply, TypeMapping, RedisArgument } from '@redis/client/dist/lib/RESP/types';
|
import { Command, ArrayReply, BlobStringReply, Resp2Reply, MapReply, TuplesReply, TypeMapping, RedisArgument } from '@redis/client/dist/lib/RESP/types';
|
||||||
import { RedisVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers';
|
import { RedisVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers';
|
||||||
import { resp2MapToValue, resp3MapToValue, SampleRawReply, Timestamp, transformRESP2LabelsWithSources, transformSamplesReply } from '.';
|
import { resp2MapToValue, resp3MapToValue, SampleRawReply, Timestamp, transformRESP2LabelsWithSources, transformSamplesReply } from './helpers';
|
||||||
import { TsRangeOptions, parseRangeArguments } from './RANGE';
|
import { TsRangeOptions, parseRangeArguments } from './RANGE';
|
||||||
import { extractResp3MRangeSources, parseGroupByArguments, TsMRangeGroupBy, TsMRangeGroupByRawMetadataReply3 } from './MRANGE_GROUPBY';
|
import { extractResp3MRangeSources, parseGroupByArguments, TsMRangeGroupBy, TsMRangeGroupByRawMetadataReply3 } from './MRANGE_GROUPBY';
|
||||||
import { parseFilterArgument } from './MGET';
|
import { parseFilterArgument } from './MGET';
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
||||||
import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types';
|
import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types';
|
||||||
import { Timestamp, transformTimestampArgument, SamplesRawReply, transformSamplesReply } from '.';
|
import { Timestamp, transformTimestampArgument, SamplesRawReply, transformSamplesReply } from './helpers';
|
||||||
import { TimeSeriesAggregationType } from './CREATERULE';
|
import { TimeSeriesAggregationType } from './CREATERULE';
|
||||||
import { Resp2Reply } from '@redis/client/dist/lib/RESP/types';
|
import { Resp2Reply } from '@redis/client/dist/lib/RESP/types';
|
||||||
|
|
||||||
|
306
packages/time-series/lib/commands/helpers.ts
Normal file
306
packages/time-series/lib/commands/helpers.ts
Normal file
@@ -0,0 +1,306 @@
|
|||||||
|
import { CommandParser } from "@redis/client/dist/lib/client/parser";
|
||||||
|
import { TsIgnoreOptions } from "./ADD";
|
||||||
|
import { ArrayReply, BlobStringReply, DoubleReply, MapReply, NullReply, NumberReply, ReplyUnion, Resp2Reply, RespType, TuplesReply, TypeMapping, UnwrapReply } from "@redis/client/dist/lib/RESP/types";
|
||||||
|
import { RESP_TYPES } from "@redis/client";
|
||||||
|
import { RedisVariadicArgument } from "@redis/client/dist/lib/commands/generic-transformers";
|
||||||
|
|
||||||
|
export function parseIgnoreArgument(parser: CommandParser, ignore?: TsIgnoreOptions) {
|
||||||
|
if (ignore !== undefined) {
|
||||||
|
parser.push('IGNORE', ignore.maxTimeDiff.toString(), ignore.maxValDiff.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function parseRetentionArgument(parser: CommandParser, retention?: number) {
|
||||||
|
if (retention !== undefined) {
|
||||||
|
parser.push('RETENTION', retention.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const TIME_SERIES_ENCODING = {
|
||||||
|
COMPRESSED: 'COMPRESSED',
|
||||||
|
UNCOMPRESSED: 'UNCOMPRESSED'
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export type TimeSeriesEncoding = typeof TIME_SERIES_ENCODING[keyof typeof TIME_SERIES_ENCODING];
|
||||||
|
|
||||||
|
export function parseEncodingArgument(parser: CommandParser, encoding?: TimeSeriesEncoding) {
|
||||||
|
if (encoding !== undefined) {
|
||||||
|
parser.push('ENCODING', encoding);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function parseChunkSizeArgument(parser: CommandParser, chunkSize?: number) {
|
||||||
|
if (chunkSize !== undefined) {
|
||||||
|
parser.push('CHUNK_SIZE', chunkSize.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const TIME_SERIES_DUPLICATE_POLICIES = {
|
||||||
|
BLOCK: 'BLOCK',
|
||||||
|
FIRST: 'FIRST',
|
||||||
|
LAST: 'LAST',
|
||||||
|
MIN: 'MIN',
|
||||||
|
MAX: 'MAX',
|
||||||
|
SUM: 'SUM'
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export type TimeSeriesDuplicatePolicies = typeof TIME_SERIES_DUPLICATE_POLICIES[keyof typeof TIME_SERIES_DUPLICATE_POLICIES];
|
||||||
|
|
||||||
|
export function parseDuplicatePolicy(parser: CommandParser, duplicatePolicy?: TimeSeriesDuplicatePolicies) {
|
||||||
|
if (duplicatePolicy !== undefined) {
|
||||||
|
parser.push('DUPLICATE_POLICY', duplicatePolicy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Timestamp = number | Date | string;
|
||||||
|
|
||||||
|
export function transformTimestampArgument(timestamp: Timestamp): string {
|
||||||
|
if (typeof timestamp === 'string') return timestamp;
|
||||||
|
|
||||||
|
return (
|
||||||
|
typeof timestamp === 'number' ?
|
||||||
|
timestamp :
|
||||||
|
timestamp.getTime()
|
||||||
|
).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Labels = {
|
||||||
|
[label: string]: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function parseLabelsArgument(parser: CommandParser, labels?: Labels) {
|
||||||
|
if (labels) {
|
||||||
|
parser.push('LABELS');
|
||||||
|
|
||||||
|
for (const [label, value] of Object.entries(labels)) {
|
||||||
|
parser.push(label, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export type SampleRawReply = TuplesReply<[timestamp: NumberReply, value: DoubleReply]>;
|
||||||
|
|
||||||
|
export const transformSampleReply = {
|
||||||
|
2(reply: Resp2Reply<SampleRawReply>) {
|
||||||
|
const [ timestamp, value ] = reply as unknown as UnwrapReply<typeof reply>;
|
||||||
|
return {
|
||||||
|
timestamp,
|
||||||
|
value: Number(value) // TODO: use double type mapping instead
|
||||||
|
};
|
||||||
|
},
|
||||||
|
3(reply: SampleRawReply) {
|
||||||
|
const [ timestamp, value ] = reply as unknown as UnwrapReply<typeof reply>;
|
||||||
|
return {
|
||||||
|
timestamp,
|
||||||
|
value
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export type SamplesRawReply = ArrayReply<SampleRawReply>;
|
||||||
|
|
||||||
|
export const transformSamplesReply = {
|
||||||
|
2(reply: Resp2Reply<SamplesRawReply>) {
|
||||||
|
return (reply as unknown as UnwrapReply<typeof reply>)
|
||||||
|
.map(sample => transformSampleReply[2](sample));
|
||||||
|
},
|
||||||
|
3(reply: SamplesRawReply) {
|
||||||
|
return (reply as unknown as UnwrapReply<typeof reply>)
|
||||||
|
.map(sample => transformSampleReply[3](sample));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: move to @redis/client?
|
||||||
|
export function resp2MapToValue<
|
||||||
|
RAW_VALUE extends TuplesReply<[key: BlobStringReply, ...rest: Array<ReplyUnion>]>,
|
||||||
|
TRANSFORMED
|
||||||
|
>(
|
||||||
|
wrappedReply: ArrayReply<RAW_VALUE>,
|
||||||
|
parseFunc: (rawValue: UnwrapReply<RAW_VALUE>) => TRANSFORMED,
|
||||||
|
typeMapping?: TypeMapping
|
||||||
|
): MapReply<BlobStringReply, TRANSFORMED> {
|
||||||
|
const reply = wrappedReply as unknown as UnwrapReply<typeof wrappedReply>;
|
||||||
|
switch (typeMapping?.[RESP_TYPES.MAP]) {
|
||||||
|
case Map: {
|
||||||
|
const ret = new Map<string, TRANSFORMED>();
|
||||||
|
for (const wrappedTuple of reply) {
|
||||||
|
const tuple = wrappedTuple as unknown as UnwrapReply<typeof wrappedTuple>;
|
||||||
|
const key = tuple[0] as unknown as UnwrapReply<typeof tuple[0]>;
|
||||||
|
ret.set(key.toString(), parseFunc(tuple));
|
||||||
|
}
|
||||||
|
return ret as never;
|
||||||
|
}
|
||||||
|
case Array: {
|
||||||
|
for (const wrappedTuple of reply) {
|
||||||
|
const tuple = wrappedTuple as unknown as UnwrapReply<typeof wrappedTuple>;
|
||||||
|
(tuple[1] as unknown as TRANSFORMED) = parseFunc(tuple);
|
||||||
|
}
|
||||||
|
return reply as never;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
const ret: Record<string, TRANSFORMED> = Object.create(null);
|
||||||
|
for (const wrappedTuple of reply) {
|
||||||
|
const tuple = wrappedTuple as unknown as UnwrapReply<typeof wrappedTuple>;
|
||||||
|
const key = tuple[0] as unknown as UnwrapReply<typeof tuple[0]>;
|
||||||
|
ret[key.toString()] = parseFunc(tuple);
|
||||||
|
}
|
||||||
|
return ret as never;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function resp3MapToValue<
|
||||||
|
RAW_VALUE extends RespType<any, any, any, any>, // TODO: simplify types
|
||||||
|
TRANSFORMED
|
||||||
|
>(
|
||||||
|
wrappedReply: MapReply<BlobStringReply, RAW_VALUE>,
|
||||||
|
parseFunc: (rawValue: UnwrapReply<RAW_VALUE>) => TRANSFORMED
|
||||||
|
): MapReply<BlobStringReply, TRANSFORMED> {
|
||||||
|
const reply = wrappedReply as unknown as UnwrapReply<typeof wrappedReply>;
|
||||||
|
if (reply instanceof Array) {
|
||||||
|
for (let i = 1; i < reply.length; i += 2) {
|
||||||
|
(reply[i] as unknown as TRANSFORMED) = parseFunc(reply[i] as unknown as UnwrapReply<RAW_VALUE>);
|
||||||
|
}
|
||||||
|
} else if (reply instanceof Map) {
|
||||||
|
for (const [key, value] of reply.entries()) {
|
||||||
|
(reply as unknown as Map<BlobStringReply, TRANSFORMED>).set(
|
||||||
|
key,
|
||||||
|
parseFunc(value as unknown as UnwrapReply<typeof value>)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (const [key, value] of Object.entries(reply)) {
|
||||||
|
(reply[key] as unknown as TRANSFORMED) = parseFunc(value as unknown as UnwrapReply<typeof value>);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return reply as never;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function parseSelectedLabelsArguments(
|
||||||
|
parser: CommandParser,
|
||||||
|
selectedLabels: RedisVariadicArgument
|
||||||
|
) {
|
||||||
|
parser.push('SELECTED_LABELS');
|
||||||
|
parser.pushVariadic(selectedLabels);
|
||||||
|
}
|
||||||
|
|
||||||
|
export type RawLabelValue = BlobStringReply | NullReply;
|
||||||
|
|
||||||
|
export type RawLabels<T extends RawLabelValue> = ArrayReply<TuplesReply<[
|
||||||
|
label: BlobStringReply,
|
||||||
|
value: T
|
||||||
|
]>>;
|
||||||
|
|
||||||
|
export function transformRESP2Labels<T extends RawLabelValue>(
|
||||||
|
labels: RawLabels<T>,
|
||||||
|
typeMapping?: TypeMapping
|
||||||
|
): MapReply<BlobStringReply, T> {
|
||||||
|
const unwrappedLabels = labels as unknown as UnwrapReply<typeof labels>;
|
||||||
|
switch (typeMapping?.[RESP_TYPES.MAP]) {
|
||||||
|
case Map:
|
||||||
|
const map = new Map<string, T>();
|
||||||
|
for (const tuple of unwrappedLabels) {
|
||||||
|
const [key, value] = tuple as unknown as UnwrapReply<typeof tuple>;
|
||||||
|
const unwrappedKey = key as unknown as UnwrapReply<typeof key>;
|
||||||
|
map.set(unwrappedKey.toString(), value);
|
||||||
|
}
|
||||||
|
return map as never;
|
||||||
|
|
||||||
|
case Array:
|
||||||
|
return unwrappedLabels.flat() as never;
|
||||||
|
|
||||||
|
case Object:
|
||||||
|
default:
|
||||||
|
const labelsObject: Record<string, T> = Object.create(null);
|
||||||
|
for (const tuple of unwrappedLabels) {
|
||||||
|
const [key, value] = tuple as unknown as UnwrapReply<typeof tuple>;
|
||||||
|
const unwrappedKey = key as unknown as UnwrapReply<typeof key>;
|
||||||
|
labelsObject[unwrappedKey.toString()] = value;
|
||||||
|
}
|
||||||
|
return labelsObject as never;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function transformRESP2LabelsWithSources<T extends RawLabelValue>(
|
||||||
|
labels: RawLabels<T>,
|
||||||
|
typeMapping?: TypeMapping
|
||||||
|
) {
|
||||||
|
const unwrappedLabels = labels as unknown as UnwrapReply<typeof labels>;
|
||||||
|
const to = unwrappedLabels.length - 2; // ignore __reducer__ and __source__
|
||||||
|
let transformedLabels: MapReply<BlobStringReply, T>;
|
||||||
|
switch (typeMapping?.[RESP_TYPES.MAP]) {
|
||||||
|
case Map:
|
||||||
|
const map = new Map<string, T>();
|
||||||
|
for (let i = 0; i < to; i++) {
|
||||||
|
const [key, value] = unwrappedLabels[i] as unknown as UnwrapReply<typeof unwrappedLabels[number]>;
|
||||||
|
const unwrappedKey = key as unknown as UnwrapReply<typeof key>;
|
||||||
|
map.set(unwrappedKey.toString(), value);
|
||||||
|
}
|
||||||
|
transformedLabels = map as never;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Array:
|
||||||
|
transformedLabels = unwrappedLabels.slice(0, to).flat() as never;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Object:
|
||||||
|
default:
|
||||||
|
const labelsObject: Record<string, T> = Object.create(null);
|
||||||
|
for (let i = 0; i < to; i++) {
|
||||||
|
const [key, value] = unwrappedLabels[i] as unknown as UnwrapReply<typeof unwrappedLabels[number]>;
|
||||||
|
const unwrappedKey = key as unknown as UnwrapReply<typeof key>;
|
||||||
|
labelsObject[unwrappedKey.toString()] = value;
|
||||||
|
}
|
||||||
|
transformedLabels = labelsObject as never;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const sourcesTuple = unwrappedLabels[unwrappedLabels.length - 1];
|
||||||
|
const unwrappedSourcesTuple = sourcesTuple as unknown as UnwrapReply<typeof sourcesTuple>;
|
||||||
|
// the __source__ label will never be null
|
||||||
|
const transformedSources = transformRESP2Sources(unwrappedSourcesTuple[1] as BlobStringReply);
|
||||||
|
|
||||||
|
return {
|
||||||
|
labels: transformedLabels,
|
||||||
|
sources: transformedSources
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function transformRESP2Sources(sourcesRaw: BlobStringReply) {
|
||||||
|
// if a label contains "," this function will produce incorrcet results..
|
||||||
|
// there is not much we can do about it, and we assume most users won't be using "," in their labels..
|
||||||
|
|
||||||
|
const unwrappedSources = sourcesRaw as unknown as UnwrapReply<typeof sourcesRaw>;
|
||||||
|
if (typeof unwrappedSources === 'string') {
|
||||||
|
return unwrappedSources.split(',');
|
||||||
|
}
|
||||||
|
|
||||||
|
const indexOfComma = unwrappedSources.indexOf(',');
|
||||||
|
if (indexOfComma === -1) {
|
||||||
|
return [unwrappedSources];
|
||||||
|
}
|
||||||
|
|
||||||
|
const sourcesArray = [
|
||||||
|
unwrappedSources.subarray(0, indexOfComma)
|
||||||
|
];
|
||||||
|
|
||||||
|
let previousComma = indexOfComma + 1;
|
||||||
|
while (true) {
|
||||||
|
const indexOf = unwrappedSources.indexOf(',', previousComma);
|
||||||
|
if (indexOf === -1) {
|
||||||
|
sourcesArray.push(
|
||||||
|
unwrappedSources.subarray(previousComma)
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const source = unwrappedSources.subarray(
|
||||||
|
previousComma,
|
||||||
|
indexOf
|
||||||
|
);
|
||||||
|
sourcesArray.push(source);
|
||||||
|
previousComma = indexOf + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sourcesArray;
|
||||||
|
}
|
@@ -24,7 +24,7 @@
|
|||||||
// TimeSeriesDuplicatePolicies,
|
// TimeSeriesDuplicatePolicies,
|
||||||
// pushLatestArgument,
|
// pushLatestArgument,
|
||||||
// TimeSeriesBucketTimestamp
|
// TimeSeriesBucketTimestamp
|
||||||
// } from '.';
|
// } from './helpers';
|
||||||
|
|
||||||
// describe('transformTimestampArgument', () => {
|
// describe('transformTimestampArgument', () => {
|
||||||
// it('number', () => {
|
// it('number', () => {
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
import type { DoubleReply, NumberReply, RedisCommands, TuplesReply, UnwrapReply, Resp2Reply, ArrayReply, BlobStringReply, MapReply, NullReply, TypeMapping, ReplyUnion, RespType } from '@redis/client/dist/lib/RESP/types';
|
import ADD from './ADD';
|
||||||
import ADD, { TsIgnoreOptions } from './ADD';
|
|
||||||
import ALTER from './ALTER';
|
import ALTER from './ALTER';
|
||||||
import CREATE from './CREATE';
|
import CREATE from './CREATE';
|
||||||
import CREATERULE from './CREATERULE';
|
import CREATERULE from './CREATERULE';
|
||||||
@@ -29,9 +28,9 @@ import MREVRANGE from './MREVRANGE';
|
|||||||
import QUERYINDEX from './QUERYINDEX';
|
import QUERYINDEX from './QUERYINDEX';
|
||||||
import RANGE from './RANGE';
|
import RANGE from './RANGE';
|
||||||
import REVRANGE from './REVRANGE';
|
import REVRANGE from './REVRANGE';
|
||||||
import { RedisVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers';
|
import { RedisCommands } from '@redis/client/dist/lib/RESP/types';
|
||||||
import { CommandParser } from '@redis/client/dist/lib/client/parser';
|
|
||||||
import { RESP_TYPES } from '@redis/client/dist/lib/RESP/decoder';
|
export * from './helpers';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
ADD,
|
ADD,
|
||||||
@@ -96,303 +95,3 @@ export default {
|
|||||||
revRange: REVRANGE
|
revRange: REVRANGE
|
||||||
} as const satisfies RedisCommands;
|
} as const satisfies RedisCommands;
|
||||||
|
|
||||||
export function parseIgnoreArgument(parser: CommandParser, ignore?: TsIgnoreOptions) {
|
|
||||||
if (ignore !== undefined) {
|
|
||||||
parser.push('IGNORE', ignore.maxTimeDiff.toString(), ignore.maxValDiff.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function parseRetentionArgument(parser: CommandParser, retention?: number) {
|
|
||||||
if (retention !== undefined) {
|
|
||||||
parser.push('RETENTION', retention.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const TIME_SERIES_ENCODING = {
|
|
||||||
COMPRESSED: 'COMPRESSED',
|
|
||||||
UNCOMPRESSED: 'UNCOMPRESSED'
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export type TimeSeriesEncoding = typeof TIME_SERIES_ENCODING[keyof typeof TIME_SERIES_ENCODING];
|
|
||||||
|
|
||||||
export function parseEncodingArgument(parser: CommandParser, encoding?: TimeSeriesEncoding) {
|
|
||||||
if (encoding !== undefined) {
|
|
||||||
parser.push('ENCODING', encoding);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function parseChunkSizeArgument(parser: CommandParser, chunkSize?: number) {
|
|
||||||
if (chunkSize !== undefined) {
|
|
||||||
parser.push('CHUNK_SIZE', chunkSize.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const TIME_SERIES_DUPLICATE_POLICIES = {
|
|
||||||
BLOCK: 'BLOCK',
|
|
||||||
FIRST: 'FIRST',
|
|
||||||
LAST: 'LAST',
|
|
||||||
MIN: 'MIN',
|
|
||||||
MAX: 'MAX',
|
|
||||||
SUM: 'SUM'
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export type TimeSeriesDuplicatePolicies = typeof TIME_SERIES_DUPLICATE_POLICIES[keyof typeof TIME_SERIES_DUPLICATE_POLICIES];
|
|
||||||
|
|
||||||
export function parseDuplicatePolicy(parser: CommandParser, duplicatePolicy?: TimeSeriesDuplicatePolicies) {
|
|
||||||
if (duplicatePolicy !== undefined) {
|
|
||||||
parser.push('DUPLICATE_POLICY', duplicatePolicy);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export type Timestamp = number | Date | string;
|
|
||||||
|
|
||||||
export function transformTimestampArgument(timestamp: Timestamp): string {
|
|
||||||
if (typeof timestamp === 'string') return timestamp;
|
|
||||||
|
|
||||||
return (
|
|
||||||
typeof timestamp === 'number' ?
|
|
||||||
timestamp :
|
|
||||||
timestamp.getTime()
|
|
||||||
).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
export type Labels = {
|
|
||||||
[label: string]: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export function parseLabelsArgument(parser: CommandParser, labels?: Labels) {
|
|
||||||
if (labels) {
|
|
||||||
parser.push('LABELS');
|
|
||||||
|
|
||||||
for (const [label, value] of Object.entries(labels)) {
|
|
||||||
parser.push(label, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export type SampleRawReply = TuplesReply<[timestamp: NumberReply, value: DoubleReply]>;
|
|
||||||
|
|
||||||
export const transformSampleReply = {
|
|
||||||
2(reply: Resp2Reply<SampleRawReply>) {
|
|
||||||
const [ timestamp, value ] = reply as unknown as UnwrapReply<typeof reply>;
|
|
||||||
return {
|
|
||||||
timestamp,
|
|
||||||
value: Number(value) // TODO: use double type mapping instead
|
|
||||||
};
|
|
||||||
},
|
|
||||||
3(reply: SampleRawReply) {
|
|
||||||
const [ timestamp, value ] = reply as unknown as UnwrapReply<typeof reply>;
|
|
||||||
return {
|
|
||||||
timestamp,
|
|
||||||
value
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export type SamplesRawReply = ArrayReply<SampleRawReply>;
|
|
||||||
|
|
||||||
export const transformSamplesReply = {
|
|
||||||
2(reply: Resp2Reply<SamplesRawReply>) {
|
|
||||||
return (reply as unknown as UnwrapReply<typeof reply>)
|
|
||||||
.map(sample => transformSampleReply[2](sample));
|
|
||||||
},
|
|
||||||
3(reply: SamplesRawReply) {
|
|
||||||
return (reply as unknown as UnwrapReply<typeof reply>)
|
|
||||||
.map(sample => transformSampleReply[3](sample));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO: move to @redis/client?
|
|
||||||
export function resp2MapToValue<
|
|
||||||
RAW_VALUE extends TuplesReply<[key: BlobStringReply, ...rest: Array<ReplyUnion>]>,
|
|
||||||
TRANSFORMED
|
|
||||||
>(
|
|
||||||
wrappedReply: ArrayReply<RAW_VALUE>,
|
|
||||||
parseFunc: (rawValue: UnwrapReply<RAW_VALUE>) => TRANSFORMED,
|
|
||||||
typeMapping?: TypeMapping
|
|
||||||
): MapReply<BlobStringReply, TRANSFORMED> {
|
|
||||||
const reply = wrappedReply as unknown as UnwrapReply<typeof wrappedReply>;
|
|
||||||
switch (typeMapping?.[RESP_TYPES.MAP]) {
|
|
||||||
case Map: {
|
|
||||||
const ret = new Map<string, TRANSFORMED>();
|
|
||||||
for (const wrappedTuple of reply) {
|
|
||||||
const tuple = wrappedTuple as unknown as UnwrapReply<typeof wrappedTuple>;
|
|
||||||
const key = tuple[0] as unknown as UnwrapReply<typeof tuple[0]>;
|
|
||||||
ret.set(key.toString(), parseFunc(tuple));
|
|
||||||
}
|
|
||||||
return ret as never;
|
|
||||||
}
|
|
||||||
case Array: {
|
|
||||||
for (const wrappedTuple of reply) {
|
|
||||||
const tuple = wrappedTuple as unknown as UnwrapReply<typeof wrappedTuple>;
|
|
||||||
(tuple[1] as unknown as TRANSFORMED) = parseFunc(tuple);
|
|
||||||
}
|
|
||||||
return reply as never;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
const ret: Record<string, TRANSFORMED> = Object.create(null);
|
|
||||||
for (const wrappedTuple of reply) {
|
|
||||||
const tuple = wrappedTuple as unknown as UnwrapReply<typeof wrappedTuple>;
|
|
||||||
const key = tuple[0] as unknown as UnwrapReply<typeof tuple[0]>;
|
|
||||||
ret[key.toString()] = parseFunc(tuple);
|
|
||||||
}
|
|
||||||
return ret as never;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function resp3MapToValue<
|
|
||||||
RAW_VALUE extends RespType<any, any, any, any>, // TODO: simplify types
|
|
||||||
TRANSFORMED
|
|
||||||
>(
|
|
||||||
wrappedReply: MapReply<BlobStringReply, RAW_VALUE>,
|
|
||||||
parseFunc: (rawValue: UnwrapReply<RAW_VALUE>) => TRANSFORMED
|
|
||||||
): MapReply<BlobStringReply, TRANSFORMED> {
|
|
||||||
const reply = wrappedReply as unknown as UnwrapReply<typeof wrappedReply>;
|
|
||||||
if (reply instanceof Array) {
|
|
||||||
for (let i = 1; i < reply.length; i += 2) {
|
|
||||||
(reply[i] as unknown as TRANSFORMED) = parseFunc(reply[i] as unknown as UnwrapReply<RAW_VALUE>);
|
|
||||||
}
|
|
||||||
} else if (reply instanceof Map) {
|
|
||||||
for (const [key, value] of reply.entries()) {
|
|
||||||
(reply as unknown as Map<BlobStringReply, TRANSFORMED>).set(
|
|
||||||
key,
|
|
||||||
parseFunc(value as unknown as UnwrapReply<typeof value>)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (const [key, value] of Object.entries(reply)) {
|
|
||||||
(reply[key] as unknown as TRANSFORMED) = parseFunc(value as unknown as UnwrapReply<typeof value>);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return reply as never;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function parseSelectedLabelsArguments(
|
|
||||||
parser: CommandParser,
|
|
||||||
selectedLabels: RedisVariadicArgument
|
|
||||||
) {
|
|
||||||
parser.push('SELECTED_LABELS');
|
|
||||||
parser.pushVariadic(selectedLabels);
|
|
||||||
}
|
|
||||||
|
|
||||||
export type RawLabelValue = BlobStringReply | NullReply;
|
|
||||||
|
|
||||||
export type RawLabels<T extends RawLabelValue> = ArrayReply<TuplesReply<[
|
|
||||||
label: BlobStringReply,
|
|
||||||
value: T
|
|
||||||
]>>;
|
|
||||||
|
|
||||||
export function transformRESP2Labels<T extends RawLabelValue>(
|
|
||||||
labels: RawLabels<T>,
|
|
||||||
typeMapping?: TypeMapping
|
|
||||||
): MapReply<BlobStringReply, T> {
|
|
||||||
const unwrappedLabels = labels as unknown as UnwrapReply<typeof labels>;
|
|
||||||
switch (typeMapping?.[RESP_TYPES.MAP]) {
|
|
||||||
case Map:
|
|
||||||
const map = new Map<string, T>();
|
|
||||||
for (const tuple of unwrappedLabels) {
|
|
||||||
const [key, value] = tuple as unknown as UnwrapReply<typeof tuple>;
|
|
||||||
const unwrappedKey = key as unknown as UnwrapReply<typeof key>;
|
|
||||||
map.set(unwrappedKey.toString(), value);
|
|
||||||
}
|
|
||||||
return map as never;
|
|
||||||
|
|
||||||
case Array:
|
|
||||||
return unwrappedLabels.flat() as never;
|
|
||||||
|
|
||||||
case Object:
|
|
||||||
default:
|
|
||||||
const labelsObject: Record<string, T> = Object.create(null);
|
|
||||||
for (const tuple of unwrappedLabels) {
|
|
||||||
const [key, value] = tuple as unknown as UnwrapReply<typeof tuple>;
|
|
||||||
const unwrappedKey = key as unknown as UnwrapReply<typeof key>;
|
|
||||||
labelsObject[unwrappedKey.toString()] = value;
|
|
||||||
}
|
|
||||||
return labelsObject as never;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function transformRESP2LabelsWithSources<T extends RawLabelValue>(
|
|
||||||
labels: RawLabels<T>,
|
|
||||||
typeMapping?: TypeMapping
|
|
||||||
) {
|
|
||||||
const unwrappedLabels = labels as unknown as UnwrapReply<typeof labels>;
|
|
||||||
const to = unwrappedLabels.length - 2; // ignore __reducer__ and __source__
|
|
||||||
let transformedLabels: MapReply<BlobStringReply, T>;
|
|
||||||
switch (typeMapping?.[RESP_TYPES.MAP]) {
|
|
||||||
case Map:
|
|
||||||
const map = new Map<string, T>();
|
|
||||||
for (let i = 0; i < to; i++) {
|
|
||||||
const [key, value] = unwrappedLabels[i] as unknown as UnwrapReply<typeof unwrappedLabels[number]>;
|
|
||||||
const unwrappedKey = key as unknown as UnwrapReply<typeof key>;
|
|
||||||
map.set(unwrappedKey.toString(), value);
|
|
||||||
}
|
|
||||||
transformedLabels = map as never;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Array:
|
|
||||||
transformedLabels = unwrappedLabels.slice(0, to).flat() as never;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Object:
|
|
||||||
default:
|
|
||||||
const labelsObject: Record<string, T> = Object.create(null);
|
|
||||||
for (let i = 0; i < to; i++) {
|
|
||||||
const [key, value] = unwrappedLabels[i] as unknown as UnwrapReply<typeof unwrappedLabels[number]>;
|
|
||||||
const unwrappedKey = key as unknown as UnwrapReply<typeof key>;
|
|
||||||
labelsObject[unwrappedKey.toString()] = value;
|
|
||||||
}
|
|
||||||
transformedLabels = labelsObject as never;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
const sourcesTuple = unwrappedLabels[unwrappedLabels.length - 1];
|
|
||||||
const unwrappedSourcesTuple = sourcesTuple as unknown as UnwrapReply<typeof sourcesTuple>;
|
|
||||||
// the __source__ label will never be null
|
|
||||||
const transformedSources = transformRESP2Sources(unwrappedSourcesTuple[1] as BlobStringReply);
|
|
||||||
|
|
||||||
return {
|
|
||||||
labels: transformedLabels,
|
|
||||||
sources: transformedSources
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function transformRESP2Sources(sourcesRaw: BlobStringReply) {
|
|
||||||
// if a label contains "," this function will produce incorrcet results..
|
|
||||||
// there is not much we can do about it, and we assume most users won't be using "," in their labels..
|
|
||||||
|
|
||||||
const unwrappedSources = sourcesRaw as unknown as UnwrapReply<typeof sourcesRaw>;
|
|
||||||
if (typeof unwrappedSources === 'string') {
|
|
||||||
return unwrappedSources.split(',');
|
|
||||||
}
|
|
||||||
|
|
||||||
const indexOfComma = unwrappedSources.indexOf(',');
|
|
||||||
if (indexOfComma === -1) {
|
|
||||||
return [unwrappedSources];
|
|
||||||
}
|
|
||||||
|
|
||||||
const sourcesArray = [
|
|
||||||
unwrappedSources.subarray(0, indexOfComma)
|
|
||||||
];
|
|
||||||
|
|
||||||
let previousComma = indexOfComma + 1;
|
|
||||||
while (true) {
|
|
||||||
const indexOf = unwrappedSources.indexOf(',', previousComma);
|
|
||||||
if (indexOf === -1) {
|
|
||||||
sourcesArray.push(
|
|
||||||
unwrappedSources.subarray(previousComma)
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
const source = unwrappedSources.subarray(
|
|
||||||
previousComma,
|
|
||||||
indexOf
|
|
||||||
);
|
|
||||||
sourcesArray.push(source);
|
|
||||||
previousComma = indexOf + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return sourcesArray;
|
|
||||||
}
|
|
||||||
|
Reference in New Issue
Block a user