From 97ee9aba66e9a84eb6e21cee75406f34ba76e983 Mon Sep 17 00:00:00 2001 From: Paul Paterson Date: Fri, 22 Nov 2024 16:37:56 -0500 Subject: [PATCH] FE-6024 Implement shell history --- src/commands/shell.mjs | 41 +++++++++++++++++++++++++++++++++++++++++ src/lib/file-util.mjs | 2 +- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/commands/shell.mjs b/src/commands/shell.mjs index a08f7333..cad13245 100644 --- a/src/commands/shell.mjs +++ b/src/commands/shell.mjs @@ -1,6 +1,9 @@ //@ts-check import repl from "node:repl"; +import path from "node:path"; +import fs from "node:fs"; +import os from "node:os"; import { container } from "../cli.mjs"; import { @@ -8,6 +11,7 @@ import { commonConfigurableQueryOptions, } from "../lib/command-helpers.mjs"; import { performQuery } from "./eval.mjs"; +import { dirExists, fileExists } from "../lib/file-util.mjs"; async function doShell(argv) { const logger = container.resolve("logger"); @@ -16,6 +20,16 @@ async function doShell(argv) { if (argv.dbPath) logger.stdout(`Starting shell for database ${argv.dbPath}`); logger.stdout("Type Ctrl+D or .exit to exit the shell"); + // Setup history file + const historyDir = path.join(os.homedir(), ".fauna"); + if (!dirExists(historyDir)) { + fs.mkdirSync(historyDir, { recursive: true }); + } + const historyFile = path.join(historyDir, "history"); + if (!fileExists(historyFile)) { + fs.writeFileSync(historyFile, "{}"); + } + /** @type {import('node:repl').ReplOptions} */ const replArgs = { prompt: `${argv.db_path || ""}> `, @@ -30,6 +44,14 @@ async function doShell(argv) { }; const shell = repl.start(replArgs); + + // Setup history + shell.setupHistory(historyFile, (err) => { + if (err) { + logger.stderr(`Error setting up history: ${err.message}`); + } + }); + // eslint-disable-next-line no-console shell.on("error", console.error); @@ -55,6 +77,25 @@ async function doShell(argv) { shell.prompt(); }, }, + { + cmd: "clearhistory", + help: "Clear command history", + action: async () => { + try { + await fs.writeFileSync(historyFile, ''); + logger.stdout('History cleared'); + // Reinitialize history + shell.setupHistory(historyFile, (err) => { + if (err) { + logger.stderr(`Error reinitializing history: ${err.message}`); + } + }); + } catch (err) { + logger.stderr(`Error clearing history: ${err.message}`); + } + shell.prompt(); + }, + } ].forEach(({ cmd, ...cmdOptions }) => shell.defineCommand(cmd, cmdOptions)); return completionPromise; diff --git a/src/lib/file-util.mjs b/src/lib/file-util.mjs index 1902d47d..4be288cd 100644 --- a/src/lib/file-util.mjs +++ b/src/lib/file-util.mjs @@ -54,7 +54,7 @@ export function dirIsWriteable(path) { * @param {string} path - The path to the file. * @returns {boolean} - Returns true if the file exists, otherwise false. */ -function fileExists(path) { +export function fileExists(path) { try { fs.readFileSync(fixPath(path)); return true;