UNPKG

cosmic-interchain-cli

Version:

A command-line utility for Cosmic Wire's interchain messaging protocol

169 lines 5.54 kB
import { input } from '@inquirer/prompts'; import select from '@inquirer/select'; import fs from 'fs'; import os from 'os'; import path from 'path'; import { LineCounter, parse, parse as yamlParse, stringify as yamlStringify, } from 'yaml'; import { objMerge } from '@hyperlane-xyz/utils'; import { log } from '../logger.js'; export const MAX_READ_LINE_OUTPUT = 250; export function resolvePath(filePath) { if (filePath.startsWith('~')) { const homedir = os.homedir(); return path.join(homedir, filePath.slice(1)); } return filePath; } export function isFile(filepath) { if (!filepath) return false; try { return fs.existsSync(filepath) && fs.lstatSync(filepath).isFile(); } catch (error) { log(`Error checking for file: ${filepath}`); return false; } } export function readFileAtPath(filepath) { if (!isFile(filepath)) { throw Error(`File doesn't exist at ${filepath}`); } return fs.readFileSync(filepath, 'utf8'); } export function writeFileAtPath(filepath, value) { const dirname = path.dirname(filepath); if (!isFile(dirname)) { fs.mkdirSync(dirname, { recursive: true }); } fs.writeFileSync(filepath, value); } export function readJson(filepath) { return JSON.parse(readFileAtPath(filepath)); } export function tryReadJson(filepath) { try { return readJson(filepath); } catch (error) { return null; } } export function writeJson(filepath, obj) { writeFileAtPath(filepath, JSON.stringify(obj, null, 2) + '\n'); } export function mergeJson(filepath, obj) { if (isFile(filepath)) { const previous = readJson(filepath); writeJson(filepath, objMerge(previous, obj)); } else { writeJson(filepath, obj); } } export function readYaml(filepath) { return yamlParse(readFileAtPath(filepath)); } export function tryReadYamlAtPath(filepath) { try { return readYaml(filepath); } catch (error) { return null; } } export function writeYaml(filepath, obj) { writeFileAtPath(filepath, yamlStringify(obj, { indent: 2, sortMapEntries: true }) + '\n'); } export function mergeYaml(filepath, obj) { if (isFile(filepath)) { const previous = readYaml(filepath); writeYaml(filepath, objMerge(previous, obj)); } else { writeYaml(filepath, obj); } } export function readYamlOrJson(filepath, format) { return resolveYamlOrJsonFn(filepath, readJson, readYaml, format); } export function writeYamlOrJson(filepath, obj, format) { return resolveYamlOrJsonFn(filepath, (f) => writeJson(f, obj), (f) => writeYaml(f, obj), format); } export function mergeYamlOrJson(filepath, obj, format = 'yaml') { return resolveYamlOrJsonFn(filepath, (f) => mergeJson(f, obj), (f) => mergeYaml(f, obj), format); } function resolveYamlOrJsonFn(filepath, jsonFn, yamlFn, format) { const fileFormat = resolveFileFormat(filepath, format); if (!fileFormat) { throw new Error(`Invalid file format for ${filepath}`); } if (fileFormat === 'json') { return jsonFn(filepath); } return yamlFn(filepath); } export function resolveFileFormat(filepath, format) { // early out if filepath is undefined if (!filepath) { return format; } if (format === 'json' || filepath?.endsWith('.json')) { return 'json'; } if (format === 'yaml' || filepath?.endsWith('.yaml') || filepath?.endsWith('.yml')) { return 'yaml'; } return undefined; } export async function runFileSelectionStep(folderPath, description, pattern) { const noFilesErrorMessage = `No "${description}" found in ${folderPath}. Please confirm the path for "${description}". By default, the CLI writes to folders relative to where its run.`; if (!fs.existsSync(folderPath)) throw new Error(noFilesErrorMessage); let filenames = fs.readdirSync(folderPath); if (pattern) { filenames = filenames.filter((f) => f.includes(pattern)); } if (filenames.length === 0) throw new Error(noFilesErrorMessage); let filename = (await select({ message: `Select ${description} file`, choices: [ ...filenames.map((f) => ({ name: f, value: f })), { name: '(Other file)', value: null }, ], pageSize: 20, })); if (filename) return path.join(folderPath, filename); filename = await input({ message: `Enter ${description} filepath`, }); if (filename) return filename; else throw new Error(`No filepath entered ${description}`); } export function indentYamlOrJson(str, indentLevel) { const indent = ' '.repeat(indentLevel); return str .split('\n') .map((line) => indent + line) .join('\n'); } /** * Logs the YAML representation of an object if the number of lines is less than the specified maximum. * * @param obj - The object to be converted to YAML. * @param maxLines - The maximum number of lines allowed for the YAML representation. * @param margin - The number of spaces to use for indentation (default is 2). */ export function logYamlIfUnderMaxLines(obj, maxLines = MAX_READ_LINE_OUTPUT, margin = 2) { const asYamlString = yamlStringify(obj, null, margin); const lineCounter = new LineCounter(); parse(asYamlString, { lineCounter }); log(lineCounter.lineStarts.length < maxLines ? asYamlString : ''); } //# sourceMappingURL=files.js.map