diff --git a/demo/tui.ts b/demo/tui.ts
index 39f35aa..142ca35 100644
--- a/demo/tui.ts
+++ b/demo/tui.ts
@@ -1,3 +1,6 @@
+///
+import readline from 'node:readline';
+
import { PrivateKey } from '@xo-cash/primitives';
import type { BaseSyncClient } from '../source/shared/base-client.js';
@@ -20,6 +23,10 @@ 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) => {
@@ -31,22 +38,55 @@ const startTUI = async (client: BaseSyncClient) => {
// Connect to the sync server and subscribe to the resource
await client.connect();
- await client.subscribe('encrypted-test');
+
+ 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
- while (true) {
- // Print the prompt
- process.stdout.write('> ');
-
- // Wait for the user to enter a command
- const data = await new Promise((resolve) => process.stdin.once('data', resolve));
-
- // If the user entered a command, write it to the resource
- if (data) {
- const message = data.toString().trim();
- await client.write('encrypted-test', message);
- }
- }
+ await selectResource();
};
const clients = {