Redis

/* * * Methods copied from create-cloudflare, same names used where possible * * */ import chalk from 'chalk' export const { white, gray, dim, hidden, bold, cyanBright, bgCyan } = chalk const brandColor = chalk.hex('#ffb063') export const shapes = { diamond: '◇', dash: '─', radioInactive: '○', radioActive: '●', backActive: '◀', backInactive: '◁', bar: '│', leftT: '├', rigthT: '┤', arrows: { left: '‹', right: '›', }, corners: { tl: '╭', bl: '╰', tr: '╮', br: '╯', }, } // Returns a string containing n non-trimmable spaces // This is useful for places where clack trims lines of output // but we need leading spaces export const space = (n = 1) => { return hidden('\u200A'.repeat(n)) } // Primitive for printing to STDERR. We must use STDERR for human-readable messages // as MCP uses STDOUT export const logRaw = (msg: string) => { process.stderr.write(`${msg}\n`) } // A simple stylized log for use within a prompt export const log = (msg: string) => { const lines = msg.split('\n').map((ln) => `${gray(shapes.bar)} ${white(ln)}`) logRaw(lines.join('\n')) } // Strip the ansi color characters out of the line when calculating // line length, otherwise the padding will be thrown off // Used from https://github.com/natemoo-re/clack/blob/main/packages/prompts/src/index.ts export const stripAnsi = (str: string) => { const pattern = [ '[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)', '(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]))', ].join('|') const regex = RegExp(pattern, 'g') return str.replace(linkRegex, '$2').replace(regex, '') } // Regular Expression that matches a hyperlink // e.g. `\u001B]8;;http://example.com/\u001B\\This is a link\u001B]8;;\u001B\` export const linkRegex = // eslint-disable-next-line no-control-regex /\u001B\]8;;(?<url>.+)\u001B\\(?<label>.+)\u001B\]8;;\u001B\\/g export function createDialog(lines: string[]) { const screenWidth = process.stdout.columns const maxLineWidth = Math.max( ...lines.map((line) => stripAnsi(line).length), 60, // Min inner width ) const dividerWidth = Math.min(maxLineWidth, screenWidth) return [gray(shapes.dash).repeat(dividerWidth), ...lines, gray(shapes.dash).repeat(dividerWidth), ''].join('\n') } export const startSection = (heading: string, subheading?: string, printNewLine = true) => { logRaw(`${gray(shapes.corners.tl)} ${brandColor(heading)} ${subheading ? dim(subheading) : ''}`) if (printNewLine) { newline() } } export const newline = () => { log('') } // Log a simple status update with a style similar to the clack spinner export const updateStatus = (msg: string, printNewLine = true) => { logRaw( format(msg, { firstLinePrefix: gray(shapes.leftT), linePrefix: gray(shapes.bar), newlineAfter: printNewLine, }), ) } type FormatOptions = { linePrefix?: string firstLinePrefix?: string newlineBefore?: boolean newlineAfter?: boolean formatLine?: (line: string) => string multiline?: boolean } export const format = ( msg: string, { linePrefix = gray(shapes.bar), firstLinePrefix = linePrefix, newlineBefore = false, newlineAfter = false, formatLine = (line: string) => white(line), multiline = true, }: FormatOptions = {}, ) => { const lines = multiline ? msg.split('\n') : [msg] const formattedLines = lines.map((line, i) => (i === 0 ? firstLinePrefix : linePrefix) + space() + formatLine(line)) if (newlineBefore) { formattedLines.unshift(linePrefix) } if (newlineAfter) { formattedLines.push(linePrefix) } return formattedLines.join('\n') } export const endSection = (heading: string, subheading?: string) => { logRaw(`${gray(shapes.corners.bl)} ${brandColor(heading)} ${subheading ? dim(subheading) : ''}\n`) } // Create a hyperlink in terminal // It works in iTerm2 and VSCode's terminal, but not macOS built-in terminal app export const hyperlink = (url: string, label = url) => { return `\u001B]8;;${url}\u001B\\${label}\u001B]8;;\u001B\\` }