Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions pkg/commands/geo_hash.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { describe, expect, test } from "bun:test";
import { newHttpClient } from "../test-utils.ts";

import { GeoAddCommand } from "./geo_add.ts";
import { GeoHashCommand } from "./geo_hash.ts";

const client = newHttpClient();

describe("GEOHASH tests", () => {
test("should accept two member array and return valid hash", async () => {
const key = "Sicily";
const members = ["Palermo", "Catania"];
await new GeoAddCommand([
key,
{ longitude: 13.361389, latitude: 38.115556, member: members[0] },
{ longitude: 15.087269, latitude: 37.502669, member: members[1] },
]).exec(client);

const response = await new GeoHashCommand([key, members]).exec(client);
expect(response.length).toEqual(2);
});

test("should accept three different string members and return valid hash", async () => {
const key = "Sicily";
const members = ["Palermo", "Catania", "Marsala"];
await new GeoAddCommand([
key,
{ longitude: 13.361389, latitude: 38.115556, member: members[0] },
{ longitude: 15.087269, latitude: 37.502669, member: members[1] },
{ longitude: 12.4372, latitude: 37.7981, member: members[2] },
]).exec(client);

const response = await new GeoHashCommand([key, "Palermo", "Catania", "Marsala"]).exec(client);
expect(response.length).toEqual(3);
});

test("should accept two objects as members", async () => {
const key = "Sicily";
const members = [{ name: "Palermo" }, { name: "Catania" }];
await new GeoAddCommand([
key,
{ longitude: 13.361389, latitude: 38.115556, member: members[0] },
{ longitude: 15.087269, latitude: 37.502669, member: members[1] },
]).exec(client);

const response = await new GeoHashCommand([key, members]).exec(client);
expect(response.length).toBe(2);
});
});
20 changes: 20 additions & 0 deletions pkg/commands/geo_hash.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Command, CommandOptions } from "./command.ts";

/**
* @see https://redis.io/commands/geohash
*/
export class GeoHashCommand<TMember = string>
extends Command<(string | null)[], (string | null)[]> {
constructor(
cmd: [string, ...TMember[] | TMember[]],
opts?: CommandOptions<(string | null)[], (string | null)[]>,
) {
const [key] = cmd;
// Check if the second argument is an array of strings (members).
// If it is, use it directly; if not, it means the members were passed individually,
// so we slice the cmd from the second element onwards to get the members.
const members = Array.isArray(cmd[1]) ? cmd[1] : cmd.slice(1);

super(["GEOHASH", key, ...members], opts);
}
}
1 change: 1 addition & 0 deletions pkg/commands/mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export * from "./flushdb";
export * from "./geo_add";
export * from "./geo_dist";
export * from "./geo_pos";
export * from "./geo_hash";
export * from "./get";
export * from "./getbit";
export * from "./getdel";
Expand Down
29 changes: 18 additions & 11 deletions pkg/pipeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
ExpireCommand,
FlushAllCommand,
FlushDBCommand,
GeoHashCommand,
GeoAddCommand,
GeoDistCommand,
GeoPosCommand,
Expand Down Expand Up @@ -231,7 +232,7 @@ export class Pipeline<TCommands extends Command<any, any>[] = []> {
exec = async <
TCommandResults extends unknown[] = [] extends TCommands
? unknown[]
: InferResponseData<TCommands>,
: InferResponseData<TCommands>
>(): Promise<TCommandResults> => {
if (this.commands.length === 0) {
throw new Error("Pipeline is empty");
Expand All @@ -245,7 +246,7 @@ export class Pipeline<TCommands extends Command<any, any>[] = []> {
return res.map(({ error, result }, i) => {
if (error) {
throw new UpstashError(
`Command ${i + 1} [ ${this.commands[i].command[0]} ] failed: ${error}`,
`Command ${i + 1} [ ${this.commands[i].command[0]} ] failed: ${error}`
);
}

Expand Down Expand Up @@ -299,7 +300,7 @@ export class Pipeline<TCommands extends Command<any, any>[] = []> {
...sourceKeys: string[]
) =>
this.chain(
new BitOpCommand([op as any, destinationKey, sourceKey, ...sourceKeys], this.commandOptions),
new BitOpCommand([op as any, destinationKey, sourceKey, ...sourceKeys], this.commandOptions)
);

/**
Expand Down Expand Up @@ -481,7 +482,7 @@ export class Pipeline<TCommands extends Command<any, any>[] = []> {
hrandfield = <TData extends string | string[] | Record<string, unknown>>(
key: string,
count?: number,
withValues?: boolean,
withValues?: boolean
) =>
this.chain(new HRandFieldCommand<TData>([key, count, withValues] as any, this.commandOptions));

Expand Down Expand Up @@ -899,23 +900,23 @@ export class Pipeline<TCommands extends Command<any, any>[] = []> {
| [
key: string,
opts: ZAddCommandOptions | ZAddCommandOptionsWithIncr,
...scoreMemberPairs: [ScoreMember<TData>, ...ScoreMember<TData>[]],
...scoreMemberPairs: [ScoreMember<TData>, ...ScoreMember<TData>[]]
]
) => {
if ("score" in args[1]) {
return this.chain(
new ZAddCommand<TData>(
[args[0], args[1] as ScoreMember<TData>, ...(args.slice(2) as any)],
this.commandOptions,
),
this.commandOptions
)
);
}

return this.chain(
new ZAddCommand<TData>(
[args[0], args[1] as any, ...(args.slice(2) as any)],
this.commandOptions,
),
this.commandOptions
)
);
};

Expand Down Expand Up @@ -977,13 +978,13 @@ export class Pipeline<TCommands extends Command<any, any>[] = []> {
key: string,
min: `(${string}` | `[${string}` | "-" | "+",
max: `(${string}` | `[${string}` | "-" | "+",
opts: { byLex: true } & ZRangeCommandOptions,
opts: { byLex: true } & ZRangeCommandOptions
]
| [
key: string,
min: number | `(${number}` | "-inf" | "+inf",
max: number | `(${number}` | "-inf" | "+inf",
opts: { byScore: true } & ZRangeCommandOptions,
opts: { byScore: true } & ZRangeCommandOptions
]
) => this.chain(new ZRangeCommand<TData>(args as any, this.commandOptions));

Expand Down Expand Up @@ -1124,6 +1125,12 @@ export class Pipeline<TCommands extends Command<any, any>[] = []> {
geopos: (...args: CommandArgs<typeof GeoPosCommand>) =>
new GeoPosCommand(args, this.commandOptions).exec(this.client),

/**
* @see https://redis.io/commands/geohash
*/
geohash: (...args: CommandArgs<typeof GeoHashCommand>) =>
new GeoHashCommand(args, this.commandOptions).exec(this.client),

/**
* @see https://redis.io/commands/json.get
*/
Expand Down
27 changes: 17 additions & 10 deletions pkg/redis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
FlushDBCommand,
GeoAddCommand,
GeoDistCommand,
GeoHashCommand,
GeoPosCommand,
GetBitCommand,
GetCommand,
Expand Down Expand Up @@ -262,6 +263,12 @@ export class Redis {
geodist: (...args: CommandArgs<typeof GeoDistCommand>) =>
new GeoDistCommand(args, this.opts).exec(this.client),

/**
* @see https://redis.io/commands/geohash
*/
geohash: (...args: CommandArgs<typeof GeoHashCommand>) =>
new GeoHashCommand(args, this.opts).exec(this.client),

/**
* @see https://redis.io/commands/json.get
*/
Expand Down Expand Up @@ -341,8 +348,8 @@ export class Redis {
use = <TResult = unknown>(
middleware: (
r: UpstashRequest,
next: <TResult = unknown>(req: UpstashRequest) => Promise<UpstashResponse<TResult>>,
) => Promise<UpstashResponse<TResult>>,
next: <TResult = unknown>(req: UpstashRequest) => Promise<UpstashResponse<TResult>>
) => Promise<UpstashResponse<TResult>>
) => {
const makeRequest = this.client.request.bind(this.client);
this.client.request = (req: UpstashRequest) => middleware(req, makeRequest) as any;
Expand Down Expand Up @@ -425,7 +432,7 @@ export class Redis {
...sourceKeys: string[]
) =>
new BitOpCommand([op as any, destinationKey, sourceKey, ...sourceKeys], this.opts).exec(
this.client,
this.client
);

/**
Expand Down Expand Up @@ -605,12 +612,12 @@ export class Redis {
<TData extends Record<string, unknown>>(
key: string,
count: number,
withValues: boolean,
withValues: boolean
): Promise<Partial<TData>>;
} = <TData extends string | string[] | Record<string, unknown>>(
key: string,
count?: number,
withValues?: boolean,
withValues?: boolean
) => new HRandFieldCommand<TData>([key, count, withValues] as any, this.opts).exec(this.client);

/**
Expand Down Expand Up @@ -1039,19 +1046,19 @@ export class Redis {
| [
key: string,
opts: ZAddCommandOptions | ZAddCommandOptionsWithIncr,
...scoreMemberPairs: [ScoreMember<TData>, ...ScoreMember<TData>[]],
...scoreMemberPairs: [ScoreMember<TData>, ...ScoreMember<TData>[]]
]
) => {
if ("score" in args[1]) {
return new ZAddCommand<TData>(
[args[0], args[1] as ScoreMember<TData>, ...(args.slice(2) as any)],
this.opts,
this.opts
).exec(this.client);
}

return new ZAddCommand<TData>(
[args[0], args[1] as any, ...(args.slice(2) as any)],
this.opts,
this.opts
).exec(this.client);
};
/**
Expand Down Expand Up @@ -1118,13 +1125,13 @@ export class Redis {
key: string,
min: `(${string}` | `[${string}` | "-" | "+",
max: `(${string}` | `[${string}` | "-" | "+",
opts: { byLex: true } & ZRangeCommandOptions,
opts: { byLex: true } & ZRangeCommandOptions
]
| [
key: string,
min: number | `(${number}` | "-inf" | "+inf",
max: number | `(${number}` | "-inf" | "+inf",
opts: { byScore: true } & ZRangeCommandOptions,
opts: { byScore: true } & ZRangeCommandOptions
]
) => new ZRangeCommand<TData>(args as any, this.opts).exec(this.client);

Expand Down