/** * Application bootstrap and lifecycle management. * Simplified to render TUI immediately and let it handle AppService creation. */ import { join } from "node:path"; import React from "react"; import { render, type Instance } from "ink"; import { App as AppComponent } from "./tui/App.js"; import { getDataDir } from "./utils/paths.js"; /** * Configuration options for the CLI application. */ export interface AppConfig { /** URL of the sync server (default: http://localhost:3000) */ syncServerUrl: string; /** Database path for wallet state storage */ databasePath: string; /** Database filename */ databaseFilename: string; /** Path for invitation storage database */ invitationStoragePath: string; } /** * Main application class that orchestrates the CLI. * Renders the TUI immediately and passes config for later AppService creation. */ export class App { /** Ink render instance */ private inkInstance: Instance | null = null; /** Application configuration */ private config: AppConfig; /** * Creates a new App instance. * @param config - Application configuration options */ private constructor(config: AppConfig) { this.config = config; } /** * Factory method to create and start the application. * @param config - Application configuration options * @returns Running App instance */ static async create(config: Partial = {}): Promise { const dataDir = getDataDir(); // Set default configuration const fullConfig: AppConfig = { syncServerUrl: config.syncServerUrl ?? "http://localhost:3000", databasePath: config.databasePath ?? dataDir, databaseFilename: config.databaseFilename ?? "xo-wallet.db", invitationStoragePath: config.invitationStoragePath ?? join(dataDir, "xo-invitations.db"), }; console.log("Full config:", fullConfig); const app = new App(fullConfig); await app.start(); return app; } /** * Starts the application. * Renders the Ink-based TUI immediately. */ async start(): Promise { // Render the Ink app with config // TUI will handle AppService creation after seed input this.inkInstance = render( React.createElement(AppComponent, { config: this.config, }), ); // Wait for the app to exit await this.inkInstance.waitUntilExit(); process.exit(0); } /** * Stops the application and cleans up resources. */ async stop(): Promise { // Unmount Ink app if (this.inkInstance) { this.inkInstance.unmount(); this.inkInstance = null; } } }