/// import readline from 'node:readline'; import { PrivateKey } from '@xo-cash/primitives'; import type { BaseSyncClient } from '../source/shared/base-client.js'; import { SSEClient } from '../source/sse/client.js'; import { EncryptedClientPerResource } from './experimental/encrypted-client-per-resource.js'; const privateKey = PrivateKey.fromString('c440ce6ac5b63ae7bc4af9891b80b7a88ccdeebba5e43246885e9ec56f912ac2'); // Define some formatting helpers const formatResourceId = (resourceId: string) => { return `\x1b[32m${resourceId}\x1b[0m`; }; const formatMessage = (message: string) => { return `\x1b[34m${message}\x1b[0m`; }; const resetFormatting = () => { return '\x1b[0m'; }; // readline lets us get both whole lines and individual keypresses (for Escape) // escapeCodeTimeout: how long to wait after Escape to see if it's part of a key sequence (default 500ms) const rl = readline.createInterface({ input: process.stdin, output: process.stdout, escapeCodeTimeout: 0 }); const startTUI = async (client: BaseSyncClient) => { // Listen and log out the resource change client.on('resource-instance-updated', (message) => { // Print the message with colours console.log( `${formatResourceId(message.resourceId)}:${formatResourceId(message.publicKey)} updated: ${formatMessage(message.value)}${resetFormatting()}`, ); }); // Connect to the sync server and subscribe to the resource await client.connect(); const writeResourceLoop = async (resourceId: string) => { while (true) { // Print the prompt process.stdout.write('> '); // Wait for the user to enter a command // Resolves with the typed line, or null if Escape was pressed const onKeypress = (_char: string, key: readline.Key) => key?.name === 'escape' && rl.emit('line', null); process.stdin.on('keypress', onKeypress); const line = await new Promise((resolve) => rl.once('line', resolve)); process.stdin.off('keypress', onKeypress); // Escape exits the loop if (line === null) return; if (line.trim()) { await client.write(resourceId, line.trim()); } } }; const selectResource = async () => { while (true) { console.log('Enter a resource:'); // Print the prompt process.stdout.write('> '); // Wait for the user to enter a command const line = await new Promise((resolve) => rl.once('line', resolve)); const resourceId = line.trim(); if (resourceId) { // Subscribe to the resource await client.subscribe(resourceId); // Read the current instances const instance = await client.read(resourceId); console.dir(instance, { depth: null }); // Write to the resource await writeResourceLoop(resourceId); } } }; // Start the TUI loop await selectResource(); }; const clients = { sse: new SSEClient('https://dev.v2.sync.xo.harvmaster.com', privateKey), encrypted: new EncryptedClientPerResource(new SSEClient('https://dev.v2.sync.xo.harvmaster.com', privateKey)), }; const params = process.argv.slice(2); const client = params[0] === 'false' ? clients.sse : clients.encrypted; startTUI(client);