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:
@@ -264,6 +264,9 @@ export function registerIpcHandlers(): void {
|
||||
ipcMain.handle('redis:detectFormat', (_e, value: string) => {
|
||||
return redis.detectFormat(value)
|
||||
})
|
||||
ipcMain.handle('redis:customFormat', (_e, value: string, command: string, key: string) => {
|
||||
return redis.customFormat(value, command, key)
|
||||
})
|
||||
|
||||
// Pub/Sub
|
||||
ipcMain.handle('redis:subscribe', async (_e, id: string, channels: string[], isPattern: boolean) => {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user