Tests. Autocomplete. Few Fixes. Mocks for Electrum Service. Template-to-Json parser. Fix global paths. Use IO Dependency injection for logging from cli. Additional commands in CLI.

This commit is contained in:
2026-04-20 10:30:38 +00:00
parent df4f438f6d
commit ff2fe126c6
44 changed files with 8220 additions and 1503 deletions

View File

@@ -1,12 +1,13 @@
import { bold, dim } from "../cli-utils.js";
import { listMnemonicFiles, createMnemonicFile, createMnemonicSeed } from "../mnemonic.js";
import type { CommandDependencies } from "./types.js";
import { listMnemonicFiles, createMnemonicFile, createMnemonicSeed, loadMnemonic } from "../mnemonic.js";
import type { BaseCommandDependencies, CommandIO } from "./types.js";
import { CommandError } from "./types.js";
/**
* Prints the help message for the mnemonic command
*/
export const printMnemonicHelp = () => {
console.log(
export const printMnemonicHelp = (io: CommandIO): void => {
io.out(
`
${bold("Usage:")} xo-cli mnemonic <sub-command>
@@ -22,52 +23,79 @@ ${bold("Options:")}
/**
* Handles the mnemonic command.
* Throws CommandError on failure, returns result data on success.
* @param deps - The command dependencies.
* @param args - Positional args after the command name, e.g. ["create"] or ["import", "page", "pencil", ...].
* @param options - Parsed option flags, e.g. { output: "mnemonic.txt" }.
*/
export const handleMnemonicCommand = async (deps: Omit<CommandDependencies, "app">, args: string[], options: Record<string, string>): Promise<void> => {
export const handleMnemonicCommand = async (
deps: BaseCommandDependencies,
args: string[],
options: Record<string, string>,
): Promise<{ savedAs?: string; count?: number; mnemonic?: string }> => {
const subCommand = args[0];
const { mnemonicsDir } = deps.paths;
if (!subCommand) {
deps.verboseLogger("No sub-command provided");
printMnemonicHelp();
return;
deps.io.verbose("No sub-command provided");
printMnemonicHelp(deps.io);
throw new CommandError("mnemonic.subcommand.missing", "No sub-command provided");
}
switch (subCommand) {
case "create": {
const mnemonicSeed = createMnemonicSeed();
await createMnemonicFile(mnemonicSeed, options["output"]);
const savedAs = createMnemonicFile(mnemonicsDir, mnemonicSeed, options["output"]);
console.log(`Mnemonic file created: ${options["output"]} (${mnemonicSeed})`);
break;
deps.io.out(`Mnemonic file created: ${savedAs} (${mnemonicSeed})`);
return { savedAs };
}
case "import": {
// The mnemonic seed words are all the positional args after the sub-command
const mnemonicSeed = args.slice(1).join(" ");
if (!mnemonicSeed) {
deps.verboseLogger("No mnemonic seed provided");
printMnemonicHelp();
return;
deps.io.verbose("No mnemonic seed provided");
printMnemonicHelp(deps.io);
throw new CommandError("mnemonic.import.seed_missing", "No mnemonic seed provided");
}
deps.verboseLogger(`Mnemonic seed: ${mnemonicSeed}`);
await createMnemonicFile(mnemonicSeed, options["output"]);
break;
deps.io.verbose(`Mnemonic seed: ${mnemonicSeed}`);
const savedAs = createMnemonicFile(mnemonicsDir, mnemonicSeed, options["output"]);
deps.io.out(`Mnemonic file created: ${savedAs}`);
return { savedAs };
}
case "list": {
const mnemonicFiles = listMnemonicFiles();
console.log(mnemonicFiles.join('\n'));
break;
const mnemonicFiles = listMnemonicFiles(mnemonicsDir);
deps.io.out(mnemonicFiles.join('\n'));
return { count: mnemonicFiles.length };
}
case "expose": {
const mnemonicFile = args[1];
if (!mnemonicFile) {
deps.io.verbose("No mnemonic file provided");
printMnemonicHelp(deps.io);
throw new CommandError("mnemonic.expose.file_missing", "No mnemonic file provided");
}
try {
const mnemonic = loadMnemonic(mnemonicsDir, mnemonicFile);
deps.io.out(mnemonic);
return { mnemonic };
} catch (error) {
throw new CommandError(
"mnemonic.expose.file_not_found",
`Mnemonic file not found: ${mnemonicFile}`,
);
}
}
default:
console.error(`Unknown sub-command: ${subCommand}`);
printMnemonicHelp();
return;
deps.io.err(`Unknown sub-command: ${subCommand}`);
printMnemonicHelp(deps.io);
throw new CommandError("mnemonic.subcommand.unknown", `Unknown sub-command: ${subCommand}`);
}
};