fix(redis): recognize OBJECT subcommands
This commit is contained in:
parent
08d73ce371
commit
7ca5e76c14
|
|
@ -115,11 +115,13 @@ const RAW_COMMANDS: Record<string, Spec> = {
|
|||
KEYS: [2, "generic", "blocked"],
|
||||
MIGRATE: [-6, "generic", "blocked"],
|
||||
MOVE: [3, "generic", "confirm"],
|
||||
OBJECT_ENCODING: [3, "generic"],
|
||||
OBJECT_FREQ: [3, "generic"],
|
||||
OBJECT_IDLETIME: [3, "generic"],
|
||||
OBJECT_REFCOUNT: [3, "generic"],
|
||||
OBJECT_HELP: [2, "generic"],
|
||||
// Redis exposes OBJECT operations as space-delimited subcommands; keep these
|
||||
// keys aligned with COMMAND metadata so shared parsing and completion work.
|
||||
"OBJECT ENCODING": [3, "generic"],
|
||||
"OBJECT FREQ": [3, "generic"],
|
||||
"OBJECT IDLETIME": [3, "generic"],
|
||||
"OBJECT REFCOUNT": [3, "generic"],
|
||||
"OBJECT HELP": [2, "generic"],
|
||||
PERSIST: [2, "generic", "confirm"],
|
||||
PEXPIRE: [-3, "generic", "confirm"],
|
||||
PEXPIREAT: [-3, "generic", "confirm"],
|
||||
|
|
|
|||
|
|
@ -59,6 +59,25 @@ test("resolveRedisCommandSpec resolves subcommand then main", () => {
|
|||
assert.equal(main?.group, "string");
|
||||
});
|
||||
|
||||
test("resolveRedisCommandSpec resolves every OBJECT subcommand with Redis arity", () => {
|
||||
const expectedArities = new Map([
|
||||
["ENCODING", 3],
|
||||
["FREQ", 3],
|
||||
["IDLETIME", 3],
|
||||
["REFCOUNT", 3],
|
||||
["HELP", 2],
|
||||
]);
|
||||
|
||||
for (const [subcommand, arity] of expectedArities) {
|
||||
const spec = resolveRedisCommandSpec(["OBJECT", subcommand]);
|
||||
assert.ok(spec, `OBJECT ${subcommand} should resolve`);
|
||||
assert.equal(spec.arity, arity);
|
||||
assert.equal(spec.group, "generic");
|
||||
}
|
||||
|
||||
assert.equal(resolveRedisCommandSpec(["OBJECT", "UNKNOWN"]), undefined);
|
||||
});
|
||||
|
||||
test("normal writes do not require confirmation but destructive commands do", () => {
|
||||
assert.equal(resolveRedisCommandSpec(["SET"])?.safety, "write");
|
||||
assert.equal(resolveRedisCommandSpec(["HSET"])?.safety, "write");
|
||||
|
|
|
|||
|
|
@ -1,12 +1,6 @@
|
|||
import assert from "node:assert/strict";
|
||||
import { test } from "vitest";
|
||||
import {
|
||||
buildRedisCompletionItems,
|
||||
getRedisCompletionContext,
|
||||
getRedisCompletionResultValidFor,
|
||||
shouldAutoOpenRedisCompletion,
|
||||
takesKeyArgument,
|
||||
} from "../../apps/desktop/src/lib/redis/redisCompletion.ts";
|
||||
import { buildRedisCompletionItems, getRedisCompletionContext, getRedisCompletionResultValidFor, shouldAutoOpenRedisCompletion, takesKeyArgument } from "../../apps/desktop/src/lib/redis/redisCompletion.ts";
|
||||
|
||||
function labels(items: { label: string }[]): string[] {
|
||||
return items.map((item) => item.label);
|
||||
|
|
@ -60,6 +54,16 @@ test("subcommand mode: filters subcommands by prefix", () => {
|
|||
assert.ok(!names.includes("DESTROY"));
|
||||
});
|
||||
|
||||
test("OBJECT completion uses Redis space-delimited subcommands", () => {
|
||||
const commandNames = labels(buildRedisCompletionItems("OBJECT", 6));
|
||||
assert.ok(commandNames.includes("OBJECT"));
|
||||
assert.ok(!commandNames.some((name) => name.startsWith("OBJECT_")));
|
||||
|
||||
const subcommands = labels(buildRedisCompletionItems("OBJECT ", 7));
|
||||
assert.deepEqual(new Set(subcommands), new Set(["ENCODING", "FREQ", "IDLETIME", "REFCOUNT", "HELP"]));
|
||||
assert.ok(!subcommands.some((name) => name.includes("_")));
|
||||
});
|
||||
|
||||
test("argument mode: offers key names for key-taking commands", () => {
|
||||
const items = buildRedisCompletionItems("GET ", 4, { keys: ["user:1", "user:2", "config:db"] });
|
||||
const names = labels(items);
|
||||
|
|
|
|||
|
|
@ -90,6 +90,24 @@ test("subcommands resolve via MAIN SUB key", () => {
|
|||
assert.equal(diags.length, 0);
|
||||
});
|
||||
|
||||
test("accepts all Redis OBJECT subcommands", () => {
|
||||
for (const command of ["OBJECT ENCODING key", "OBJECT FREQ key", "OBJECT IDLETIME key", "OBJECT REFCOUNT key", "OBJECT HELP"]) {
|
||||
assert.deepEqual(messages(command), [], `${command} should be valid`);
|
||||
}
|
||||
});
|
||||
|
||||
test("validates OBJECT subcommand arity and rejects unknown subcommands", () => {
|
||||
for (const command of ["OBJECT ENCODING", "OBJECT FREQ", "OBJECT IDLETIME", "OBJECT REFCOUNT", "OBJECT HELP extra"]) {
|
||||
const diags = buildRedisSyntaxDiagnostics(command);
|
||||
assert.equal(diags.length, 1, `${command} should have one diagnostic`);
|
||||
assert.match(diags[0].message, /Wrong number of arguments for 'OBJECT'/);
|
||||
}
|
||||
|
||||
const unknown = buildRedisSyntaxDiagnostics("OBJECT UNKNOWN key");
|
||||
assert.equal(unknown.length, 1);
|
||||
assert.match(unknown[0].message, /Unknown command 'OBJECT'/);
|
||||
});
|
||||
|
||||
test("treats command names case-insensitively", () => {
|
||||
assert.deepEqual(messages("get foo"), []);
|
||||
const setDiag = buildRedisSyntaxDiagnostics("Set a b");
|
||||
|
|
|
|||
Loading…
Reference in New Issue