You've already forked node-redis
mirror of
https://github.com/redis/node-redis.git
synced 2025-08-06 02:15:48 +03:00
WIP
This commit is contained in:
@@ -181,6 +181,7 @@ Some command arguments/replies have changed to align more closely to data types
|
|||||||
- `JSON.ARRLEN`: `path` argument moved to `{ path: string; }` [^future-proofing]
|
- `JSON.ARRLEN`: `path` argument moved to `{ path: string; }` [^future-proofing]
|
||||||
- `JSON.DEL`: `path` argument moved to `{ path: string; }` [^future-proofing]
|
- `JSON.DEL`: `path` argument moved to `{ path: string; }` [^future-proofing]
|
||||||
- `JSON.FORGET`: `path` argument moved to `{ path: string; }` [^future-proofing]
|
- `JSON.FORGET`: `path` argument moved to `{ path: string; }` [^future-proofing]
|
||||||
|
- `TS.[M][REV]RANGE`: `enum TimeSeriesBucketTimestamp` -> `const TIME_SERIES_BUCKET_TIMESTAMP` [^enum-to-constants], `enum TimeSeriesReducers` -> `const TIME_SERIES_REDUCERS` [^enum-to-constants], the `ALIGN` argument has been moved into `AGGREGRATION`
|
||||||
|
|
||||||
[^enum-to-constants]: TODO
|
[^enum-to-constants]: TODO
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { RedisArgument, SimpleStringReply, Command } from '../RESP/types';
|
import { RedisArgument, SimpleStringReply, BlobStringReply, Command } from '../RESP/types';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
FIRST_KEY_INDEX: undefined,
|
FIRST_KEY_INDEX: undefined,
|
||||||
@@ -11,5 +11,5 @@ export default {
|
|||||||
|
|
||||||
return args;
|
return args;
|
||||||
},
|
},
|
||||||
transformReply: undefined as unknown as () => SimpleStringReply
|
transformReply: undefined as unknown as () => SimpleStringReply | BlobStringReply
|
||||||
} as const satisfies Command;
|
} as const satisfies Command;
|
||||||
|
@@ -64,7 +64,7 @@ describe('TS.ALTER', () => {
|
|||||||
testUtils.testWithClient('client.ts.alter', async client => {
|
testUtils.testWithClient('client.ts.alter', async client => {
|
||||||
const [, reply] = await Promise.all([
|
const [, reply] = await Promise.all([
|
||||||
client.ts.create('key'),
|
client.ts.create('key'),
|
||||||
client.ts.alter('key', { RETENTION: 1 })
|
client.ts.alter('key')
|
||||||
]);
|
]);
|
||||||
|
|
||||||
assert.equal(reply, 'OK');
|
assert.equal(reply, 'OK');
|
||||||
|
@@ -3,7 +3,7 @@ import testUtils, { GLOBAL } from '../test-utils';
|
|||||||
import MADD from './MADD';
|
import MADD from './MADD';
|
||||||
import { SimpleError } from '@redis/client/lib/errors';
|
import { SimpleError } from '@redis/client/lib/errors';
|
||||||
|
|
||||||
describe.only('TS.MADD', () => {
|
describe('TS.MADD', () => {
|
||||||
it('transformArguments', () => {
|
it('transformArguments', () => {
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
MADD.transformArguments([{
|
MADD.transformArguments([{
|
||||||
|
@@ -1,40 +1,40 @@
|
|||||||
import { strict as assert } from 'assert';
|
import { strict as assert } from 'assert';
|
||||||
import testUtils, { GLOBAL } from '../test-utils';
|
import testUtils, { GLOBAL } from '../test-utils';
|
||||||
import { transformArguments } from './MGET';
|
import MGET from './MGET';
|
||||||
|
|
||||||
describe('TS.MGET', () => {
|
describe('TS.MGET', () => {
|
||||||
describe('transformArguments', () => {
|
describe('transformArguments', () => {
|
||||||
it('without options', () => {
|
it('without options', () => {
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
transformArguments('label=value'),
|
MGET.transformArguments('label=value'),
|
||||||
['TS.MGET', 'FILTER', 'label=value']
|
['TS.MGET', 'FILTER', 'label=value']
|
||||||
);
|
);
|
||||||
});
|
|
||||||
|
|
||||||
it('with LATEST', () => {
|
|
||||||
assert.deepEqual(
|
|
||||||
transformArguments('label=value', {
|
|
||||||
LATEST: true
|
|
||||||
}),
|
|
||||||
['TS.MGET', 'LATEST', 'FILTER', 'label=value']
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
testUtils.testWithClient('client.ts.mGet', async client => {
|
it('with LATEST', () => {
|
||||||
await client.ts.add('key', 0, 0, {
|
assert.deepEqual(
|
||||||
LABELS: { label: 'value' }
|
MGET.transformArguments('label=value', {
|
||||||
});
|
LATEST: true
|
||||||
|
}),
|
||||||
|
['TS.MGET', 'LATEST', 'FILTER', 'label=value']
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
assert.deepEqual(
|
testUtils.testWithClient('client.ts.mGet', async client => {
|
||||||
await client.ts.mGet('label=value'),
|
const [, reply] = await Promise.all([
|
||||||
[{
|
client.ts.add('key', 0, 0, {
|
||||||
key: 'key',
|
LABELS: { label: 'value' }
|
||||||
sample: {
|
}),
|
||||||
timestamp: 0,
|
client.ts.mGet('label=value')
|
||||||
value: 0
|
]);
|
||||||
}
|
|
||||||
}]
|
assert.deepEqual(reply, [{
|
||||||
);
|
key: 'key',
|
||||||
}, GLOBAL.SERVERS.OPEN);
|
sample: {
|
||||||
|
timestamp: 0,
|
||||||
|
value: 0
|
||||||
|
}
|
||||||
|
}]);
|
||||||
|
}, GLOBAL.SERVERS.OPEN);
|
||||||
});
|
});
|
||||||
|
@@ -1,31 +1,31 @@
|
|||||||
import { RedisCommandArguments } from '@redis/client/dist/lib/commands';
|
import { CommandArguments, Command } from '@redis/client/dist/lib/RESP/types';
|
||||||
import { Filter, pushFilterArgument, pushLatestArgument, RawLabels, SampleRawReply, SampleReply, transformSampleReply } from '.';
|
import { RedisVariadicArgument, pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers';
|
||||||
|
|
||||||
export const IS_READ_ONLY = true;
|
export interface TsMGetOptions {
|
||||||
|
LATEST?: boolean;
|
||||||
export interface MGetOptions {
|
|
||||||
LATEST?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function transformArguments(filter: Filter, options?: MGetOptions): RedisCommandArguments {
|
export function pushLatestArgument(args: CommandArguments, latest?: boolean) {
|
||||||
|
if (latest) {
|
||||||
|
args.push('LATEST');
|
||||||
|
}
|
||||||
|
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function pushFilterArgument(args: CommandArguments, filter: RedisVariadicArgument) {
|
||||||
|
args.push('FILTER');
|
||||||
|
return pushVariadicArguments(args, filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
FIRST_KEY_INDEX: undefined,
|
||||||
|
IS_READ_ONLY: true,
|
||||||
|
transformArguments(filter: RedisVariadicArgument, options?: TsMGetOptions) {
|
||||||
const args = pushLatestArgument(['TS.MGET'], options?.LATEST);
|
const args = pushLatestArgument(['TS.MGET'], options?.LATEST);
|
||||||
return pushFilterArgument(args, filter);
|
return pushFilterArgument(args, filter);
|
||||||
}
|
},
|
||||||
|
// TODO
|
||||||
export type MGetRawReply = Array<[
|
// transformSampleReply
|
||||||
key: string,
|
transformReply: undefined as unknown as () => any
|
||||||
labels: RawLabels,
|
} as const satisfies Command;
|
||||||
sample: SampleRawReply
|
|
||||||
]>;
|
|
||||||
|
|
||||||
export interface MGetReply {
|
|
||||||
key: string,
|
|
||||||
sample: SampleReply
|
|
||||||
}
|
|
||||||
|
|
||||||
export function transformReply(reply: MGetRawReply): Array<MGetReply> {
|
|
||||||
return reply.map(([key, _, sample]) => ({
|
|
||||||
key,
|
|
||||||
sample: transformSampleReply(sample)
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
@@ -1,39 +1,41 @@
|
|||||||
import { strict as assert } from 'assert';
|
import { strict as assert } from 'assert';
|
||||||
import testUtils, { GLOBAL } from '../test-utils';
|
import testUtils, { GLOBAL } from '../test-utils';
|
||||||
import { transformArguments } from './MGET_WITHLABELS';
|
import MGET_WITHLABELS from './MGET_WITHLABELS';
|
||||||
|
|
||||||
describe('TS.MGET_WITHLABELS', () => {
|
describe('TS.MGET_WITHLABELS', () => {
|
||||||
describe('transformArguments', () => {
|
describe('transformArguments', () => {
|
||||||
it('without options', () => {
|
it('without options', () => {
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
transformArguments('label=value'),
|
MGET_WITHLABELS.transformArguments('label=value'),
|
||||||
['TS.MGET', 'WITHLABELS', 'FILTER', 'label=value']
|
['TS.MGET', 'WITHLABELS', 'FILTER', 'label=value']
|
||||||
);
|
);
|
||||||
});
|
|
||||||
|
|
||||||
it('with SELECTED_LABELS', () => {
|
|
||||||
assert.deepEqual(
|
|
||||||
transformArguments('label=value', { SELECTED_LABELS: 'label' }),
|
|
||||||
['TS.MGET', 'SELECTED_LABELS', 'label', 'FILTER', 'label=value']
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
testUtils.testWithClient('client.ts.mGetWithLabels', async client => {
|
it('with SELECTED_LABELS', () => {
|
||||||
await client.ts.add('key', 0, 0, {
|
assert.deepEqual(
|
||||||
LABELS: { label: 'value' }
|
MGET_WITHLABELS.transformArguments('label=value', {
|
||||||
});
|
SELECTED_LABELS: 'label'
|
||||||
|
}),
|
||||||
|
['TS.MGET', 'SELECTED_LABELS', 'label', 'FILTER', 'label=value']
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
assert.deepEqual(
|
testUtils.testWithClient('client.ts.mGetWithLabels', async client => {
|
||||||
await client.ts.mGetWithLabels('label=value'),
|
const [, reply] = await Promise.all([
|
||||||
[{
|
client.ts.add('key', 0, 0, {
|
||||||
key: 'key',
|
LABELS: { label: 'value' }
|
||||||
labels: { label: 'value'},
|
}),
|
||||||
sample: {
|
client.ts.mGetWithLabels('label=value')
|
||||||
timestamp: 0,
|
]);
|
||||||
value: 0
|
|
||||||
}
|
assert.deepEqual(reply, [{
|
||||||
}]
|
key: 'key',
|
||||||
);
|
labels: { label: 'value' },
|
||||||
}, GLOBAL.SERVERS.OPEN);
|
sample: {
|
||||||
|
timestamp: 0,
|
||||||
|
value: 0
|
||||||
|
}
|
||||||
|
}]);
|
||||||
|
}, GLOBAL.SERVERS.OPEN);
|
||||||
});
|
});
|
||||||
|
@@ -1,37 +1,20 @@
|
|||||||
import {
|
import { Command } from '@redis/client/dist/lib/RESP/types';
|
||||||
SelectedLabels,
|
import { RedisVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers';
|
||||||
pushWithLabelsArgument,
|
import { TsMGetOptions, pushLatestArgument, pushFilterArgument } from './MGET';
|
||||||
Labels,
|
import { pushWithLabelsArgument } from '.';
|
||||||
transformLablesReply,
|
|
||||||
transformSampleReply,
|
|
||||||
Filter,
|
|
||||||
pushFilterArgument
|
|
||||||
} from '.';
|
|
||||||
import { MGetOptions, MGetRawReply, MGetReply } from './MGET';
|
|
||||||
import { RedisCommandArguments } from '@redis/client/dist/lib/commands';
|
|
||||||
|
|
||||||
export const IS_READ_ONLY = true;
|
export interface TsMGetWithLabelsOptions extends TsMGetOptions {
|
||||||
|
SELECTED_LABELS?: RedisVariadicArgument;
|
||||||
interface MGetWithLabelsOptions extends MGetOptions {
|
|
||||||
SELECTED_LABELS?: SelectedLabels;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function transformArguments(
|
export default {
|
||||||
filter: Filter,
|
FIRST_KEY_INDEX: undefined,
|
||||||
options?: MGetWithLabelsOptions
|
IS_READ_ONLY: true,
|
||||||
): RedisCommandArguments {
|
transformArguments(filter: RedisVariadicArgument, options?: TsMGetWithLabelsOptions) {
|
||||||
const args = pushWithLabelsArgument(['TS.MGET'], options?.SELECTED_LABELS);
|
let args = pushLatestArgument(['TS.MGET'], options?.LATEST);
|
||||||
|
args = pushWithLabelsArgument(args, options?.SELECTED_LABELS);
|
||||||
return pushFilterArgument(args, filter);
|
return pushFilterArgument(args, filter);
|
||||||
}
|
},
|
||||||
|
// TODO
|
||||||
export interface MGetWithLabelsReply extends MGetReply {
|
transformReply: undefined as unknown as () => any
|
||||||
labels: Labels;
|
} as const satisfies Command;
|
||||||
};
|
|
||||||
|
|
||||||
export function transformReply(reply: MGetRawReply): Array<MGetWithLabelsReply> {
|
|
||||||
return reply.map(([key, labels, sample]) => ({
|
|
||||||
key,
|
|
||||||
labels: transformLablesReply(labels),
|
|
||||||
sample: transformSampleReply(sample)
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
@@ -1,50 +1,54 @@
|
|||||||
import { strict as assert } from 'assert';
|
import { strict as assert } from 'assert';
|
||||||
import testUtils, { GLOBAL } from '../test-utils';
|
import testUtils, { GLOBAL } from '../test-utils';
|
||||||
import { transformArguments } from './MRANGE';
|
import MRANGE from './MRANGE';
|
||||||
import { TimeSeriesAggregationType, TimeSeriesReducers } from '.';
|
import { TimeSeriesAggregationType, TimeSeriesReducers } from '.';
|
||||||
|
|
||||||
describe('TS.MRANGE', () => {
|
describe('TS.MRANGE', () => {
|
||||||
it('transformArguments', () => {
|
it('transformArguments', () => {
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
transformArguments('-', '+', 'label=value', {
|
MRANGE.transformArguments('-', '+', 'label=value', {
|
||||||
FILTER_BY_TS: [0],
|
FILTER_BY_TS: [0],
|
||||||
FILTER_BY_VALUE: {
|
FILTER_BY_VALUE: {
|
||||||
min: 0,
|
min: 0,
|
||||||
max: 1
|
max: 1
|
||||||
},
|
},
|
||||||
COUNT: 1,
|
COUNT: 1,
|
||||||
ALIGN: '-',
|
ALIGN: '-',
|
||||||
AGGREGATION: {
|
AGGREGATION: {
|
||||||
type: TimeSeriesAggregationType.AVERAGE,
|
type: TimeSeriesAggregationType.AVERAGE,
|
||||||
timeBucket: 1
|
timeBucket: 1
|
||||||
},
|
},
|
||||||
GROUPBY: {
|
GROUPBY: {
|
||||||
label: 'label',
|
label: 'label',
|
||||||
reducer: TimeSeriesReducers.SUM
|
reducer: TimeSeriesReducers.SUM
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
['TS.MRANGE', '-', '+', 'FILTER_BY_TS', '0', 'FILTER_BY_VALUE', '0', '1',
|
[
|
||||||
'COUNT', '1', 'ALIGN', '-', 'AGGREGATION', 'AVG', '1', 'FILTER', 'label=value',
|
'TS.MRANGE', '-', '+', 'FILTER_BY_TS', '0', 'FILTER_BY_VALUE', '0', '1',
|
||||||
'GROUPBY', 'label', 'REDUCE', 'SUM']
|
'COUNT', '1', 'ALIGN', '-', 'AGGREGATION', 'AVG', '1', 'FILTER', 'label=value',
|
||||||
);
|
'GROUPBY', 'label', 'REDUCE', 'SUM'
|
||||||
});
|
]
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
testUtils.testWithClient('client.ts.mRange', async client => {
|
testUtils.testWithClient('client.ts.mRange', async client => {
|
||||||
await client.ts.add('key', 0, 0, {
|
const [, reply] = await Promise.all([
|
||||||
LABELS: { label: 'value'}
|
client.ts.add('key', 0, 0, {
|
||||||
});
|
LABELS: {
|
||||||
|
label: 'value'
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
client.ts.mRange('-', '+', 'label=value', {
|
||||||
|
COUNT: 1
|
||||||
|
})
|
||||||
|
]);
|
||||||
|
|
||||||
assert.deepEqual(
|
assert.deepEqual(reply, [{
|
||||||
await client.ts.mRange('-', '+', 'label=value', {
|
key: 'key',
|
||||||
COUNT: 1
|
samples: [{
|
||||||
}),
|
timestamp: 0,
|
||||||
[{
|
value: 0
|
||||||
key: 'key',
|
}]
|
||||||
samples: [{
|
}]);
|
||||||
timestamp: 0,
|
}, GLOBAL.SERVERS.OPEN);
|
||||||
value: 0
|
|
||||||
}]
|
|
||||||
}]
|
|
||||||
);
|
|
||||||
}, GLOBAL.SERVERS.OPEN);
|
|
||||||
});
|
});
|
||||||
|
@@ -1,21 +1,68 @@
|
|||||||
import { RedisCommandArguments } from '@redis/client/dist/lib/commands';
|
import { RedisArgument, Command, CommandArguments } from '@redis/client/dist/lib/RESP/types';
|
||||||
import { MRangeOptions, Timestamp, pushMRangeArguments, Filter } from '.';
|
import { RedisVariadicArgument, pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers';
|
||||||
|
import { Timestamp } from '.';
|
||||||
|
import { TsRangeOptions, pushRangeArguments } from './RANGE';
|
||||||
|
import { pushFilterArgument } from './MGET';
|
||||||
|
|
||||||
export const IS_READ_ONLY = true;
|
export const TIME_SERIES_REDUCERS = {
|
||||||
|
AVG: 'AVG',
|
||||||
|
SUM: 'SUM',
|
||||||
|
MIN: 'MIN',
|
||||||
|
MAX: 'MAX',
|
||||||
|
RANGE: 'RANGE',
|
||||||
|
COUNT: 'COUNT',
|
||||||
|
STD_P: 'STD.P',
|
||||||
|
STD_S: 'STD.S',
|
||||||
|
VAR_P: 'VAR.P',
|
||||||
|
VAR_S: 'VAR.S'
|
||||||
|
};
|
||||||
|
|
||||||
export function transformArguments(
|
export type TimeSeriesReducers = typeof TIME_SERIES_REDUCERS[keyof typeof TIME_SERIES_REDUCERS];
|
||||||
fromTimestamp: Timestamp,
|
|
||||||
toTimestamp: Timestamp,
|
export interface TsMRangeOptions extends TsRangeOptions {
|
||||||
filters: Filter,
|
GROUPBY?: {
|
||||||
options?: MRangeOptions
|
label: RedisArgument;
|
||||||
): RedisCommandArguments {
|
reducer: TimeSeriesReducers;
|
||||||
return pushMRangeArguments(
|
};
|
||||||
['TS.MRANGE'],
|
|
||||||
fromTimestamp,
|
|
||||||
toTimestamp,
|
|
||||||
filters,
|
|
||||||
options
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export { transformMRangeReply as transformReply } from '.';
|
export function pushGroupByArgument(args: CommandArguments, groupBy?: TsMRangeOptions['GROUPBY']) {
|
||||||
|
if (groupBy) {
|
||||||
|
args.push(
|
||||||
|
'GROUPBY',
|
||||||
|
groupBy.label,
|
||||||
|
'REDUCE',
|
||||||
|
groupBy.reducer
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function transformMRangeArguments(
|
||||||
|
command: RedisArgument,
|
||||||
|
fromTimestamp: Timestamp,
|
||||||
|
toTimestamp: Timestamp,
|
||||||
|
filter: RedisVariadicArgument,
|
||||||
|
options?: TsMRangeOptions
|
||||||
|
) {
|
||||||
|
let args = pushRangeArguments(
|
||||||
|
[command],
|
||||||
|
fromTimestamp,
|
||||||
|
toTimestamp,
|
||||||
|
options
|
||||||
|
);
|
||||||
|
|
||||||
|
args = pushFilterArgument(args, filter);
|
||||||
|
|
||||||
|
return pushGroupByArgument(args, options?.GROUPBY);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
FIRST_KEY_INDEX: undefined,
|
||||||
|
IS_READ_ONLY: true,
|
||||||
|
transformArguments: transformMRangeArguments.bind(undefined, 'TS.MRANGE'),
|
||||||
|
// TODO
|
||||||
|
// export { transformMRangeReply as transformReply } from '.';
|
||||||
|
transformReply: undefined as unknown as () => any
|
||||||
|
} as const satisfies Command;
|
||||||
|
@@ -1,52 +1,53 @@
|
|||||||
import { strict as assert } from 'assert';
|
import { strict as assert } from 'assert';
|
||||||
import testUtils, { GLOBAL } from '../test-utils';
|
import testUtils, { GLOBAL } from '../test-utils';
|
||||||
import { transformArguments } from './MRANGE_WITHLABELS';
|
import MRANGE_WITHLABELS from './MRANGE_WITHLABELS';
|
||||||
import { TimeSeriesAggregationType, TimeSeriesReducers } from '.';
|
import { TIME_SERIES_AGGREGATION_TYPE } from './CREATERULE';
|
||||||
|
import { TIME_SERIES_REDUCERS } from './MRANGE';
|
||||||
|
|
||||||
describe('TS.MRANGE_WITHLABELS', () => {
|
describe('TS.MRANGE_WITHLABELS', () => {
|
||||||
it('transformArguments', () => {
|
it('transformArguments', () => {
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
transformArguments('-', '+', 'label=value', {
|
MRANGE_WITHLABELS.transformArguments('-', '+', 'label=value', {
|
||||||
FILTER_BY_TS: [0],
|
FILTER_BY_TS: [0],
|
||||||
FILTER_BY_VALUE: {
|
FILTER_BY_VALUE: {
|
||||||
min: 0,
|
min: 0,
|
||||||
max: 1
|
max: 1
|
||||||
},
|
},
|
||||||
SELECTED_LABELS: ['label'],
|
SELECTED_LABELS: ['label'],
|
||||||
COUNT: 1,
|
COUNT: 1,
|
||||||
ALIGN: '-',
|
ALIGN: '-',
|
||||||
AGGREGATION: {
|
AGGREGATION: {
|
||||||
type: TimeSeriesAggregationType.AVERAGE,
|
type: TIME_SERIES_AGGREGATION_TYPE.AVG,
|
||||||
timeBucket: 1
|
timeBucket: 1
|
||||||
},
|
},
|
||||||
GROUPBY: {
|
GROUPBY: {
|
||||||
label: 'label',
|
label: 'label',
|
||||||
reducer: TimeSeriesReducers.SUM
|
reducer: TIME_SERIES_REDUCERS.SUM
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
['TS.MRANGE', '-', '+', 'FILTER_BY_TS', '0', 'FILTER_BY_VALUE', '0', '1',
|
['TS.MRANGE', '-', '+', 'FILTER_BY_TS', '0', 'FILTER_BY_VALUE', '0', '1',
|
||||||
'COUNT', '1', 'ALIGN', '-', 'AGGREGATION', 'AVG', '1', 'SELECTED_LABELS', 'label',
|
'COUNT', '1', 'ALIGN', '-', 'AGGREGATION', 'AVG', '1', 'SELECTED_LABELS', 'label',
|
||||||
'FILTER', 'label=value', 'GROUPBY', 'label', 'REDUCE', 'SUM']
|
'FILTER', 'label=value', 'GROUPBY', 'label', 'REDUCE', 'SUM']
|
||||||
);
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
testUtils.testWithClient('client.ts.mRangeWithLabels', async client => {
|
||||||
|
await client.ts.add('key', 0, 0, {
|
||||||
|
LABELS: { label: 'value' }
|
||||||
});
|
});
|
||||||
|
|
||||||
testUtils.testWithClient('client.ts.mRangeWithLabels', async client => {
|
assert.deepEqual(
|
||||||
await client.ts.add('key', 0, 0, {
|
await client.ts.mRangeWithLabels('-', '+', 'label=value', {
|
||||||
LABELS: { label: 'value'}
|
COUNT: 1
|
||||||
});
|
}),
|
||||||
|
[{
|
||||||
assert.deepEqual(
|
key: 'key',
|
||||||
await client.ts.mRangeWithLabels('-', '+', 'label=value', {
|
labels: { label: 'value' },
|
||||||
COUNT: 1
|
samples: [{
|
||||||
}),
|
timestamp: 0,
|
||||||
[{
|
value: 0
|
||||||
key: 'key',
|
}]
|
||||||
labels: { label: 'value' },
|
}]
|
||||||
samples: [{
|
);
|
||||||
timestamp: 0,
|
}, GLOBAL.SERVERS.OPEN);
|
||||||
value: 0
|
|
||||||
}]
|
|
||||||
}]
|
|
||||||
);
|
|
||||||
}, GLOBAL.SERVERS.OPEN);
|
|
||||||
});
|
});
|
||||||
|
@@ -1,21 +1,32 @@
|
|||||||
import { RedisCommandArguments } from '@redis/client/dist/lib/commands';
|
import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types';
|
||||||
import { Timestamp, MRangeWithLabelsOptions, pushMRangeWithLabelsArguments } from '.';
|
import { RedisVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers';
|
||||||
|
import { TsMRangeOptions, pushGroupByArgument } from './MRANGE';
|
||||||
|
import { Timestamp, pushWithLabelsArgument } from '.';
|
||||||
|
import { pushFilterArgument } from './MGET';
|
||||||
|
import { pushRangeArguments } from './RANGE';
|
||||||
|
|
||||||
export const IS_READ_ONLY = true;
|
export interface TsMRangeWithLabelsOptions extends TsMRangeOptions {
|
||||||
|
SELECTED_LABELS?: RedisVariadicArgument;
|
||||||
export function transformArguments(
|
|
||||||
fromTimestamp: Timestamp,
|
|
||||||
toTimestamp: Timestamp,
|
|
||||||
filters: string | Array<string>,
|
|
||||||
options?: MRangeWithLabelsOptions
|
|
||||||
): RedisCommandArguments {
|
|
||||||
return pushMRangeWithLabelsArguments(
|
|
||||||
['TS.MRANGE'],
|
|
||||||
fromTimestamp,
|
|
||||||
toTimestamp,
|
|
||||||
filters,
|
|
||||||
options
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export { transformMRangeWithLabelsReply as transformReply } from '.';
|
export function transformMRangeWithLabelsArguments(
|
||||||
|
command: RedisArgument,
|
||||||
|
fromTimestamp: Timestamp,
|
||||||
|
toTimestamp: Timestamp,
|
||||||
|
filter: RedisVariadicArgument,
|
||||||
|
options?: TsMRangeWithLabelsOptions
|
||||||
|
) {
|
||||||
|
let args = pushRangeArguments([command], fromTimestamp, toTimestamp, options);
|
||||||
|
args = pushWithLabelsArgument(args, options?.SELECTED_LABELS);
|
||||||
|
args = pushFilterArgument(args, filter);
|
||||||
|
return pushGroupByArgument(args, options?.GROUPBY);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
FIRST_KEY_INDEX: undefined,
|
||||||
|
IS_READ_ONLY: true,
|
||||||
|
transformArguments: transformMRangeWithLabelsArguments.bind(undefined, 'TS.MRANGE'),
|
||||||
|
// TODO
|
||||||
|
// export { transformMRangeWithLabelsReply as transformReply } from '.';
|
||||||
|
transformReply: undefined as unknown as () => any
|
||||||
|
} as const satisfies Command;
|
||||||
|
@@ -4,47 +4,49 @@ import { transformArguments } from './MREVRANGE';
|
|||||||
import { TimeSeriesAggregationType, TimeSeriesReducers } from '.';
|
import { TimeSeriesAggregationType, TimeSeriesReducers } from '.';
|
||||||
|
|
||||||
describe('TS.MREVRANGE', () => {
|
describe('TS.MREVRANGE', () => {
|
||||||
it('transformArguments', () => {
|
it('transformArguments', () => {
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
transformArguments('-', '+', 'label=value', {
|
transformArguments('-', '+', 'label=value', {
|
||||||
FILTER_BY_TS: [0],
|
FILTER_BY_TS: [0],
|
||||||
FILTER_BY_VALUE: {
|
FILTER_BY_VALUE: {
|
||||||
min: 0,
|
min: 0,
|
||||||
max: 1
|
max: 1
|
||||||
},
|
},
|
||||||
COUNT: 1,
|
COUNT: 1,
|
||||||
ALIGN: '-',
|
ALIGN: '-',
|
||||||
AGGREGATION: {
|
AGGREGATION: {
|
||||||
type: TimeSeriesAggregationType.AVERAGE,
|
type: TimeSeriesAggregationType.AVERAGE,
|
||||||
timeBucket: 1
|
timeBucket: 1
|
||||||
},
|
},
|
||||||
GROUPBY: {
|
GROUPBY: {
|
||||||
label: 'label',
|
label: 'label',
|
||||||
reducer: TimeSeriesReducers.SUM
|
reducer: TimeSeriesReducers.SUM
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
['TS.MREVRANGE', '-', '+', 'FILTER_BY_TS', '0', 'FILTER_BY_VALUE', '0', '1',
|
[
|
||||||
'COUNT', '1', 'ALIGN', '-', 'AGGREGATION', 'AVG', '1', 'FILTER', 'label=value',
|
'TS.MREVRANGE', '-', '+', 'FILTER_BY_TS', '0', 'FILTER_BY_VALUE', '0', '1',
|
||||||
'GROUPBY', 'label', 'REDUCE', 'SUM']
|
'COUNT', '1', 'ALIGN', '-', 'AGGREGATION', 'AVG', '1', 'FILTER', 'label=value',
|
||||||
);
|
'GROUPBY', 'label', 'REDUCE', 'SUM'
|
||||||
});
|
]
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
testUtils.testWithClient('client.ts.mRevRange', async client => {
|
testUtils.testWithClient('client.ts.mRevRange', async client => {
|
||||||
await client.ts.add('key', 0, 0, {
|
const [, reply] = await Promise.all([
|
||||||
LABELS: { label: 'value'}
|
client.ts.add('key', 0, 0, {
|
||||||
});
|
LABELS: { label: 'value' }
|
||||||
|
}),
|
||||||
|
client.ts.mRevRange('-', '+', 'label=value', {
|
||||||
|
COUNT: 1
|
||||||
|
})
|
||||||
|
]);
|
||||||
|
|
||||||
assert.deepEqual(
|
assert.deepEqual(reply, [{
|
||||||
await client.ts.mRevRange('-', '+', 'label=value', {
|
key: 'key',
|
||||||
COUNT: 1
|
samples: [{
|
||||||
}),
|
timestamp: 0,
|
||||||
[{
|
value: 0
|
||||||
key: 'key',
|
}]
|
||||||
samples: [{
|
}]);
|
||||||
timestamp: 0,
|
}, GLOBAL.SERVERS.OPEN);
|
||||||
value: 0
|
|
||||||
}]
|
|
||||||
}]
|
|
||||||
);
|
|
||||||
}, GLOBAL.SERVERS.OPEN);
|
|
||||||
});
|
});
|
||||||
|
@@ -1,21 +1,9 @@
|
|||||||
import { RedisCommandArguments } from '@redis/client/dist/lib/commands';
|
import { Command } from '@redis/client/dist/lib/RESP/types';
|
||||||
import { MRangeOptions, Timestamp, pushMRangeArguments, Filter } from '.';
|
import MRANGE, { transformMRangeArguments } from './MRANGE';
|
||||||
|
|
||||||
export const IS_READ_ONLY = true;
|
export default {
|
||||||
|
FIRST_KEY_INDEX: MRANGE.FIRST_KEY_INDEX,
|
||||||
export function transformArguments(
|
IS_READ_ONLY: MRANGE.IS_READ_ONLY,
|
||||||
fromTimestamp: Timestamp,
|
transformArguments: transformMRangeArguments.bind(undefined, 'TS.MREVRANGE'),
|
||||||
toTimestamp: Timestamp,
|
transformReply: MRANGE.transformReply
|
||||||
filters: Filter,
|
} as const satisfies Command;
|
||||||
options?: MRangeOptions
|
|
||||||
): RedisCommandArguments {
|
|
||||||
return pushMRangeArguments(
|
|
||||||
['TS.MREVRANGE'],
|
|
||||||
fromTimestamp,
|
|
||||||
toTimestamp,
|
|
||||||
filters,
|
|
||||||
options
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export { transformMRangeReply as transformReply } from '.';
|
|
||||||
|
@@ -1,52 +1,54 @@
|
|||||||
import { strict as assert } from 'assert';
|
import { strict as assert } from 'assert';
|
||||||
import testUtils, { GLOBAL } from '../test-utils';
|
import testUtils, { GLOBAL } from '../test-utils';
|
||||||
import { transformArguments } from './MREVRANGE_WITHLABELS';
|
import MREVRANGE_WITHLABELS from './MREVRANGE_WITHLABELS';
|
||||||
import { TimeSeriesAggregationType, TimeSeriesReducers } from '.';
|
import { TimeSeriesAggregationType, TimeSeriesReducers } from '.';
|
||||||
|
|
||||||
describe('TS.MREVRANGE_WITHLABELS', () => {
|
describe('TS.MREVRANGE_WITHLABELS', () => {
|
||||||
it('transformArguments', () => {
|
it('transformArguments', () => {
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
transformArguments('-', '+', 'label=value', {
|
MREVRANGE_WITHLABELS.transformArguments('-', '+', 'label=value', {
|
||||||
FILTER_BY_TS: [0],
|
FILTER_BY_TS: [0],
|
||||||
FILTER_BY_VALUE: {
|
FILTER_BY_VALUE: {
|
||||||
min: 0,
|
min: 0,
|
||||||
max: 1
|
max: 1
|
||||||
},
|
},
|
||||||
SELECTED_LABELS: ['label'],
|
SELECTED_LABELS: ['label'],
|
||||||
COUNT: 1,
|
COUNT: 1,
|
||||||
ALIGN: '-',
|
ALIGN: '-',
|
||||||
AGGREGATION: {
|
AGGREGATION: {
|
||||||
type: TimeSeriesAggregationType.AVERAGE,
|
type: TimeSeriesAggregationType.AVERAGE,
|
||||||
timeBucket: 1
|
timeBucket: 1
|
||||||
},
|
},
|
||||||
GROUPBY: {
|
GROUPBY: {
|
||||||
label: 'label',
|
label: 'label',
|
||||||
reducer: TimeSeriesReducers.SUM
|
reducer: TimeSeriesReducers.SUM
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
['TS.MREVRANGE', '-', '+', 'FILTER_BY_TS', '0', 'FILTER_BY_VALUE', '0', '1',
|
[
|
||||||
'COUNT', '1', 'ALIGN', '-', 'AGGREGATION', 'AVG', '1', 'SELECTED_LABELS', 'label',
|
'TS.MREVRANGE', '-', '+', 'FILTER_BY_TS', '0', 'FILTER_BY_VALUE', '0', '1',
|
||||||
'FILTER', 'label=value', 'GROUPBY', 'label', 'REDUCE', 'SUM']
|
'COUNT', '1', 'ALIGN', '-', 'AGGREGATION', 'AVG', '1', 'SELECTED_LABELS', 'label',
|
||||||
);
|
'FILTER', 'label=value', 'GROUPBY', 'label', 'REDUCE', 'SUM'
|
||||||
});
|
]
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
testUtils.testWithClient('client.ts.mRevRangeWithLabels', async client => {
|
testUtils.testWithClient('client.ts.mRevRangeWithLabels', async client => {
|
||||||
await client.ts.add('key', 0, 0, {
|
const [, reply] = await Promise.all([
|
||||||
LABELS: { label: 'value'}
|
client.ts.add('key', 0, 0, {
|
||||||
});
|
LABELS: { label: 'value' }
|
||||||
|
}),
|
||||||
|
client.ts.mRevRangeWithLabels('-', '+', 'label=value', {
|
||||||
|
COUNT: 1
|
||||||
|
})
|
||||||
|
]);
|
||||||
|
|
||||||
assert.deepEqual(
|
assert.deepEqual(reply, [{
|
||||||
await client.ts.mRevRangeWithLabels('-', '+', 'label=value', {
|
key: 'key',
|
||||||
COUNT: 1
|
labels: { label: 'value' },
|
||||||
}),
|
samples: [{
|
||||||
[{
|
timestamp: 0,
|
||||||
key: 'key',
|
value: 0
|
||||||
labels: { label: 'value' },
|
}]
|
||||||
samples: [{
|
}]);
|
||||||
timestamp: 0,
|
}, GLOBAL.SERVERS.OPEN);
|
||||||
value: 0
|
|
||||||
}]
|
|
||||||
}]
|
|
||||||
);
|
|
||||||
}, GLOBAL.SERVERS.OPEN);
|
|
||||||
});
|
});
|
||||||
|
@@ -1,21 +1,11 @@
|
|||||||
import { RedisCommandArguments } from '@redis/client/dist/lib/commands';
|
import { Command } from '@redis/client/dist/lib/RESP/types';
|
||||||
import { Timestamp, MRangeWithLabelsOptions, pushMRangeWithLabelsArguments, Filter } from '.';
|
import { transformMRangeWithLabelsArguments } from './MRANGE_WITHLABELS';
|
||||||
|
|
||||||
export const IS_READ_ONLY = true;
|
export default {
|
||||||
|
FIRST_KEY_INDEX: undefined,
|
||||||
export function transformArguments(
|
IS_READ_ONLY: true,
|
||||||
fromTimestamp: Timestamp,
|
transformArguments: transformMRangeWithLabelsArguments.bind(undefined, 'TS.MREVRANGE'),
|
||||||
toTimestamp: Timestamp,
|
// TODO
|
||||||
filters: Filter,
|
// export { transformMRangeWithLabelsReply as transformReply } from '.';
|
||||||
options?: MRangeWithLabelsOptions
|
transformReply: undefined as unknown as () => any
|
||||||
): RedisCommandArguments {
|
} as const satisfies Command;
|
||||||
return pushMRangeWithLabelsArguments(
|
|
||||||
['TS.MREVRANGE'],
|
|
||||||
fromTimestamp,
|
|
||||||
toTimestamp,
|
|
||||||
filters,
|
|
||||||
options
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export { transformMRangeWithLabelsReply as transformReply } from '.';
|
|
||||||
|
@@ -1,34 +1,34 @@
|
|||||||
import { strict as assert } from 'assert';
|
import { strict as assert } from 'assert';
|
||||||
import testUtils, { GLOBAL } from '../test-utils';
|
import testUtils, { GLOBAL } from '../test-utils';
|
||||||
import { transformArguments } from './QUERYINDEX';
|
import QUERYINDEX from './QUERYINDEX';
|
||||||
|
|
||||||
describe('TS.QUERYINDEX', () => {
|
describe('TS.QUERYINDEX', () => {
|
||||||
describe('transformArguments', () => {
|
describe('transformArguments', () => {
|
||||||
it('single filter', () => {
|
it('single filter', () => {
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
transformArguments('*'),
|
QUERYINDEX.transformArguments('*'),
|
||||||
['TS.QUERYINDEX', '*']
|
['TS.QUERYINDEX', '*']
|
||||||
);
|
);
|
||||||
});
|
|
||||||
|
|
||||||
it('multiple filters', () => {
|
|
||||||
assert.deepEqual(
|
|
||||||
transformArguments(['a=1', 'b=2']),
|
|
||||||
['TS.QUERYINDEX', 'a=1', 'b=2']
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
testUtils.testWithClient('client.ts.queryIndex', async client => {
|
it('multiple filters', () => {
|
||||||
await client.ts.create('key', {
|
assert.deepEqual(
|
||||||
LABELS: {
|
QUERYINDEX.transformArguments(['a=1', 'b=2']),
|
||||||
label: 'value'
|
['TS.QUERYINDEX', 'a=1', 'b=2']
|
||||||
}
|
);
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
assert.deepEqual(
|
testUtils.testWithClient('client.ts.queryIndex', async client => {
|
||||||
await client.ts.queryIndex('label=value'),
|
const [, reply] = await Promise.all([
|
||||||
['key']
|
client.ts.create('key', {
|
||||||
);
|
LABELS: {
|
||||||
}, GLOBAL.SERVERS.OPEN);
|
label: 'value'
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
client.ts.queryIndex('label=value')
|
||||||
|
]);
|
||||||
|
|
||||||
|
assert.deepEqual(reply, ['key']);
|
||||||
|
}, GLOBAL.SERVERS.OPEN);
|
||||||
});
|
});
|
||||||
|
@@ -1,11 +1,14 @@
|
|||||||
import { RedisCommandArguments } from '@redis/client/dist/lib/commands';
|
import { ArrayReply, BlobStringReply, SetReply, Command } from '@redis/client/dist/lib/RESP/types';
|
||||||
import { pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers';
|
import { RedisVariadicArgument, pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers';
|
||||||
import { Filter } from '.';
|
|
||||||
|
|
||||||
export const IS_READ_ONLY = true;
|
export default {
|
||||||
|
FIRST_KEY_INDEX: undefined,
|
||||||
export function transformArguments(filter: Filter): RedisCommandArguments {
|
IS_READ_ONLY: true,
|
||||||
|
transformArguments(filter: RedisVariadicArgument) {
|
||||||
return pushVariadicArguments(['TS.QUERYINDEX'], filter);
|
return pushVariadicArguments(['TS.QUERYINDEX'], filter);
|
||||||
}
|
},
|
||||||
|
transformReply: {
|
||||||
export declare function transformReply(): Array<string>;
|
2: undefined as unknown as () => ArrayReply<BlobStringReply>,
|
||||||
|
3: undefined as unknown as () => SetReply<BlobStringReply>
|
||||||
|
}
|
||||||
|
} as const satisfies Command;
|
||||||
|
@@ -1,38 +1,40 @@
|
|||||||
import { strict as assert } from 'assert';
|
import { strict as assert } from 'assert';
|
||||||
import testUtils, { GLOBAL } from '../test-utils';
|
import testUtils, { GLOBAL } from '../test-utils';
|
||||||
import { transformArguments } from './RANGE';
|
import RANGE from './RANGE';
|
||||||
import { TimeSeriesAggregationType } from '.';
|
import { TIME_SERIES_AGGREGATION_TYPE } from './CREATERULE';
|
||||||
|
|
||||||
describe('TS.RANGE', () => {
|
describe('TS.RANGE', () => {
|
||||||
it('transformArguments', () => {
|
it('transformArguments', () => {
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
transformArguments('key', '-', '+', {
|
RANGE.transformArguments('key', '-', '+', {
|
||||||
FILTER_BY_TS: [0],
|
FILTER_BY_TS: [0],
|
||||||
FILTER_BY_VALUE: {
|
FILTER_BY_VALUE: {
|
||||||
min: 1,
|
min: 1,
|
||||||
max: 2
|
max: 2
|
||||||
},
|
},
|
||||||
COUNT: 1,
|
COUNT: 1,
|
||||||
ALIGN: '-',
|
ALIGN: '-',
|
||||||
AGGREGATION: {
|
AGGREGATION: {
|
||||||
type: TimeSeriesAggregationType.AVERAGE,
|
type: TIME_SERIES_AGGREGATION_TYPE.AVG,
|
||||||
timeBucket: 1
|
timeBucket: 1
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
['TS.RANGE', 'key', '-', '+', 'FILTER_BY_TS', '0', 'FILTER_BY_VALUE',
|
[
|
||||||
'1', '2', 'COUNT', '1', 'ALIGN', '-', 'AGGREGATION', 'AVG', '1']
|
'TS.RANGE', 'key', '-', '+', 'FILTER_BY_TS', '0', 'FILTER_BY_VALUE',
|
||||||
);
|
'1', '2', 'COUNT', '1', 'ALIGN', '-', 'AGGREGATION', 'AVG', '1'
|
||||||
});
|
]
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
testUtils.testWithClient('client.ts.range', async client => {
|
testUtils.testWithClient('client.ts.range', async client => {
|
||||||
await client.ts.add('key', 1, 2);
|
const [, reply] = await Promise.all([
|
||||||
|
client.ts.add('key', 1, 2),
|
||||||
|
client.ts.range('key', '-', '+')
|
||||||
|
]);
|
||||||
|
|
||||||
assert.deepEqual(
|
assert.deepEqual(reply, [{
|
||||||
await client.ts.range('key', '-', '+'),
|
timestamp: 1,
|
||||||
[{
|
value: 2
|
||||||
timestamp: 1,
|
}]);
|
||||||
value: 2
|
}, GLOBAL.SERVERS.OPEN);
|
||||||
}]
|
|
||||||
);
|
|
||||||
}, GLOBAL.SERVERS.OPEN);
|
|
||||||
});
|
});
|
||||||
|
@@ -1,24 +1,117 @@
|
|||||||
import { RedisCommandArguments } from '@redis/client/dist/lib/commands';
|
import { CommandArguments, RedisArgument, Command } from '@redis/client/dist/lib/RESP/types';
|
||||||
import { RangeOptions, Timestamp, pushRangeArguments, SampleRawReply, SampleReply, transformRangeReply } from '.';
|
import { Timestamp, transformTimestampArgument } from '.';
|
||||||
|
import { TimeSeriesAggregationType } from './CREATERULE';
|
||||||
|
|
||||||
export const FIRST_KEY_INDEX = 1;
|
export const TIME_SERIES_BUCKET_TIMESTAMP = {
|
||||||
|
LOW: '-',
|
||||||
|
MIDDLE: '~',
|
||||||
|
END: '+'
|
||||||
|
};
|
||||||
|
|
||||||
export const IS_READ_ONLY = true;
|
export type TimeSeriesBucketTimestamp = typeof TIME_SERIES_BUCKET_TIMESTAMP[keyof typeof TIME_SERIES_BUCKET_TIMESTAMP];
|
||||||
|
|
||||||
export function transformArguments(
|
export interface TsRangeOptions {
|
||||||
key: string,
|
LATEST?: boolean;
|
||||||
fromTimestamp: Timestamp,
|
FILTER_BY_TS?: Array<Timestamp>;
|
||||||
toTimestamp: Timestamp,
|
FILTER_BY_VALUE?: {
|
||||||
options?: RangeOptions
|
min: number;
|
||||||
): RedisCommandArguments {
|
max: number;
|
||||||
return pushRangeArguments(
|
};
|
||||||
['TS.RANGE', key],
|
COUNT?: number;
|
||||||
fromTimestamp,
|
ALIGN?: Timestamp;
|
||||||
toTimestamp,
|
AGGREGATION?: {
|
||||||
options
|
ALIGN?: Timestamp;
|
||||||
|
type: TimeSeriesAggregationType;
|
||||||
|
timeBucket: Timestamp;
|
||||||
|
BUCKETTIMESTAMP?: TimeSeriesBucketTimestamp;
|
||||||
|
EMPTY?: boolean;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function pushRangeArguments(
|
||||||
|
args: CommandArguments,
|
||||||
|
fromTimestamp: Timestamp,
|
||||||
|
toTimestamp: Timestamp,
|
||||||
|
options?: TsRangeOptions
|
||||||
|
) {
|
||||||
|
args.push(
|
||||||
|
transformTimestampArgument(fromTimestamp),
|
||||||
|
transformTimestampArgument(toTimestamp)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (options?.LATEST) {
|
||||||
|
args.push('LATEST');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options?.FILTER_BY_TS) {
|
||||||
|
args.push('FILTER_BY_TS');
|
||||||
|
for (const timestamp of options.FILTER_BY_TS) {
|
||||||
|
args.push(transformTimestampArgument(timestamp));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options?.FILTER_BY_VALUE) {
|
||||||
|
args.push(
|
||||||
|
'FILTER_BY_VALUE',
|
||||||
|
options.FILTER_BY_VALUE.min.toString(),
|
||||||
|
options.FILTER_BY_VALUE.max.toString()
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options?.COUNT !== undefined) {
|
||||||
|
args.push('COUNT', options.COUNT.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options?.AGGREGATION) {
|
||||||
|
if (options?.ALIGN !== undefined) {
|
||||||
|
args.push('ALIGN', transformTimestampArgument(options.ALIGN));
|
||||||
|
}
|
||||||
|
|
||||||
|
args.push(
|
||||||
|
'AGGREGATION',
|
||||||
|
options.AGGREGATION.type,
|
||||||
|
transformTimestampArgument(options.AGGREGATION.timeBucket)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (options.AGGREGATION.BUCKETTIMESTAMP) {
|
||||||
|
args.push(
|
||||||
|
'BUCKETTIMESTAMP',
|
||||||
|
options.AGGREGATION.BUCKETTIMESTAMP
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.AGGREGATION.EMPTY) {
|
||||||
|
args.push('EMPTY');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function transformReply(reply: Array<SampleRawReply>): Array<SampleReply> {
|
export function transformRangeArguments(
|
||||||
return transformRangeReply(reply);
|
command: RedisArgument,
|
||||||
|
key: RedisArgument,
|
||||||
|
fromTimestamp: Timestamp,
|
||||||
|
toTimestamp: Timestamp,
|
||||||
|
options?: TsRangeOptions
|
||||||
|
) {
|
||||||
|
return pushRangeArguments(
|
||||||
|
[command, key],
|
||||||
|
fromTimestamp,
|
||||||
|
toTimestamp,
|
||||||
|
options
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
FIRST_KEY_INDEX: 1,
|
||||||
|
IS_READ_ONLY: true,
|
||||||
|
transformArguments: transformRangeArguments.bind(undefined, 'TS.RANGE'),
|
||||||
|
// TODO
|
||||||
|
// import { SampleReply, transformRangeReply } from '.';
|
||||||
|
// export function transformReply(reply: Array<SampleRawReply>): Array<SampleReply> {
|
||||||
|
// return transformRangeReply(reply);
|
||||||
|
// }
|
||||||
|
transformReply: undefined as unknown as () => any
|
||||||
|
} as const satisfies Command;
|
||||||
|
|
||||||
|
@@ -4,103 +4,101 @@ import { transformArguments } from './REVRANGE';
|
|||||||
import { TimeSeriesAggregationType } from '.';
|
import { TimeSeriesAggregationType } from '.';
|
||||||
|
|
||||||
describe('TS.REVRANGE', () => {
|
describe('TS.REVRANGE', () => {
|
||||||
describe('transformArguments', () => {
|
describe('transformArguments', () => {
|
||||||
it('without options', () => {
|
it('without options', () => {
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
transformArguments('key', '-', '+'),
|
transformArguments('key', '-', '+'),
|
||||||
['TS.REVRANGE', 'key', '-', '+']
|
['TS.REVRANGE', 'key', '-', '+']
|
||||||
);
|
);
|
||||||
});
|
|
||||||
|
|
||||||
it('with FILTER_BY_TS', () => {
|
|
||||||
assert.deepEqual(
|
|
||||||
transformArguments('key', '-', '+', {
|
|
||||||
FILTER_BY_TS: [0]
|
|
||||||
}),
|
|
||||||
['TS.REVRANGE', 'key', '-', '+', 'FILTER_BY_TS', '0']
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('with FILTER_BY_VALUE', () => {
|
|
||||||
assert.deepEqual(
|
|
||||||
transformArguments('key', '-', '+', {
|
|
||||||
FILTER_BY_VALUE: {
|
|
||||||
min: 1,
|
|
||||||
max: 2
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
['TS.REVRANGE', 'key', '-', '+', 'FILTER_BY_VALUE', '1', '2']
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('with COUNT', () => {
|
|
||||||
assert.deepEqual(
|
|
||||||
transformArguments('key', '-', '+', {
|
|
||||||
COUNT: 1
|
|
||||||
}),
|
|
||||||
['TS.REVRANGE', 'key', '-', '+', 'COUNT', '1']
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('with ALIGN', () => {
|
|
||||||
assert.deepEqual(
|
|
||||||
transformArguments('key', '-', '+', {
|
|
||||||
ALIGN: '-'
|
|
||||||
}),
|
|
||||||
['TS.REVRANGE', 'key', '-', '+', 'ALIGN', '-']
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('with AGGREGATION', () => {
|
|
||||||
assert.deepEqual(
|
|
||||||
transformArguments('key', '-', '+', {
|
|
||||||
AGGREGATION: {
|
|
||||||
type: TimeSeriesAggregationType.AVERAGE,
|
|
||||||
timeBucket: 1
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
['TS.REVRANGE', 'key', '-', '+', 'AGGREGATION', 'AVG', '1']
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('with FILTER_BY_TS, FILTER_BY_VALUE, COUNT, ALIGN, AGGREGATION', () => {
|
|
||||||
assert.deepEqual(
|
|
||||||
transformArguments('key', '-', '+', {
|
|
||||||
FILTER_BY_TS: [0],
|
|
||||||
FILTER_BY_VALUE: {
|
|
||||||
min: 1,
|
|
||||||
max: 2
|
|
||||||
},
|
|
||||||
COUNT: 1,
|
|
||||||
ALIGN: '-',
|
|
||||||
AGGREGATION: {
|
|
||||||
type: TimeSeriesAggregationType.AVERAGE,
|
|
||||||
timeBucket: 1
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
[
|
|
||||||
'TS.REVRANGE', 'key', '-', '+', 'FILTER_BY_TS', '0', 'FILTER_BY_VALUE',
|
|
||||||
'1', '2', 'COUNT', '1', 'ALIGN', '-', 'AGGREGATION', 'AVG', '1'
|
|
||||||
]
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
testUtils.testWithClient('client.ts.revRange', async client => {
|
it('with FILTER_BY_TS', () => {
|
||||||
await Promise.all([
|
assert.deepEqual(
|
||||||
client.ts.add('key', 0, 1),
|
transformArguments('key', '-', '+', {
|
||||||
client.ts.add('key', 1, 2)
|
FILTER_BY_TS: [0]
|
||||||
]);
|
}),
|
||||||
|
['TS.REVRANGE', 'key', '-', '+', 'FILTER_BY_TS', '0']
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
assert.deepEqual(
|
it('with FILTER_BY_VALUE', () => {
|
||||||
await client.ts.revRange('key', '-', '+'),
|
assert.deepEqual(
|
||||||
[{
|
transformArguments('key', '-', '+', {
|
||||||
timestamp: 1,
|
FILTER_BY_VALUE: {
|
||||||
value: 2
|
min: 1,
|
||||||
}, {
|
max: 2
|
||||||
timestamp: 0,
|
}
|
||||||
value: 1
|
}),
|
||||||
}]
|
['TS.REVRANGE', 'key', '-', '+', 'FILTER_BY_VALUE', '1', '2']
|
||||||
);
|
);
|
||||||
}, GLOBAL.SERVERS.OPEN);
|
});
|
||||||
|
|
||||||
|
it('with COUNT', () => {
|
||||||
|
assert.deepEqual(
|
||||||
|
transformArguments('key', '-', '+', {
|
||||||
|
COUNT: 1
|
||||||
|
}),
|
||||||
|
['TS.REVRANGE', 'key', '-', '+', 'COUNT', '1']
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('with ALIGN', () => {
|
||||||
|
assert.deepEqual(
|
||||||
|
transformArguments('key', '-', '+', {
|
||||||
|
ALIGN: '-'
|
||||||
|
}),
|
||||||
|
['TS.REVRANGE', 'key', '-', '+', 'ALIGN', '-']
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('with AGGREGATION', () => {
|
||||||
|
assert.deepEqual(
|
||||||
|
transformArguments('key', '-', '+', {
|
||||||
|
AGGREGATION: {
|
||||||
|
type: TimeSeriesAggregationType.AVERAGE,
|
||||||
|
timeBucket: 1
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
['TS.REVRANGE', 'key', '-', '+', 'AGGREGATION', 'AVG', '1']
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('with FILTER_BY_TS, FILTER_BY_VALUE, COUNT, ALIGN, AGGREGATION', () => {
|
||||||
|
assert.deepEqual(
|
||||||
|
transformArguments('key', '-', '+', {
|
||||||
|
FILTER_BY_TS: [0],
|
||||||
|
FILTER_BY_VALUE: {
|
||||||
|
min: 1,
|
||||||
|
max: 2
|
||||||
|
},
|
||||||
|
COUNT: 1,
|
||||||
|
ALIGN: '-',
|
||||||
|
AGGREGATION: {
|
||||||
|
type: TimeSeriesAggregationType.AVERAGE,
|
||||||
|
timeBucket: 1
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
[
|
||||||
|
'TS.REVRANGE', 'key', '-', '+', 'FILTER_BY_TS', '0', 'FILTER_BY_VALUE',
|
||||||
|
'1', '2', 'COUNT', '1', 'ALIGN', '-', 'AGGREGATION', 'AVG', '1'
|
||||||
|
]
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
testUtils.testWithClient('client.ts.revRange', async client => {
|
||||||
|
const [, , reply] = await Promise.all([
|
||||||
|
client.ts.add('key', 0, 1),
|
||||||
|
client.ts.add('key', 1, 2),
|
||||||
|
client.ts.revRange('key', '-', '+')
|
||||||
|
]);
|
||||||
|
|
||||||
|
assert.deepEqual(reply, [{
|
||||||
|
timestamp: 1,
|
||||||
|
value: 2
|
||||||
|
}, {
|
||||||
|
timestamp: 0,
|
||||||
|
value: 1
|
||||||
|
}]);
|
||||||
|
}, GLOBAL.SERVERS.OPEN);
|
||||||
});
|
});
|
||||||
|
@@ -1,24 +1,9 @@
|
|||||||
import { RedisCommandArguments } from '@redis/client/dist/lib/commands';
|
import { Command } from '@redis/client/dist/lib/RESP/types';
|
||||||
import { RangeOptions, Timestamp, pushRangeArguments, SampleRawReply, SampleReply, transformRangeReply } from '.';
|
import RANGE, { transformRangeArguments } from './RANGE';
|
||||||
|
|
||||||
export const FIRST_KEY_INDEX = 1;
|
export default {
|
||||||
|
FIRST_KEY_INDEX: RANGE.FIRST_KEY_INDEX,
|
||||||
export const IS_READ_ONLY = true;
|
IS_READ_ONLY: RANGE.IS_READ_ONLY,
|
||||||
|
transformArguments: transformRangeArguments.bind(undefined, 'TS.REVRANGE'),
|
||||||
export function transformArguments(
|
transformReply: RANGE.transformReply
|
||||||
key: string,
|
} as const satisfies Command;
|
||||||
fromTimestamp: Timestamp,
|
|
||||||
toTimestamp: Timestamp,
|
|
||||||
options?: RangeOptions
|
|
||||||
): RedisCommandArguments {
|
|
||||||
return pushRangeArguments(
|
|
||||||
['TS.REVRANGE', key],
|
|
||||||
fromTimestamp,
|
|
||||||
toTimestamp,
|
|
||||||
options
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function transformReply(reply: Array<SampleRawReply>): Array<SampleReply> {
|
|
||||||
return transformRangeReply(reply);
|
|
||||||
}
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import type { RedisArgument, RedisCommands } from '@redis/client/dist/lib/RESP/types';
|
import type { BlobStringReply, CommandArguments, DoubleReply, NumberReply, RedisArgument, RedisCommands, TuplesReply, UnwrapReply } from '@redis/client/dist/lib/RESP/types';
|
||||||
import ADD from './ADD';
|
import ADD from './ADD';
|
||||||
import ALTER from './ALTER';
|
import ALTER from './ALTER';
|
||||||
import CREATE from './CREATE';
|
import CREATE from './CREATE';
|
||||||
@@ -11,15 +11,16 @@ import INCRBY from './INCRBY';
|
|||||||
// import INFO_DEBUG from './INFO_DEBUG';
|
// import INFO_DEBUG from './INFO_DEBUG';
|
||||||
// import INFO from './INFO';
|
// import INFO from './INFO';
|
||||||
import MADD from './MADD';
|
import MADD from './MADD';
|
||||||
// import MGET from './MGET';
|
import MGET_WITHLABELS from './MGET_WITHLABELS';
|
||||||
// import MGET_WITHLABELS from './MGET_WITHLABELS';
|
import MGET from './MGET';
|
||||||
// import QUERYINDEX from './QUERYINDEX';
|
import MRANGE_WITHLABELS from './MRANGE_WITHLABELS';
|
||||||
// import RANGE from './RANGE';
|
import MRANGE from './MRANGE';
|
||||||
// import REVRANGE from './REVRANGE';
|
import MREVRANGE_WITHLABELS from './MREVRANGE_WITHLABELS';
|
||||||
// import MRANGE from './MRANGE';
|
import MREVRANGE from './MREVRANGE';
|
||||||
// import MRANGE_WITHLABELS from './MRANGE_WITHLABELS';
|
import QUERYINDEX from './QUERYINDEX';
|
||||||
// import MREVRANGE from './MREVRANGE';
|
import RANGE from './RANGE';
|
||||||
// import MREVRANGE_WITHLABELS from './MREVRANGE_WITHLABELS';
|
import REVRANGE from './REVRANGE';
|
||||||
|
import { RedisVariadicArgument, pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
ADD,
|
ADD,
|
||||||
@@ -46,24 +47,24 @@ export default {
|
|||||||
// info: INFO,
|
// info: INFO,
|
||||||
MADD,
|
MADD,
|
||||||
mAdd: MADD,
|
mAdd: MADD,
|
||||||
// MGET,
|
MGET_WITHLABELS,
|
||||||
// mGet: MGET,
|
mGetWithLabels: MGET_WITHLABELS,
|
||||||
// MGET_WITHLABELS,
|
MGET,
|
||||||
// mGetWithLabels: MGET_WITHLABELS,
|
mGet: MGET,
|
||||||
// QUERYINDEX,
|
MRANGE_WITHLABELS,
|
||||||
// queryIndex: QUERYINDEX,
|
mRangeWithLabels: MRANGE_WITHLABELS,
|
||||||
// RANGE,
|
MRANGE,
|
||||||
// range: RANGE,
|
mRange: MRANGE,
|
||||||
// REVRANGE,
|
MREVRANGE_WITHLABELS,
|
||||||
// revRange: REVRANGE,
|
mRevRangeWithLabels: MREVRANGE_WITHLABELS,
|
||||||
// MRANGE,
|
MREVRANGE,
|
||||||
// mRange: MRANGE,
|
mRevRange: MREVRANGE,
|
||||||
// MRANGE_WITHLABELS,
|
QUERYINDEX,
|
||||||
// mRangeWithLabels: MRANGE_WITHLABELS,
|
queryIndex: QUERYINDEX,
|
||||||
// MREVRANGE,
|
RANGE,
|
||||||
// mRevRange: MREVRANGE,
|
range: RANGE,
|
||||||
// MREVRANGE_WITHLABELS,
|
REVRANGE,
|
||||||
// mRevRangeWithLabels: MREVRANGE_WITHLABELS
|
revRange: REVRANGE
|
||||||
} as const satisfies RedisCommands;
|
} as const satisfies RedisCommands;
|
||||||
|
|
||||||
export function pushRetentionArgument(args: Array<RedisArgument>, retention?: number) {
|
export function pushRetentionArgument(args: Array<RedisArgument>, retention?: number) {
|
||||||
@@ -148,20 +149,22 @@ export function pushLabelsArgument(args: Array<RedisArgument>, labels?: Labels)
|
|||||||
// return labels
|
// return labels
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
export const transformSampleReply = {
|
||||||
// export type SampleRawReply = [timestamp: number, value: string];
|
2(reply: TuplesReply<[timestamp: NumberReply, value: BlobStringReply]>) {
|
||||||
|
const [timestamp, value] = reply as unknown as UnwrapReply<typeof reply>;
|
||||||
// export interface SampleReply {
|
return {
|
||||||
// timestamp: number;
|
timestamp,
|
||||||
// value: number;
|
value: Number(value)
|
||||||
// }
|
};
|
||||||
|
},
|
||||||
// export function transformSampleReply(reply: SampleRawReply): SampleReply {
|
3(reply: TuplesReply<[timestamp: NumberReply, value: DoubleReply]>) {
|
||||||
// return {
|
const [timestamp, value] = reply as unknown as UnwrapReply<typeof reply>;
|
||||||
// timestamp: reply[0],
|
return {
|
||||||
// value: Number(reply[1])
|
timestamp,
|
||||||
// };
|
value
|
||||||
// }
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// export enum TimeSeriesBucketTimestamp {
|
// export enum TimeSeriesBucketTimestamp {
|
||||||
// LOW = '-',
|
// LOW = '-',
|
||||||
@@ -293,16 +296,15 @@ export function pushLabelsArgument(args: Array<RedisArgument>, labels?: Labels)
|
|||||||
|
|
||||||
// export type SelectedLabels = string | Array<string>;
|
// export type SelectedLabels = string | Array<string>;
|
||||||
|
|
||||||
// export function pushWithLabelsArgument(args: RedisCommandArguments, selectedLabels?: SelectedLabels): RedisCommandArguments {
|
export function pushWithLabelsArgument(args: CommandArguments, selectedLabels?: RedisVariadicArgument) {
|
||||||
// if (!selectedLabels) {
|
if (!selectedLabels) {
|
||||||
// args.push('WITHLABELS');
|
args.push('WITHLABELS');
|
||||||
// } else {
|
return args;
|
||||||
// args.push('SELECTED_LABELS');
|
} else {
|
||||||
// args = pushVariadicArguments(args, selectedLabels);
|
args.push('SELECTED_LABELS');
|
||||||
// }
|
return pushVariadicArguments(args, selectedLabels);
|
||||||
|
}
|
||||||
// return args;
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
// export interface MRangeWithLabelsOptions extends MRangeOptions {
|
// export interface MRangeWithLabelsOptions extends MRangeOptions {
|
||||||
// SELECTED_LABELS?: SelectedLabels;
|
// SELECTED_LABELS?: SelectedLabels;
|
||||||
|
@@ -4,8 +4,8 @@ export {
|
|||||||
TIME_SERIES_ENCODING,
|
TIME_SERIES_ENCODING,
|
||||||
TimeSeriesEncoding,
|
TimeSeriesEncoding,
|
||||||
TIME_SERIES_DUPLICATE_POLICIES,
|
TIME_SERIES_DUPLICATE_POLICIES,
|
||||||
TimeSeriesDuplicatePolicies,
|
TimeSeriesDuplicatePolicies
|
||||||
// TimeSeriesBucketTimestamp
|
|
||||||
} from './commands';
|
} from './commands';
|
||||||
|
|
||||||
export { TIME_SERIES_AGGREGATION_TYPE, TimeSeriesAggregationType } from './commands/CREATERULE';
|
export { TIME_SERIES_AGGREGATION_TYPE, TimeSeriesAggregationType } from './commands/CREATERULE';
|
||||||
|
export { TIME_SERIES_BUCKET_TIMESTAMP, TimeSeriesBucketTimestamp } from './commands/RANGE';
|
||||||
|
@@ -5,7 +5,8 @@
|
|||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
"types": "./dist/index.d.ts",
|
"types": "./dist/index.d.ts",
|
||||||
"files": [
|
"files": [
|
||||||
"dist/"
|
"dist/",
|
||||||
|
"!dist/tsconfig.tsbuildinfo"
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "nyc -r text-summary -r lcov mocha -r source-map-support/register -r ts-node/register './lib/**/*.spec.ts'"
|
"test": "nyc -r text-summary -r lcov mocha -r source-map-support/register -r ts-node/register './lib/**/*.spec.ts'"
|
||||||
|
Reference in New Issue
Block a user