Files
xo-cli/src/app.ts

98 lines
2.6 KiB
TypeScript

/**
* 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<AppConfig> = {}): Promise<App> {
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<void> {
// 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<void> {
// Unmount Ink app
if (this.inkInstance) {
this.inkInstance.unmount();
this.inkInstance = null;
}
}
}