kami-redis 2.0.2 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +2365 -0
- package/dist/index.js +1 -241
- package/package.json +7 -2
- package/.changeset/README.md +0 -8
- package/.changeset/config.json +0 -11
- package/.github/workflows/main.yml +0 -17
- package/.github/workflows/publish.yml +0 -32
- package/.vscode/settings.json +0 -51
- package/CHANGELOG.md +0 -19
- package/bun.lock +0 -1237
- package/eslint.config.js +0 -28
- package/src/index.ts +0 -75
- package/src/utils/clean-up.ts +0 -3
- package/src/utils/format-value.ts +0 -16
- package/src/utils/get-value.ts +0 -18
- package/src/utils/graceful-exit.ts +0 -24
- package/src/utils/is-redis-url.ts +0 -23
- package/src/utils/prompt-for-key.ts +0 -30
- package/src/utils/view-key.ts +0 -95
- package/tsconfig.json +0 -27
- package/tsup.config.ts +0 -8
package/eslint.config.js
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import antfu from "@antfu/eslint-config";
|
|
2
|
-
|
|
3
|
-
export default antfu({
|
|
4
|
-
type: "app",
|
|
5
|
-
typescript: true,
|
|
6
|
-
formatters: true,
|
|
7
|
-
stylistic: {
|
|
8
|
-
indent: 2,
|
|
9
|
-
semi: true,
|
|
10
|
-
quotes: "double",
|
|
11
|
-
},
|
|
12
|
-
}, {
|
|
13
|
-
rules: {
|
|
14
|
-
"ts/no-redeclare": "off",
|
|
15
|
-
"ts/consistent-type-definitions": ["error", "type"],
|
|
16
|
-
"no-console": ["off"],
|
|
17
|
-
"antfu/no-top-level-await": ["off"],
|
|
18
|
-
"node/prefer-global/process": ["off"],
|
|
19
|
-
"node/no-process-env": ["off"],
|
|
20
|
-
"perfectionist/sort-imports": ["error", {
|
|
21
|
-
tsconfigRootDir: ".",
|
|
22
|
-
}],
|
|
23
|
-
"unicorn/filename-case": ["error", {
|
|
24
|
-
case: "kebabCase",
|
|
25
|
-
ignore: ["README.md"],
|
|
26
|
-
}],
|
|
27
|
-
},
|
|
28
|
-
});
|
package/src/index.ts
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/* eslint-disable style/no-tabs */
|
|
3
|
-
import meow from "meow";
|
|
4
|
-
import pc from "picocolors";
|
|
5
|
-
import { createClient } from "redis";
|
|
6
|
-
|
|
7
|
-
import { cleanup } from "./utils/clean-up";
|
|
8
|
-
import { gracefulExit } from "./utils/graceful-exit";
|
|
9
|
-
import { isRedisUrl } from "./utils/is-redis-url";
|
|
10
|
-
import { promptForKey } from "./utils/prompt-for-key";
|
|
11
|
-
import { viewKey } from "./utils/view-key";
|
|
12
|
-
|
|
13
|
-
const cli = meow(
|
|
14
|
-
`
|
|
15
|
-
Usage
|
|
16
|
-
kami-redis <url>
|
|
17
|
-
`,
|
|
18
|
-
{
|
|
19
|
-
importMeta: import.meta,
|
|
20
|
-
},
|
|
21
|
-
);
|
|
22
|
-
|
|
23
|
-
const [url] = cli.input;
|
|
24
|
-
|
|
25
|
-
if (!url) {
|
|
26
|
-
console.log(cli.help);
|
|
27
|
-
process.exit(1);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
if (!isRedisUrl(url)) {
|
|
31
|
-
console.log(cli.help);
|
|
32
|
-
console.log(pc.red("Provided URL is not a valid Redis URL"));
|
|
33
|
-
process.exit(1);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export const client = createClient({ url });
|
|
37
|
-
|
|
38
|
-
async function main() {
|
|
39
|
-
try {
|
|
40
|
-
cleanup();
|
|
41
|
-
await client.connect();
|
|
42
|
-
|
|
43
|
-
while (true) {
|
|
44
|
-
const selectedKey = await promptForKey();
|
|
45
|
-
if (!selectedKey) {
|
|
46
|
-
console.log("No keys in Redis!");
|
|
47
|
-
await client.quit();
|
|
48
|
-
process.exit(0);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const action = await viewKey(selectedKey);
|
|
52
|
-
|
|
53
|
-
if (action === "quit") {
|
|
54
|
-
await gracefulExit(0);
|
|
55
|
-
}
|
|
56
|
-
else if (action === "deleted") {
|
|
57
|
-
continue;
|
|
58
|
-
}
|
|
59
|
-
else if (action === "back") {
|
|
60
|
-
continue;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
catch (err) {
|
|
65
|
-
console.error(pc.red("Unexpected error:"), err);
|
|
66
|
-
try {
|
|
67
|
-
await client.quit();
|
|
68
|
-
}
|
|
69
|
-
catch {
|
|
70
|
-
process.exit(1);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
main();
|
package/src/utils/clean-up.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
export function formatValue(value: unknown): string {
|
|
2
|
-
if (typeof value === "object" && value !== null) {
|
|
3
|
-
return JSON.stringify(value, null, 2);
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
if (typeof value === "string") {
|
|
7
|
-
try {
|
|
8
|
-
return JSON.stringify(JSON.parse(value), null, 2);
|
|
9
|
-
}
|
|
10
|
-
catch {
|
|
11
|
-
return value;
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
return String(value);
|
|
16
|
-
}
|
package/src/utils/get-value.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { client } from "..";
|
|
2
|
-
|
|
3
|
-
export async function getValue(selectedKey: string, type: string): Promise<unknown> {
|
|
4
|
-
switch (type) {
|
|
5
|
-
case "string":
|
|
6
|
-
return client.get(selectedKey);
|
|
7
|
-
case "hash":
|
|
8
|
-
return client.hGetAll(selectedKey);
|
|
9
|
-
case "list":
|
|
10
|
-
return client.lRange(selectedKey, 0, -1);
|
|
11
|
-
case "set":
|
|
12
|
-
return client.sMembers(selectedKey);
|
|
13
|
-
case "zset":
|
|
14
|
-
return client.zRangeWithScores(selectedKey, 0, -1);
|
|
15
|
-
default:
|
|
16
|
-
return "(unsupported type)";
|
|
17
|
-
}
|
|
18
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { client } from "..";
|
|
2
|
-
import { cleanup } from "./clean-up";
|
|
3
|
-
|
|
4
|
-
export async function gracefulExit(code = 0) {
|
|
5
|
-
try {
|
|
6
|
-
if (process.stdin.isTTY) {
|
|
7
|
-
try {
|
|
8
|
-
process.stdin.setRawMode(false);
|
|
9
|
-
}
|
|
10
|
-
catch {}
|
|
11
|
-
}
|
|
12
|
-
try {
|
|
13
|
-
process.stdin.pause();
|
|
14
|
-
}
|
|
15
|
-
catch {
|
|
16
|
-
await client.quit();
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
catch {}
|
|
20
|
-
finally {
|
|
21
|
-
cleanup();
|
|
22
|
-
process.exit(code);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
export function isRedisUrl(url: string): boolean {
|
|
2
|
-
let parsed;
|
|
3
|
-
try {
|
|
4
|
-
parsed = new URL(url);
|
|
5
|
-
}
|
|
6
|
-
catch {
|
|
7
|
-
return false;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
if (parsed.protocol !== "redis:" && parsed.protocol !== "rediss:") {
|
|
11
|
-
return false;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
if (!parsed.hostname) {
|
|
15
|
-
return false;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
if (parsed.port && Number.isNaN(Number(parsed.port))) {
|
|
19
|
-
return false;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
return true;
|
|
23
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import inquirer from "inquirer";
|
|
2
|
-
|
|
3
|
-
import { client } from "..";
|
|
4
|
-
import { gracefulExit } from "./graceful-exit";
|
|
5
|
-
|
|
6
|
-
export async function promptForKey() {
|
|
7
|
-
const keys = await client.keys("*");
|
|
8
|
-
if (keys.length === 0)
|
|
9
|
-
return null;
|
|
10
|
-
|
|
11
|
-
try {
|
|
12
|
-
const { selectedKey } = await inquirer.prompt({
|
|
13
|
-
type: "list",
|
|
14
|
-
name: "selectedKey",
|
|
15
|
-
message: "Select a key to view its value:",
|
|
16
|
-
choices: keys,
|
|
17
|
-
pageSize: 20,
|
|
18
|
-
theme: {
|
|
19
|
-
icon: {
|
|
20
|
-
cursor: ">",
|
|
21
|
-
},
|
|
22
|
-
prefix: "0_0",
|
|
23
|
-
},
|
|
24
|
-
});
|
|
25
|
-
return selectedKey;
|
|
26
|
-
}
|
|
27
|
-
catch {
|
|
28
|
-
await gracefulExit(0);
|
|
29
|
-
}
|
|
30
|
-
}
|
package/src/utils/view-key.ts
DELETED
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
import type { Buffer } from "node:buffer";
|
|
2
|
-
|
|
3
|
-
import boxen from "boxen";
|
|
4
|
-
import highlight from "cli-highlight";
|
|
5
|
-
import clipboardy from "clipboardy";
|
|
6
|
-
import readline from "node:readline";
|
|
7
|
-
import pc from "picocolors";
|
|
8
|
-
|
|
9
|
-
import { client } from "..";
|
|
10
|
-
import { cleanup } from "./clean-up";
|
|
11
|
-
import { formatValue } from "./format-value";
|
|
12
|
-
import { getValue } from "./get-value";
|
|
13
|
-
|
|
14
|
-
export async function viewKey(selectedKey: string): Promise<"back" | "deleted" | "quit"> {
|
|
15
|
-
const type = await client.type(selectedKey);
|
|
16
|
-
|
|
17
|
-
const value = await getValue(selectedKey, type);
|
|
18
|
-
|
|
19
|
-
cleanup();
|
|
20
|
-
|
|
21
|
-
console.log(
|
|
22
|
-
boxen(highlight(formatValue(value), { language: "json", ignoreIllegals: true }), {
|
|
23
|
-
borderColor: "cyan",
|
|
24
|
-
padding: 1,
|
|
25
|
-
title: selectedKey,
|
|
26
|
-
borderStyle: "round",
|
|
27
|
-
}),
|
|
28
|
-
);
|
|
29
|
-
console.log(pc.blue("Press 'd' to delete, 'c' to copy, ← to go back, Ctrl+C to quit."));
|
|
30
|
-
|
|
31
|
-
readline.emitKeypressEvents(process.stdin);
|
|
32
|
-
|
|
33
|
-
try {
|
|
34
|
-
process.stdin.resume();
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
catch {}
|
|
38
|
-
if (process.stdin.isTTY) {
|
|
39
|
-
process.stdin.setRawMode(true);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
return await new Promise((resolve) => {
|
|
43
|
-
const onKeypress = async (str: string, key: readline.Key) => {
|
|
44
|
-
if (!key) {
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
if (key.name === "d" && !key.ctrl && !key.meta) {
|
|
49
|
-
try {
|
|
50
|
-
await client.del(selectedKey);
|
|
51
|
-
}
|
|
52
|
-
catch {
|
|
53
|
-
console.error(pc.red("Delete failed:"));
|
|
54
|
-
}
|
|
55
|
-
cleanup();
|
|
56
|
-
resolve("deleted");
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
if (key.name === "c" && !key.ctrl && !key.meta) {
|
|
61
|
-
try {
|
|
62
|
-
clipboardy.writeSync(formatValue(value));
|
|
63
|
-
cleanup();
|
|
64
|
-
resolve("back");
|
|
65
|
-
}
|
|
66
|
-
catch (e) {
|
|
67
|
-
console.error(pc.red("Copy failed:"), e);
|
|
68
|
-
}
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
if (key.name === "left") {
|
|
73
|
-
cleanup();
|
|
74
|
-
resolve("back");
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
if ((key.ctrl && key.name === "c") || key.sequence === "\u0003") {
|
|
79
|
-
cleanup();
|
|
80
|
-
resolve("quit");
|
|
81
|
-
}
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
const onData = async (chunk: Buffer | string) => {
|
|
85
|
-
const s = chunk.toString();
|
|
86
|
-
if (s.includes("\u0003")) {
|
|
87
|
-
cleanup();
|
|
88
|
-
resolve("quit");
|
|
89
|
-
}
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
process.stdin.on("keypress", onKeypress);
|
|
93
|
-
process.stdin.on("data", onData);
|
|
94
|
-
});
|
|
95
|
-
}
|
package/tsconfig.json
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ESNext",
|
|
4
|
-
"jsx": "react-jsx",
|
|
5
|
-
|
|
6
|
-
"lib": ["ESNext"],
|
|
7
|
-
"moduleDetection": "force",
|
|
8
|
-
"module": "Preserve",
|
|
9
|
-
|
|
10
|
-
"moduleResolution": "bundler",
|
|
11
|
-
"allowImportingTsExtensions": true,
|
|
12
|
-
"allowJs": true,
|
|
13
|
-
|
|
14
|
-
"strict": true,
|
|
15
|
-
"noFallthroughCasesInSwitch": true,
|
|
16
|
-
"noImplicitOverride": true,
|
|
17
|
-
|
|
18
|
-
"noPropertyAccessFromIndexSignature": false,
|
|
19
|
-
"noUncheckedIndexedAccess": true,
|
|
20
|
-
|
|
21
|
-
"noUnusedLocals": false,
|
|
22
|
-
"noUnusedParameters": false,
|
|
23
|
-
"noEmit": true,
|
|
24
|
-
"verbatimModuleSyntax": true,
|
|
25
|
-
"skipLibCheck": true
|
|
26
|
-
}
|
|
27
|
-
}
|