feat: custom formatter support

- format.ts: customFormat() uses child_process.execFile
- Template params: {KEY} {VALUE} {HEX_FILE}
- Value written to temp file, path passed via {HEX_FILE}
- 10s timeout, error handling
- StringEditor: 'custom' format option + command input
- Command persisted to localStorage
- i18n keys (zh-CN + en)
This commit is contained in:
2026-07-07 21:54:13 +08:00
parent 5178aea6d1
commit 1511427e62
8 changed files with 65 additions and 2 deletions
+35 -1
View File
@@ -1,6 +1,10 @@
// electron/main/redis/format.ts
// 值格式转换(解压/编码)
// 值格式转换(解压/编码/自定义
import { gunzipSync, inflateSync, brotliDecompressSync } from 'zlib'
import { execFile } from 'child_process'
import { writeFile, unlink, mkdtemp } from 'fs/promises'
import { tmpdir } from 'os'
import { join } from 'path'
export type FormatType = 'text' | 'hex' | 'json' | 'binary' | 'gzip' | 'deflate' | 'brotli' | 'deflateRaw'
@@ -44,3 +48,33 @@ export function detectFormat(value: string): FormatType {
if (hasNonPrintable) return 'hex'
return 'text'
}
export async function customFormat(
value: string,
command: string,
key?: string
): Promise<string> {
const tmpDir = await mkdtemp(join(tmpdir(), 'jrdm-fmt-'))
const tmpFile = join(tmpDir, 'value.bin')
await writeFile(tmpFile, value, 'utf-8')
return new Promise((resolve) => {
const cmd = command
.replace(/\{KEY\}/g, key || '')
.replace(/\{VALUE\}/g, value)
.replace(/\{HEX_FILE\}/g, tmpFile)
const parts = cmd.split(/\s+/)
const exe = parts[0]
const args = parts.slice(1)
execFile(exe, args, { timeout: 10000, maxBuffer: 10 * 1024 * 1024 }, async (err, stdout) => {
await unlink(tmpFile).catch(() => {})
if (err) {
resolve(`[Custom formatter error: ${err.message}]`)
} else {
resolve(stdout)
}
})
})
}