peer-term 1.4.6 → 1.4.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "peer-term",
3
- "version": "1.4.6",
3
+ "version": "1.4.8",
4
4
  "license": "MIT",
5
5
  "description": "Share your terminal instantly using a 6-digit code or QR code. Encrypted. No config.",
6
6
  "repository": {
package/src/cli.js CHANGED
@@ -4,13 +4,13 @@
4
4
  * Top-level orchestration:
5
5
  * 1. Detects shell, resolves start path, runs interactive prompts
6
6
  * 2. Creates a SessionManager and starts the first session
7
- * 3. Provides a readline-based menu (n/l/k/a/q) for managing sessions
7
+ * 3. Provides a readline-based menu (n/l/r/k/a/q) for managing sessions
8
8
  * 4. Handles SIGINT and global error handlers
9
9
  */
10
10
 
11
11
  import readline from 'readline';
12
12
  import logger from './logger.js';
13
- import { printBanner } from './ui.js';
13
+ import { printBanner, printCommandsMenu } from './ui.js';
14
14
  import { argv, RELAY_URLS } from './config.js';
15
15
  import { formatDuration, detectShell, resolveStartPath } from './utils.js';
16
16
  import { getExpiryInteractive, getRejoinInteractive } from './prompts.js';
@@ -50,14 +50,7 @@ async function main() {
50
50
  }
51
51
 
52
52
  // ─── Interactive CLI menu ──────────────────────────────────────────
53
- console.log(' ─────────────────────────────────────────');
54
- console.log(' Commands:');
55
- console.log(' [n] New session');
56
- console.log(' [l] List sessions');
57
- console.log(' [a <code>] Authorize verified fingerprint');
58
- console.log(' [k <code>] Kill session');
59
- console.log(' [q] Quit all');
60
- console.log(' ─────────────────────────────────────────');
53
+ printCommandsMenu();
61
54
  console.log('');
62
55
 
63
56
  const rl = readline.createInterface({
@@ -76,6 +69,13 @@ async function main() {
76
69
  await manager.createSession();
77
70
  } else if (input === 'l') {
78
71
  manager.listSessions();
72
+ } else if (input.startsWith('r ') || input.startsWith('rt ') || input === 'r' || input === 'rt') {
73
+ const code = input.startsWith('rt ')
74
+ ? input.slice(3).trim()
75
+ : input.startsWith('r ')
76
+ ? input.slice(2).trim()
77
+ : '';
78
+ await manager.toggleReadonlySession(code);
79
79
  } else if (input.startsWith('a ')) {
80
80
  const code = input.slice(2).trim();
81
81
  await manager.authorizeSession(code);
@@ -88,7 +88,7 @@ async function main() {
88
88
  rl.close();
89
89
  process.exit(0);
90
90
  } else if (input) {
91
- console.log(' Unknown command. Use n, l, a <code>, k <code>, or q.');
91
+ console.log(' Unknown command. Use n, l, r <code>, a <code>, k <code>, or q.');
92
92
  }
93
93
 
94
94
  rl.prompt();
package/src/index.js CHANGED
@@ -46,7 +46,7 @@ import { ViewerServer } from './viewer.js';
46
46
 
47
47
  // ─── Session Class ───────────────────────────────────────────────────────────
48
48
 
49
- class Session {
49
+ export class Session {
50
50
  constructor(shell, expiryMs, rejoinMs, readOnly, startPath, onDestroy) {
51
51
  this.shell = shell;
52
52
  this.expiryMs = expiryMs;
@@ -92,6 +92,25 @@ class Session {
92
92
  this.sessionDurationInterval = null; // Interval: periodic CLI status log
93
93
  }
94
94
 
95
+ get readonly() {
96
+ return this.readOnly;
97
+ }
98
+
99
+ set readonly(val) {
100
+ this.readOnly = Boolean(val);
101
+ }
102
+
103
+ async toggleReadonly() {
104
+ this.readonly = !this.readonly;
105
+ const modeStr = this.readonly ? 'READ-ONLY' : 'INTERACTIVE (write enabled)';
106
+ const codeLabel = this.code ? `Session ${this.code}` : 'Session';
107
+ this.log(`${codeLabel} is now ${modeStr}`);
108
+ if (this.sharedKey && this.fingerprintAuthorized) {
109
+ await this._sendSessionConfig();
110
+ }
111
+ return this.readonly;
112
+ }
113
+
95
114
  /**
96
115
  * Build the context object for FileTransferHandler.
97
116
  * Called on construction and whenever shared key changes.
@@ -233,18 +252,21 @@ class Session {
233
252
  }
234
253
 
235
254
  async _sendSessionConfig() {
236
- if (!this.sharedKey || !this.ws || this.ws.readyState !== WebSocket.OPEN) return;
255
+ if (!this.sharedKey) return;
237
256
 
238
257
  const config = JSON.stringify({
239
258
  type: 'session-config',
240
- readonly: this.readOnly,
259
+ readonly: this.readonly,
241
260
  version: version,
242
261
  shell: this.shell,
243
262
  startPath: this.startPath,
244
263
  });
245
264
  try {
246
265
  const payload = await encrypt(this.sharedKey, config);
247
- this.ws.send(JSON.stringify({ type: 'data', payload }));
266
+ this._sendEncryptedToClient(payload, {
267
+ directPayload: JSON.stringify({ _meta: 'session-config', payload }),
268
+ meta: 'session-config',
269
+ });
248
270
  } catch (err) {
249
271
  this.log(`Failed to send session config: ${err.message}`);
250
272
  }
@@ -941,8 +963,8 @@ class Session {
941
963
  } else {
942
964
  status = `waiting for client (expires in ${formatDuration(remaining)})`;
943
965
  }
944
- if (this.readOnly) status += ' (readonly)';
945
- return status;
966
+ const mode = this.readonly ? '[READ-ONLY]' : '[INTERACTIVE]';
967
+ return `${status} ${mode}`;
946
968
  }
947
969
 
948
970
  // ─── Session Duration Logging ────────────────────────────────────────
@@ -1034,6 +1056,19 @@ export class SessionManager {
1034
1056
  await session.authorizeFingerprint();
1035
1057
  }
1036
1058
 
1059
+ async toggleReadonlySession(code) {
1060
+ const session = this.sessions.get(code);
1061
+ if (!session) {
1062
+ logger.warn(`Session ${code} not found.`);
1063
+ return;
1064
+ }
1065
+ await session.toggleReadonly();
1066
+ }
1067
+
1068
+ async toggleReadonly(code) {
1069
+ return this.toggleReadonlySession(code);
1070
+ }
1071
+
1037
1072
  killAll() {
1038
1073
  for (const [, session] of this.sessions) {
1039
1074
  session.destroy();
package/src/ui.js CHANGED
@@ -164,3 +164,21 @@ export function printVersion() {
164
164
  console.log('peer-term (version unknown)');
165
165
  }
166
166
  }
167
+
168
+ // ─── Commands Menu ───────────────────────────────────────────────────────────
169
+
170
+ /**
171
+ * Print the interactive CLI commands menu.
172
+ */
173
+ export function printCommandsMenu() {
174
+ console.log(' ─────────────────────────────────────────');
175
+ console.log(' Commands:');
176
+ console.log(' [n] New session');
177
+ console.log(' [l] List sessions');
178
+ console.log(' [r <code>] Toggle read-only mode');
179
+ console.log(' [a <code>] Authorize verified fingerprint');
180
+ console.log(' [k <code>] Kill session');
181
+ console.log(' [q] Quit all');
182
+ console.log(' ─────────────────────────────────────────');
183
+ }
184
+