Initial Commit

This commit is contained in:
2026-01-29 07:13:33 +00:00
commit 399e93f714
34 changed files with 7663 additions and 0 deletions

134
src/app.ts Normal file
View File

@@ -0,0 +1,134 @@
/**
* Application bootstrap and lifecycle management.
* Coordinates initialization of all CLI components.
*/
import React from 'react';
import { render, type Instance } from 'ink';
import { App as AppComponent } from './tui/App.js';
import { WalletController } from './controllers/wallet-controller.js';
import { InvitationController } from './controllers/invitation-controller.js';
import { SyncClient } from './services/sync-client.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;
}
/**
* Main application class that orchestrates all CLI components.
*/
export class App {
/** Ink render instance */
private inkInstance: Instance | null = null;
/** Wallet controller for engine operations */
private walletController: WalletController;
/** Invitation controller for collaborative transactions */
private invitationController: InvitationController;
/** HTTP client for sync server communication */
private syncClient: SyncClient;
/** Application configuration */
private config: Required<AppConfig>;
/**
* Creates a new App instance.
* @param config - Application configuration options
*/
private constructor(config: AppConfig = {}) {
// Set default configuration
this.config = {
syncServerUrl: config.syncServerUrl ?? 'http://localhost:3000',
databasePath: config.databasePath ?? './',
databaseFilename: config.databaseFilename ?? 'xo-wallet',
};
// Initialize sync client
this.syncClient = new SyncClient(this.config.syncServerUrl);
// Initialize wallet controller (engine will be created when seed is provided)
this.walletController = new WalletController({
databasePath: this.config.databasePath,
databaseFilename: this.config.databaseFilename,
});
// Initialize invitation controller
this.invitationController = new InvitationController(
this.walletController,
this.syncClient,
);
}
/**
* Factory method to create and start the application.
* @param config - Application configuration options
* @returns Running App instance
*/
static async create(config: AppConfig = {}): Promise<App> {
const app = new App(config);
await app.start();
return app;
}
/**
* Starts the application.
* Renders the Ink-based TUI.
*/
async start(): Promise<void> {
// Render the Ink app
this.inkInstance = render(
React.createElement(AppComponent, {
walletController: this.walletController,
invitationController: this.invitationController,
})
);
// Wait for the app to exit
await this.inkInstance.waitUntilExit();
}
/**
* Stops the application and cleans up resources.
*/
async stop(): Promise<void> {
// Stop the wallet engine if running
await this.walletController.stop();
// Unmount Ink app
if (this.inkInstance) {
this.inkInstance.unmount();
this.inkInstance = null;
}
}
/**
* Gets the wallet controller for external access.
*/
getWalletController(): WalletController {
return this.walletController;
}
/**
* Gets the invitation controller for external access.
*/
getInvitationController(): InvitationController {
return this.invitationController;
}
/**
* Gets the sync client for external access.
*/
getSyncClient(): SyncClient {
return this.syncClient;
}
}