Formatting

This commit is contained in:
2026-04-20 12:26:35 +00:00
parent 32c42cdc2d
commit dbfb2c68d2
32 changed files with 3557 additions and 1828 deletions

View File

@@ -27,7 +27,11 @@ import { existsSync, readdirSync, readFileSync } from "node:fs";
import { join } from "node:path";
import { createHash } from "node:crypto";
import { getDataDir, getMnemonicsDir, getWalletConfigPath } from "../../utils/paths.js";
import {
getDataDir,
getMnemonicsDir,
getWalletConfigPath,
} from "../../utils/paths.js";
import { loadMnemonic } from "../mnemonic.js";
import { Storage } from "../../services/storage.js";
import { COMMAND_TREE } from "./completions.js";
@@ -56,7 +60,9 @@ async function getEngineModule() {
*/
function outputCompletions(items: readonly string[], prefix?: string): void {
const filtered = prefix
? items.filter((item) => item.toLowerCase().startsWith(prefix.toLowerCase()))
? items.filter((item) =>
item.toLowerCase().startsWith(prefix.toLowerCase()),
)
: items;
for (const item of filtered) {
@@ -71,7 +77,9 @@ function outputCompletions(items: readonly string[], prefix?: string): void {
function listMnemonics(prefix?: string): void {
try {
const mnemonicsDir = getMnemonicsDir();
const files = readdirSync(mnemonicsDir).filter((f) => f.startsWith("mnemonic-"));
const files = readdirSync(mnemonicsDir).filter((f) =>
f.startsWith("mnemonic-"),
);
outputCompletions(files, prefix);
} catch {
// Silently fail - no completions available
@@ -155,7 +163,13 @@ async function listTemplates(prefix?: string): Promise<void> {
* Resolves a template by name or ID.
*/
async function resolveTemplate(
engine: Awaited<ReturnType<Awaited<ReturnType<typeof getOfflineEngineModule>>["tryCreateOfflineEngine"]>>,
engine: Awaited<
ReturnType<
Awaited<
ReturnType<typeof getOfflineEngineModule>
>["tryCreateOfflineEngine"]
>
>,
templateQuery: string,
) {
if (!engine) return null;
@@ -165,7 +179,9 @@ async function resolveTemplate(
// Try exact match on name or ID
let template = templates.find(
(t) => t.name === templateQuery || generateTemplateIdentifier(t) === templateQuery,
(t) =>
t.name === templateQuery ||
generateTemplateIdentifier(t) === templateQuery,
);
// Try partial match on name
@@ -181,7 +197,10 @@ async function resolveTemplate(
/**
* Lists actions for a specific template.
*/
async function listActions(templateQuery: string, prefix?: string): Promise<void> {
async function listActions(
templateQuery: string,
prefix?: string,
): Promise<void> {
const mnemonic = getCurrentMnemonic();
if (!mnemonic) return;
@@ -210,7 +229,11 @@ async function listActions(templateQuery: string, prefix?: string): Promise<void
* Lists fields (actions, transactions, outputs, etc.) for a specific template category.
* Used for completing the 3rd argument of `template inspect <category> <template> <field>`.
*/
async function listFields(category: string, templateQuery: string, prefix?: string): Promise<void> {
async function listFields(
category: string,
templateQuery: string,
prefix?: string,
): Promise<void> {
const mnemonic = getCurrentMnemonic();
if (!mnemonic) return;
@@ -300,7 +323,9 @@ async function listResources(prefix?: string): Promise<void> {
try {
const utxos = await engine.listUnspentOutputsData();
const outpoints = utxos.map((u) => `${u.outpointTransactionHash}:${u.outpointIndex}`);
const outpoints = utxos.map(
(u) => `${u.outpointTransactionHash}:${u.outpointIndex}`,
);
outputCompletions(outpoints, prefix);
} finally {
await engine.stop();

View File

@@ -19,7 +19,12 @@
* xo-cli completions fish --install
*/
import { existsSync, readFileSync, appendFileSync, writeFileSync } from "node:fs";
import {
existsSync,
readFileSync,
appendFileSync,
writeFileSync,
} from "node:fs";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
import { homedir } from "node:os";
@@ -40,7 +45,16 @@ const MNEMONIC_SUBS = ["create", "import", "list", "expose"];
/** Subcommands for the template command */
const TEMPLATE_SUBS = ["import", "list", "inspect", "set-default"];
/** Subcommands for the invitation command */
const INVITATION_SUBS = ["create", "append", "sign", "broadcast", "requirements", "import", "inspect", "list"];
const INVITATION_SUBS = [
"create",
"append",
"sign",
"broadcast",
"requirements",
"import",
"inspect",
"list",
];
/** Subcommands for the resource command */
const RESOURCE_SUBS = ["list", "unreserve", "unreserve-all"];
/** Subcommands for the completions command */
@@ -57,7 +71,16 @@ export const COMMAND_TREE = {
} as const;
/** Global option flags available on every command. */
const GLOBAL_OPTIONS = ["-h", "--help", "-v", "--verbose", "-m", "--mnemonic-file", "-o", "--output"];
const GLOBAL_OPTIONS = [
"-h",
"--help",
"-v",
"--verbose",
"-m",
"--mnemonic-file",
"-o",
"--output",
];
/**
* Gets the path to the scripts directory containing shell templates.
@@ -92,13 +115,22 @@ function loadAndProcessTemplate(templateName: string, binName: string): string {
content = content.replace(/\{\{OPTIONS\}\}/g, options);
content = content.replace(/\{\{MNEMONIC_SUBS\}\}/g, MNEMONIC_SUBS.join(" "));
content = content.replace(/\{\{TEMPLATE_SUBS\}\}/g, TEMPLATE_SUBS.join(" "));
content = content.replace(/\{\{INVITATION_SUBS\}\}/g, INVITATION_SUBS.join(" "));
content = content.replace(
/\{\{INVITATION_SUBS\}\}/g,
INVITATION_SUBS.join(" "),
);
content = content.replace(/\{\{RESOURCE_SUBS\}\}/g, RESOURCE_SUBS.join(" "));
// Fish-specific placeholders
if (templateName.endsWith(".fish")) {
content = content.replace(/\{\{TOP_LEVEL_COMMANDS\}\}/g, generateFishTopLevelCommands(binName));
content = content.replace(/\{\{STATIC_SUBCOMMANDS\}\}/g, generateFishStaticSubcommands(binName));
content = content.replace(
/\{\{TOP_LEVEL_COMMANDS\}\}/g,
generateFishTopLevelCommands(binName),
);
content = content.replace(
/\{\{STATIC_SUBCOMMANDS\}\}/g,
generateFishStaticSubcommands(binName),
);
}
return content;
@@ -110,7 +142,9 @@ function loadAndProcessTemplate(templateName: string, binName: string): string {
function generateFishTopLevelCommands(binName: string): string {
const lines: string[] = [];
for (const cmd of Object.keys(COMMAND_TREE)) {
lines.push(`complete -c ${binName} -n "__fish_use_subcommand" -a "${cmd}" -d "${cmd} command"`);
lines.push(
`complete -c ${binName} -n "__fish_use_subcommand" -a "${cmd}" -d "${cmd} command"`,
);
}
return lines.join("\n");
}
@@ -122,7 +156,9 @@ function generateFishStaticSubcommands(binName: string): string {
const lines: string[] = [];
for (const [cmd, subs] of Object.entries(COMMAND_TREE)) {
for (const sub of subs) {
lines.push(`complete -c ${binName} -n "__fish_seen_subcommand_from ${cmd}; and not __fish_seen_subcommand_from ${subs.join(" ")}" -a "${sub}" -d "${cmd} ${sub}"`);
lines.push(
`complete -c ${binName} -n "__fish_seen_subcommand_from ${cmd}; and not __fish_seen_subcommand_from ${subs.join(" ")}" -a "${sub}" -d "${cmd} ${sub}"`,
);
}
}
return lines.join("\n");
@@ -163,7 +199,10 @@ const generators: Record<ShellType, (binName: string) => string> = {
/**
* Shell config file paths and eval commands for each shell type.
*/
const shellConfigs: Record<ShellType, { configFile: string; evalCommand: (binName: string) => string }> = {
const shellConfigs: Record<
ShellType,
{ configFile: string; evalCommand: (binName: string) => string }
> = {
bash: {
configFile: join(homedir(), ".bashrc"),
evalCommand: (binName) => `eval "$(${binName} completions bash)"`,
@@ -199,7 +238,8 @@ function installCompletions(shell: ShellType, binName: string): boolean {
}
// Append the completion line
const newLine = existingContent.endsWith("\n") || existingContent === "" ? "" : "\n";
const newLine =
existingContent.endsWith("\n") || existingContent === "" ? "" : "\n";
const completionBlock = `${newLine}\n# ${binName} shell completions\n${evalCommand}\n`;
appendFileSync(config.configFile, completionBlock);
@@ -227,14 +267,26 @@ export function handleCompletionsCommand(
console.error(`Usage: ${binName} completions <${supported}> [--install]`);
console.error("");
console.error("Examples:");
console.error(` eval "$(${binName} completions bash)" # Output to stdout (add to ~/.bashrc)`);
console.error(` eval "$(${binName} completions zsh)" # Output to stdout (add to ~/.zshrc)`);
console.error(` ${binName} completions fish | source # Output to stdout (add to fish config)`);
console.error(
` eval "$(${binName} completions bash)" # Output to stdout (add to ~/.bashrc)`,
);
console.error(
` eval "$(${binName} completions zsh)" # Output to stdout (add to ~/.zshrc)`,
);
console.error(
` ${binName} completions fish | source # Output to stdout (add to fish config)`,
);
console.error("");
console.error("Install directly to shell config:");
console.error(` ${binName} completions bash --install # Appends to ~/.bashrc`);
console.error(` ${binName} completions zsh --install # Appends to ~/.zshrc`);
console.error(` ${binName} completions fish --install # Appends to ~/.config/fish/config.fish`);
console.error(
` ${binName} completions bash --install # Appends to ~/.bashrc`,
);
console.error(
` ${binName} completions zsh --install # Appends to ~/.zshrc`,
);
console.error(
` ${binName} completions fish --install # Appends to ~/.config/fish/config.fish`,
);
process.exit(1);
}

View File

@@ -8,7 +8,11 @@
* and instead constructs the engine directly with an in-memory blockchain provider.
*/
import { BlockchainMonitor, Engine, InMemoryBlockchainProvider } from "@xo-cash/engine";
import {
BlockchainMonitor,
Engine,
InMemoryBlockchainProvider,
} from "@xo-cash/engine";
import { createStorageAdapter, State, StorageType } from "@xo-cash/state";
import { convertMnemonicToSeedBytes } from "@xo-cash/crypto";
import { binToHex, hash256 } from "@bitauth/libauth";