oorja 2.3.0 → 2.5.1

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/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  TeleType
2
2
  =====
3
3
 
4
- cli tool that allows you to share your terminal online conveniently. Check out [oorja.io](https://oorja.io) - show off mad cli-fu, help a colleague, teach, or troubleshoot.
4
+ cli tool that allows you to share your terminal online conveniently. Check out [SupaKit](https://supakit.app) - show off mad cli-fu, help a colleague, teach, or troubleshoot.
5
5
 
6
6
  [![Version](https://img.shields.io/npm/v/oorja.svg)](https://npmjs.org/package/oorja)
7
7
  [![Downloads/week](https://img.shields.io/npm/dw/oorja.svg)](https://npmjs.org/package/oorja)
@@ -9,11 +9,11 @@ cli tool that allows you to share your terminal online conveniently. Check out [
9
9
 
10
10
 
11
11
  <p align="center">
12
- <img width="600" src="https://oorja.io/images/cli-demo.svg">
12
+ <img width="600" src="https://supakit.app/images/cli-demo.svg">
13
13
  </p>
14
14
 
15
15
  <p align="center">
16
- <img src="https://oorja.io/images/teletype-session.png">
16
+ <img src="https://supakit.app/images/teletype-session.png">
17
17
  </p>
18
18
 
19
19
  Your stream can be view-only or collaboration enabled (command-line flag).
@@ -49,82 +49,84 @@ Any participant in the room can stream their terminal(s) i.e there can be multip
49
49
  For options: `teletype -h`
50
50
 
51
51
  **Note**
52
- This is the cli companion for [oorja.io](https://oorja.io) which is a privacy focussed collaboration tool with more features like voice, notes, and chat - [privacy policy](https://oorja.io/privacy-policy).
52
+ This is the cli companion for [SupaKit](https://supakit.app) which is a privacy focussed collaboration tool with more features like voice, notes, and chat - [privacy policy](https://supakit.app/privacy-policy).
53
53
  TLDR: Your data is end-to-end encrypted, no prying eyes 🍻.
54
54
 
55
55
  Like it ? [follow or tweet, tell your colleagues](https://twitter.com/oorja_app) 👩🏻‍💻
56
56
 
57
57
  Open [issues](https://github.com/akshaykmr/TeleType/issues).
58
58
 
59
- More ways to [contact](https://oorja.io/contact).
59
+ More ways to [contact](https://supakit.app/contact).
60
60
 
61
61
 
62
62
  # Commands
63
- <!-- commands-disabled -->
64
- * [`oorja help [COMMAND]`](#oorja-help-command)
65
- * [`oorja teletype [SPACE]`](#oorja-teletype-space)
63
+ <!-- commands -->
64
+ * [`oorja teletype [STREAMKEY]`](#oorja-teletype-streamkey)
66
65
  * [`oorja signout`](#oorja-signout)
66
+ * [`oorja help [COMMAND]`](#oorja-help-command)
67
67
 
68
- ## `oorja help [COMMAND]`
69
-
70
- Display help for oorja.
71
-
72
- ```
73
- USAGE
74
- $ oorja help [COMMAND...] [-n]
75
-
76
- ARGUMENTS
77
- COMMAND... Command to show help for.
78
-
79
- FLAGS
80
- -n, --nested-commands Include all nested commands in the output.
81
-
82
- DESCRIPTION
83
- Display help for oorja.
84
- ```
85
-
86
- ## `oorja teletype [STREAM_KEY]`
68
+ ## `oorja teletype [STREAMKEY]`
87
69
 
88
- Launch a terminal streaming session in oorja.
70
+ Launch a terminal streaming session in SupaKit.
89
71
 
90
72
  ```
91
73
  USAGE
92
- $ oorja teletype [STREAM_KEY] [-h] [-s <value>] [-m] [-n]
74
+ $ oorja teletype [STREAMKEY] [-h] [-s <value>] [-m] [-n]
93
75
 
94
76
  FLAGS
95
77
  -h, --help Show CLI help.
96
78
  -m, --multiplex Allows users to WRITE TO YOUR SHELL i.e enables collaboration mode. Make sure you trust space
97
79
  participants. Off by default
98
- -n, --new_space Create new space
99
- -s, --shell=<value> [default: /usr/bin/bash] shell to use. e.g. bash, fish
80
+ -n, --new Create a new space
81
+ -s, --shell=<value> shell to use. e.g. bash, fish
100
82
 
101
83
  DESCRIPTION
102
- Launch a terminal streaming session in oorja.
84
+ Launch a terminal streaming session in SupaKit.
103
85
 
104
86
  ALIASES
105
87
  $ oorja tty
106
88
 
107
89
  EXAMPLES
108
90
  $ teletype
109
- Will prompt to choose streaming destination - existing space or create a new one.
91
+ Will prompt to choose streaming destination - either enter a stream key for an existing space or create a new space.
110
92
 
111
- $ teletype $stream-key
112
- Will stream to the space specified by secret link.
93
+ $ teletype 'sk-xxxx:space-id#encryption-secret'
94
+ Will stream to the space using the secret stream-key. NOTE: stream-keys are personal (generated for you in the teletype app at supakit.app), do not accept them from other people, nor should
95
+ you share your stream-keys with others.
113
96
 
114
97
  $ teletype -m
115
- Will also allow participants to write to your terminal!
98
+ Will also allow participants to write to your terminal! Collaboration mode must be explicitly enabled.
116
99
  ```
117
100
 
118
101
  ## `oorja signout`
119
102
 
120
- Sign-out of oorja. Clears saved auth-token
103
+ Sign out of SupaKit. Clears saved auth-token
121
104
 
122
105
  ```
123
106
  USAGE
124
107
  $ oorja signout
125
108
 
126
109
  DESCRIPTION
127
- Sign-out of oorja. Clears saved auth-token
110
+ Sign out of SupaKit. Clears saved auth-token
111
+ ```
112
+
113
+
114
+ ## `oorja help [COMMAND]`
115
+
116
+ Display help for oorja.
117
+
118
+ ```
119
+ USAGE
120
+ $ oorja help [COMMAND...] [-n]
121
+
122
+ ARGUMENTS
123
+ [COMMAND...] Command to show help for.
124
+
125
+ FLAGS
126
+ -n, --nested-commands Include all nested commands in the output.
127
+
128
+ DESCRIPTION
129
+ Display help for oorja.
128
130
  ```
129
131
 
130
- <!-- commandsstop-disabled -->
132
+ <!-- commandsstop -->
@@ -1,7 +1,7 @@
1
1
  import { Command } from '@oclif/core';
2
- import { Config } from '../lib/config.js';
2
+ import { Config } from 'oorja/lib/config';
3
3
  export class SignOut extends Command {
4
- static description = `Sign-out of oorja. Clears saved auth-token`;
4
+ static description = `Sign out of SupaKit. Clears saved auth-token`;
5
5
  async run() {
6
6
  const config = new Config(this.config.configDir);
7
7
  config.setAccessToken('');
@@ -6,9 +6,9 @@ export default class TeleTypeCommand extends Command {
6
6
  static examples: string[];
7
7
  static flags: {
8
8
  help: import("@oclif/core/interfaces").BooleanFlag<void>;
9
- shell: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
9
+ shell: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
10
  multiplex: import("@oclif/core/interfaces").BooleanFlag<boolean>;
11
- new_space: import("@oclif/core/interfaces").BooleanFlag<boolean>;
11
+ new: import("@oclif/core/interfaces").BooleanFlag<boolean>;
12
12
  };
13
13
  static args: {
14
14
  streamKey: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
@@ -3,23 +3,23 @@ import { Command, Flags, Args } from '@oclif/core';
3
3
  import ora from 'ora';
4
4
  import { hostname, platform } from 'os';
5
5
  import chalk from 'chalk';
6
- import { Config, STREAM_KEY_SAMPLE } from '../../lib/config.js';
7
- import { App, parseStreamKey } from '../../lib/oorja/index.js';
8
- import { printExitMessage, promptStreamKey } from '../../lib/utils.js';
9
- import { Unauthorized } from '../../lib/connect/errors.js';
10
- import { exit } from '../../lib/exit.js';
6
+ import { Config, STREAM_KEY_SAMPLE } from 'oorja/lib/config';
7
+ import { App, parseStreamKey } from 'oorja/lib/oorja/index';
8
+ import { printExitMessage, promptStreamKey } from 'oorja/lib/utils';
9
+ import { Unauthorized } from 'oorja/lib/connect/errors';
10
+ import { exit } from 'oorja/lib/exit';
11
11
  const DEFAULT_SHELL = platform() === 'win32' ? 'powershell.exe' : process.env.SHELL || 'bash';
12
12
  export default class TeleTypeCommand extends Command {
13
13
  static order = 1;
14
14
  static aliases = ['tty'];
15
- static description = `Launch a terminal streaming session in oorja.`;
15
+ static description = `Launch a terminal streaming session in SupaKit.`;
16
16
  static examples = [
17
17
  `${chalk.blueBright('$ teletype')}
18
18
  Will prompt to choose streaming destination - either enter a stream key for an existing space or create a new space.
19
19
 
20
20
  `,
21
21
  `${chalk.blueBright(`$ teletype '${STREAM_KEY_SAMPLE}'`)}
22
- Will stream to the space using the secret stream-key. NOTE: stream-keys are personal (generated for you in the teletype app at oorja.io), do not accept them from other people, nor should
22
+ Will stream to the space using the secret stream-key. NOTE: stream-keys are personal (generated for you in the teletype app at supakit.app), do not accept them from other people, nor should
23
23
  you share your stream-keys with others.
24
24
 
25
25
  `,
@@ -33,16 +33,17 @@ Will also allow participants to write to your terminal! Collaboration mode must
33
33
  shell: Flags.string({
34
34
  char: 's',
35
35
  description: 'shell to use. e.g. bash, fish',
36
- default: DEFAULT_SHELL,
37
36
  }),
38
37
  multiplex: Flags.boolean({
39
38
  char: 'm',
40
39
  description: 'Allows users to WRITE TO YOUR SHELL i.e enables collaboration mode. Make sure you trust space participants. Off by default',
41
40
  default: false,
42
41
  }),
43
- new_space: Flags.boolean({
42
+ new: Flags.boolean({
43
+ aliases: ['new-space', 'new_space'],
44
44
  char: 'n',
45
- description: 'Create new space',
45
+ deprecateAliases: true,
46
+ description: 'Create a new space',
46
47
  default: false,
47
48
  }),
48
49
  };
@@ -50,14 +51,15 @@ Will also allow participants to write to your terminal! Collaboration mode must
50
51
  streamKey: Args.string({}),
51
52
  };
52
53
  async run() {
53
- const { args, flags: { shell, multiplex, new_space }, } = await this.parse(TeleTypeCommand);
54
+ const { args, flags: { shell: selectedShell, multiplex, new: createNewSpace }, } = await this.parse(TeleTypeCommand);
55
+ const shell = selectedShell || DEFAULT_SHELL;
54
56
  const config = new Config(this.config.configDir);
55
57
  const app = new App(config);
56
58
  if (args.streamKey) {
57
59
  await this.streamUsingStreamKey(app, { shell, multiplex, streamKey: args.streamKey });
58
60
  exit(0);
59
61
  }
60
- if (new_space) {
62
+ if (createNewSpace) {
61
63
  await this.createRoomAndStream(app, { shell, multiplex });
62
64
  exit(0);
63
65
  }
@@ -121,7 +123,7 @@ Will also allow participants to write to your terminal! Collaboration mode must
121
123
  printExitMessage('Failed to create space. Are you sure your access-token is valid?');
122
124
  }
123
125
  else {
124
- printExitMessage('Failed to create space. Try again later or try updating your oorja-cli');
126
+ printExitMessage('Failed to create space. Try again later or update the CLI: npm update -g oorja');
125
127
  }
126
128
  exit(9);
127
129
  return Promise.reject();
@@ -1,4 +1,4 @@
1
- export declare const CLI_VERSION = 2.8;
1
+ export declare const CLI_VERSION = 2.9;
2
2
  export type env = 'local' | 'prod';
3
3
  export declare class Config {
4
4
  streamKeyAuth: boolean;
@@ -1,7 +1,7 @@
1
1
  import chalk from 'chalk';
2
2
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
3
3
  import path from 'path';
4
- export const CLI_VERSION = 2.8;
4
+ export const CLI_VERSION = 2.9;
5
5
  export class Config {
6
6
  streamKeyAuth = false;
7
7
  configPath;
@@ -38,7 +38,7 @@ export class Config {
38
38
  }
39
39
  }
40
40
  getEnv = () => {
41
- return this.config['env'] ?? 'prod';
41
+ return this.config['env'] || 'prod';
42
42
  };
43
43
  getAccessToken = () => {
44
44
  return this.config[`${this.getEnv()}-access-token`] || '';
@@ -54,6 +54,7 @@ export const getConnectConfig = (env, region) => {
54
54
  case 'local':
55
55
  return 'localhost:4000';
56
56
  case 'prod':
57
+ default:
57
58
  return region ? `${region}.connect.oorja.io` : 'connect.oorja.io';
58
59
  }
59
60
  };
@@ -72,7 +73,7 @@ export const getoorjaConfig = (env) => {
72
73
  host = 'localhost:3000';
73
74
  break;
74
75
  case 'prod':
75
- host = 'oorja.io';
76
+ host = 'supakit.app';
76
77
  break;
77
78
  }
78
79
  return {
@@ -1,5 +1,5 @@
1
- import { User, RoomApps, Room, CliManifest, NewRoomInviteResponse } from './types.js';
2
- import { env } from '../config.js';
1
+ import { User, RoomApps, Room, CliManifest, NewRoomInviteResponse } from 'oorja/lib/connect/types';
2
+ import { env } from 'oorja/lib/config';
3
3
  import { Channel } from 'phoenix';
4
4
  export declare class ApiClientError extends Error {
5
5
  }
@@ -2,13 +2,13 @@
2
2
  import { Encoder, Decoder } from '@msgpack/msgpack';
3
3
  const encoder = new Encoder();
4
4
  const decoder = new Decoder();
5
- import { defaultParser } from './resources.js';
6
- import { getConnectConfig } from '../config.js';
7
- import { Unauthorized, BadRequest } from './errors.js';
5
+ import { defaultParser } from 'oorja/lib/connect/resources';
6
+ import { getConnectConfig } from 'oorja/lib/config';
7
+ import { Unauthorized, BadRequest } from 'oorja/lib/connect/errors';
8
8
  import { Socket, Presence } from 'phoenix';
9
9
  import camelcaseKeys from 'camelcase-keys';
10
- import { printExitMessage } from '../utils.js';
11
- import { exit } from '../exit.js';
10
+ import { printExitMessage } from 'oorja/lib/utils';
11
+ import { exit } from 'oorja/lib/exit';
12
12
  export class ApiClientError extends Error {
13
13
  }
14
14
  export class ConnectClient {
@@ -1,4 +1,4 @@
1
- import { RoomKey } from './connect/types.js';
1
+ import { RoomKey } from 'oorja/lib/connect/types';
2
2
  export type EncryptedPayload = {
3
3
  iv: Buffer | Uint8Array;
4
4
  data: Buffer | Uint8Array;
@@ -1 +1,2 @@
1
+ export declare const CLI_OUTDATED_EXIT_CODE = 42;
1
2
  export declare function exit(exitCode?: number, streams?: any): void;
package/dist/lib/exit.js CHANGED
@@ -8,11 +8,12 @@
8
8
  * Licensed under the MIT license.
9
9
  */
10
10
  'use strict';
11
+ export const CLI_OUTDATED_EXIT_CODE = 42;
11
12
  export function exit(exitCode = 0, streams) {
12
13
  if (!streams) {
13
14
  streams = [process.stdout, process.stderr];
14
15
  }
15
- var drainCount = 0;
16
+ let drainCount = 0;
16
17
  // Actually exit if all streams are drained.
17
18
  function tryToExit() {
18
19
  if (drainCount === streams.length) {
@@ -1,13 +1,13 @@
1
1
  import haversine from 'haversine-distance';
2
- import { printExitMessage } from '../utils.js';
3
- import { exit } from '../exit.js';
4
- import { geoMap } from './geoMap.js';
2
+ import { printExitMessage } from 'oorja/lib/utils';
3
+ import { exit } from 'oorja/lib/exit';
4
+ import { geoMap } from 'oorja/lib/oorja/geoMap';
5
5
  export class OorjaClientError extends Error {
6
6
  }
7
7
  const _maybeError = (response) => {
8
8
  const { status } = response;
9
9
  if (status >= 400) {
10
- throw new OorjaClientError('oorja network client error');
10
+ throw new OorjaClientError('SupaKit network client error');
11
11
  }
12
12
  };
13
13
  class Client {
@@ -26,7 +26,7 @@ class Client {
26
26
  }
27
27
  const _client = new Client();
28
28
  export const getRegion = async () => {
29
- const response = await _client.get('https://oorja.io/nudge', {
29
+ const response = await _client.get('https://supakit.app/nudge', {
30
30
  method: 'GET',
31
31
  });
32
32
  if (response.status !== 200) {
@@ -1,8 +1,8 @@
1
- import { oorjaConfig, Config } from '../config.js';
2
- import { RoomKey, UserProfile } from '../connect/types.js';
3
- import { TeletypeOptions } from '../teletype/index.js';
4
- import { CreateRoomOptions, ConnectClient } from '../connect/index.js';
5
- import { Future } from '../utils.js';
1
+ import { oorjaConfig, Config } from 'oorja/lib/config';
2
+ import { RoomKey, UserProfile } from 'oorja/lib/connect/types';
3
+ import { TeletypeOptions } from 'oorja/lib/teletype/index';
4
+ import { CreateRoomOptions, ConnectClient } from 'oorja/lib/connect/index';
5
+ import { Future } from 'oorja/lib/utils';
6
6
  export declare class InvalidRoomLink extends Error {
7
7
  }
8
8
  export declare class OORJA {
@@ -11,13 +11,13 @@ export declare class OORJA {
11
11
  user: UserProfile;
12
12
  constructor(config: oorjaConfig, connectClient: ConnectClient, user: UserProfile);
13
13
  createRoom: (options: CreateRoomOptions) => Promise<{
14
- room: import("../connect/types.js").Room;
14
+ room: import("oorja/lib/connect/types").Room;
15
15
  roomKey: RoomKey;
16
16
  inviteCode: string;
17
17
  }>;
18
18
  linkForRoom: (roomKey: RoomKey, inviteCode: string) => string;
19
19
  getRoomKey(streamKey: StreamKey): RoomKey;
20
- teletype: (options: Omit<TeletypeOptions, "userId" | "joinChannel">) => Promise<unknown>;
20
+ teletype: (options: Omit<TeletypeOptions, "userId" | "joinChannel">) => Promise<null>;
21
21
  }
22
22
  type StreamKey = {
23
23
  roomId: string;
@@ -1,13 +1,13 @@
1
- import { getoorjaConfig, INVALID_STREAM_KEY_MESSAGE } from '../config.js';
2
- import { teletypeApp } from '../teletype/index.js';
3
- import { ConnectClient } from '../connect/index.js';
4
- import { importKey, createRoomKey, exportKey } from '../encryption.js';
5
- import { promptAuth, validateCliVersion } from './preflight.js';
6
- import { getRegion } from './client.js';
1
+ import { getoorjaConfig, INVALID_STREAM_KEY_MESSAGE } from 'oorja/lib/config';
2
+ import { TeletypeSession } from 'oorja/lib/teletype/index';
3
+ import { ConnectClient } from 'oorja/lib/connect/index';
4
+ import { importKey, createRoomKey, exportKey } from 'oorja/lib/encryption';
5
+ import { promptAuth, validateCliVersion } from 'oorja/lib/oorja/preflight';
6
+ import { getRegion } from 'oorja/lib/oorja/client';
7
7
  import ora from 'ora';
8
- import { Future, printExitMessage } from '../utils.js';
9
- import { Unauthorized } from '../connect/errors.js';
10
- import { exit } from '../exit.js';
8
+ import { Future, printExitMessage } from 'oorja/lib/utils';
9
+ import { Unauthorized } from 'oorja/lib/connect/errors';
10
+ import { exit } from 'oorja/lib/exit';
11
11
  import chalk from 'chalk';
12
12
  export class InvalidRoomLink extends Error {
13
13
  }
@@ -41,11 +41,11 @@ export class OORJA {
41
41
  };
42
42
  }
43
43
  teletype = (options) => {
44
- return teletypeApp({
44
+ return new TeletypeSession({
45
45
  userId: this.user.id,
46
46
  joinChannel: this.connectClient.joinChannel,
47
47
  ...options,
48
- });
48
+ }).run();
49
49
  };
50
50
  }
51
51
  export const parseStreamKey = (streamKey) => {
@@ -156,7 +156,7 @@ export class App {
156
156
  await validateCliVersion(connectClient);
157
157
  this.connectClient = connectClient;
158
158
  }
159
- catch (e) {
159
+ catch {
160
160
  this.connectionCheckFailed = true;
161
161
  }
162
162
  finally {
@@ -1,3 +1,3 @@
1
- import { ConnectClient } from '../connect/index.js';
1
+ import { ConnectClient } from 'oorja/lib/connect/index';
2
2
  export declare const promptAuth: (connectClient: ConnectClient, generateTokenLink: string) => Promise<string>;
3
3
  export declare const validateCliVersion: (connectClient: ConnectClient) => Promise<void>;
@@ -1,8 +1,8 @@
1
1
  import chalk from 'chalk';
2
2
  import inquirer from 'inquirer';
3
- import { CLI_VERSION } from '../config.js';
4
- import { printExitMessage } from '../utils.js';
5
- import { exit } from '../exit.js';
3
+ import { CLI_VERSION } from 'oorja/lib/config';
4
+ import { printExitMessage } from 'oorja/lib/utils';
5
+ import { CLI_OUTDATED_EXIT_CODE, exit } from 'oorja/lib/exit';
6
6
  const promptToken = () => inquirer
7
7
  .prompt([
8
8
  {
@@ -14,7 +14,7 @@ const promptToken = () => inquirer
14
14
  .then((answers) => answers.accessToken);
15
15
  export const promptAuth = async (connectClient, generateTokenLink) => {
16
16
  const ANON = 'Proceed as an anonymous user';
17
- const SIGN_IN = 'Sign-in with oorja';
17
+ const SIGN_IN = 'Sign in with SupaKit';
18
18
  console.log(`\n${chalk.bold('PRO-TIP:')} If you sign-in, you can control your shell from the web-ui as well, without enabling collaboration mode for the other participants\n`);
19
19
  const { answer } = await inquirer.prompt([
20
20
  {
@@ -37,7 +37,7 @@ export const promptAuth = async (connectClient, generateTokenLink) => {
37
37
  export const validateCliVersion = async (connectClient) => {
38
38
  const manifest = await connectClient.fetchCliManifest();
39
39
  if (manifest.cliVersion > CLI_VERSION) {
40
- printExitMessage(chalk.redBright('Your oorja cli is outdated. Please run: npm update -g oorja'));
41
- exit(1);
40
+ printExitMessage(chalk.redBright('Your CLI is outdated. Please run: npm update -g oorja'));
41
+ exit(CLI_OUTDATED_EXIT_CODE);
42
42
  }
43
43
  };
@@ -1,5 +1,5 @@
1
- import { RoomKey } from '../connect/types.js';
2
- import { JoinChannelOptions } from '../connect/index.js';
1
+ import { RoomKey } from 'oorja/lib/connect/types';
2
+ import { JoinChannelOptions } from 'oorja/lib/connect/index';
3
3
  import { Channel } from 'phoenix';
4
4
  export type TeletypeOptions = {
5
5
  userId: string;
@@ -14,5 +14,28 @@ type TeletypeChannelParams = {
14
14
  hostname: string;
15
15
  multiplexed: boolean;
16
16
  };
17
- export declare const teletypeApp: (options: TeletypeOptions) => Promise<unknown>;
17
+ export declare class TeletypeSession {
18
+ private readonly options;
19
+ private readonly username;
20
+ private readonly hostname;
21
+ private readonly userDimensions;
22
+ private channel;
23
+ private term;
24
+ private sessionCount;
25
+ private ptyReady;
26
+ private readonly ptyFuture;
27
+ private stopped;
28
+ private cleanupShell;
29
+ private resolve?;
30
+ constructor(options: TeletypeOptions);
31
+ run: () => Promise<null>;
32
+ private startTerm;
33
+ private reEvaluateOwnDimensions;
34
+ private handleClose;
35
+ private handleError;
36
+ private handleMessage;
37
+ private handleSessionJoin;
38
+ private handleSessionLeave;
39
+ private stop;
40
+ }
18
41
  export {};
@@ -1,11 +1,11 @@
1
1
  import { spawn } from 'node-pty';
2
2
  import * as os from 'os';
3
- import { getDimensions, initScreen, areDimensionEqual, resizeBestFit } from './auxiliary.js';
3
+ import { getDimensions, initScreen, areDimensionEqual, resizeBestFit } from 'oorja/lib/teletype/auxiliary';
4
4
  import chalk from 'chalk';
5
- import { Unauthorized } from '../connect/errors.js';
6
- import { encrypt, decrypt } from '../encryption.js';
7
- import { Future, printExitMessage } from '../utils.js';
8
- import { exit } from '../exit.js';
5
+ import { Unauthorized } from 'oorja/lib/connect/errors';
6
+ import { encrypt, decrypt } from 'oorja/lib/encryption';
7
+ import { Future, printExitMessage } from 'oorja/lib/utils';
8
+ import { exit } from 'oorja/lib/exit';
9
9
  var MessageType;
10
10
  (function (MessageType) {
11
11
  MessageType["IN"] = "i";
@@ -13,139 +13,188 @@ var MessageType;
13
13
  MessageType["DIMENSIONS"] = "d";
14
14
  })(MessageType || (MessageType = {}));
15
15
  const SELF = 'self';
16
- export const teletypeApp = (options) => {
17
- const username = os.userInfo().username;
18
- const hostname = os.hostname();
19
- const userDimensions = {};
20
- userDimensions[SELF] = getDimensions();
21
- let term;
22
- const reEvaluateOwnDimensions = () => {
23
- const lastKnown = userDimensions[SELF];
16
+ export class TeletypeSession {
17
+ options;
18
+ username = os.userInfo().username;
19
+ hostname = os.hostname();
20
+ userDimensions = {
21
+ [SELF]: getDimensions(),
22
+ };
23
+ channel;
24
+ term;
25
+ sessionCount = 0;
26
+ ptyReady = false;
27
+ ptyFuture = new Future();
28
+ stopped = false;
29
+ cleanupShell = () => { };
30
+ resolve;
31
+ constructor(options) {
32
+ this.options = options;
33
+ }
34
+ run = () => new Promise((resolve) => {
35
+ this.resolve = resolve;
36
+ this.channel = this.options.joinChannel({
37
+ channel: `teletype:${this.options.roomKey.roomId}`,
38
+ params: {
39
+ username: this.username,
40
+ hostname: this.hostname,
41
+ multiplexed: this.options.multiplex,
42
+ },
43
+ onJoin: this.startTerm,
44
+ onClose: this.handleClose,
45
+ onError: this.handleError,
46
+ onMessage: this.handleMessage,
47
+ handleSessionJoin: this.handleSessionJoin,
48
+ handleSessionLeave: this.handleSessionLeave,
49
+ });
50
+ });
51
+ startTerm = () => {
52
+ const { stdin, stdout } = this.options.process;
53
+ const dimensions = this.userDimensions[SELF];
54
+ console.log(chalk.blue(`${chalk.bold(`${this.username}@${this.hostname}`)} Spawning streaming shell: ${chalk.bold(`${this.options.shell}`)}`));
55
+ this.term = spawn(this.options.shell, [], {
56
+ name: 'xterm-256color',
57
+ cols: dimensions.cols,
58
+ rows: dimensions.rows,
59
+ cwd: this.options.process.cwd(),
60
+ env: this.options.process.env,
61
+ });
62
+ this.ptyFuture.promise.then(() => {
63
+ initScreen(this.username, this.hostname, this.options.shell, this.options.multiplex);
64
+ if (this.options.shell.endsWith('bash')) {
65
+ stdout.write('Adjusting shell prompt to show streaming indicator\n');
66
+ this.term.write("export PS1='📡 [streaming] '$PS1\n");
67
+ }
68
+ if (this.options.shell.endsWith('zsh')) {
69
+ stdout.write('Adjusting shell prompt to show streaming indicator\n');
70
+ // FIXME: this doesnt work on macos (or its probably due to some conflict with powerlevel10k)
71
+ this.term.write("PROMPT='📡 [streaming] '$PROMPT\n");
72
+ }
73
+ if (this.options.shell.endsWith('fish')) {
74
+ stdout.write('Adjusting shell prompt to show streaming indicator\n');
75
+ this.term.write('functions -c fish_prompt __orig_fish_prompt; ' +
76
+ "function fish_prompt; echo -n '📡 [streaming] '; __orig_fish_prompt; end\n");
77
+ }
78
+ });
79
+ // track own dimensions and keep it up to date
80
+ const dimensionPoll = setInterval(this.reEvaluateOwnDimensions, 1000);
81
+ const ptyDataSubscription = this.term.onData((d) => {
82
+ stdout.write(d);
83
+ if (!this.ptyReady) {
84
+ this.ptyReady = true;
85
+ setTimeout(() => {
86
+ this.ptyFuture.resolve(true);
87
+ }, 100);
88
+ }
89
+ if (this.sessionCount < 2) {
90
+ // 1 sub for own channel session
91
+ // < 2 means no subscribers. no point pushing data.
92
+ return;
93
+ }
94
+ this.channel.push('new_msg', {
95
+ t: MessageType.OUT,
96
+ b: true,
97
+ d: encrypt(d, this.options.roomKey),
98
+ });
99
+ });
100
+ const ptyExitSubscription = this.term.onExit(() => {
101
+ console.log(chalk.blueBright('terminated shell stream to SupaKit. byee!'));
102
+ this.stop({ killTerm: false });
103
+ this.resolve?.(null);
104
+ });
105
+ stdin.setEncoding('utf8');
106
+ stdin.setRawMode(true);
107
+ const stdinDataHandler = (d) => this.term.write(d.toString('utf8'));
108
+ stdin.on('data', stdinDataHandler);
109
+ this.cleanupShell = ({ killTerm = true } = {}) => {
110
+ clearInterval(dimensionPoll);
111
+ ptyDataSubscription.dispose();
112
+ ptyExitSubscription.dispose();
113
+ stdin.off('data', stdinDataHandler);
114
+ stdin.setRawMode(false);
115
+ if (killTerm) {
116
+ this.term.kill();
117
+ }
118
+ };
119
+ };
120
+ reEvaluateOwnDimensions = () => {
121
+ const lastKnown = this.userDimensions[SELF];
24
122
  const latest = getDimensions();
25
123
  if (areDimensionEqual(lastKnown, latest)) {
26
124
  return;
27
125
  }
28
- userDimensions[SELF] = latest;
29
- resizeBestFit(term, userDimensions);
126
+ this.userDimensions[SELF] = latest;
127
+ resizeBestFit(this.term, this.userDimensions);
30
128
  };
31
- return new Promise((resolve, reject) => {
32
- let sessionCount = 0;
33
- let ptyReady = false;
34
- const ptyFuture = new Future();
35
- const channel = options.joinChannel({
36
- channel: `teletype:${options.roomKey.roomId}`,
37
- params: {
38
- username,
39
- hostname,
40
- multiplexed: options.multiplex,
41
- },
42
- onJoin: () => {
43
- const stdin = options.process.stdin;
44
- const stdout = options.process.stdout;
45
- const dimensions = userDimensions[SELF];
46
- console.log(chalk.blue(`${chalk.bold(`${username}@${hostname}`)} Spawning streaming shell: ${chalk.bold(`${options.shell}`)}`));
47
- term = spawn(options.shell, [], {
48
- name: 'xterm-256color',
49
- cols: dimensions.cols,
50
- rows: dimensions.rows,
51
- cwd: options.process.cwd(),
52
- env: options.process.env,
53
- });
54
- ptyFuture.promise.then(() => {
55
- initScreen(username, hostname, options.shell, options.multiplex);
56
- if (options.shell.endsWith('bash')) {
57
- stdout.write('Adjusting shell prompt to show streaming indicator\n');
58
- term.write("export PS1='📡 [streaming] '$PS1\n");
59
- }
60
- if (options.shell.endsWith('zsh')) {
61
- stdout.write('Adjusting shell prompt to show streaming indicator\n');
62
- // FIXME: this doesnt work on macos (or its probably due to some conflict with powerlevel10k)
63
- term.write("PROMPT='📡 [streaming] '$PROMPT\n");
64
- }
65
- if (options.shell.endsWith('fish')) {
66
- stdout.write('Adjusting shell prompt to show streaming indicator\n');
67
- term.write('functions -c fish_prompt __orig_fish_prompt; ' +
68
- "function fish_prompt; echo -n '📡 [streaming] '; __orig_fish_prompt; end\n");
69
- }
70
- });
71
- // track own dimensions and keep it up to date
72
- setInterval(reEvaluateOwnDimensions, 1000);
73
- term.onData((d) => {
74
- stdout.write(d);
75
- if (!ptyReady) {
76
- ptyReady = true;
77
- setTimeout(() => {
78
- ptyFuture.resolve(true);
79
- }, 100);
80
- }
81
- if (sessionCount < 2) {
82
- // 1 sub for own channel session
83
- // < 2 means no subscribers. no point pushing data.
84
- return;
85
- }
86
- channel.push('new_msg', {
87
- t: MessageType.OUT,
88
- b: true,
89
- d: encrypt(d, options.roomKey),
90
- });
91
- });
92
- term.onExit(() => {
93
- console.log(chalk.blueBright('terminated shell stream to oorja. byee!'));
94
- resolve(null);
95
- });
96
- stdin.setEncoding('utf8');
97
- stdin.setRawMode(true);
98
- stdin.on('data', (d) => term.write(d.toString('utf8')));
99
- },
100
- onClose: () => {
101
- printExitMessage(chalk.redBright('connection closed, terminated stream.'));
102
- exit(3);
103
- },
104
- onError: (err) => {
105
- if (err instanceof Unauthorized) {
106
- printExitMessage(chalk.redBright(err.message));
129
+ handleClose = () => {
130
+ if (this.stopped) {
131
+ return;
132
+ }
133
+ this.stop({ leaveChannel: false });
134
+ printExitMessage(chalk.redBright('connection closed, terminated stream.'));
135
+ exit(3);
136
+ };
137
+ handleError = (err) => {
138
+ this.stop({ leaveChannel: false });
139
+ if (err instanceof Unauthorized) {
140
+ printExitMessage(chalk.redBright(err.message));
141
+ }
142
+ else {
143
+ printExitMessage(chalk.redBright('connection error, terminated stream.'));
144
+ }
145
+ exit(4);
146
+ };
147
+ handleMessage = ({ from: { session }, t, d }) => {
148
+ switch (t) {
149
+ case MessageType.DIMENSIONS:
150
+ this.userDimensions[session] = d;
151
+ resizeBestFit(this.term, this.userDimensions, d.initial);
152
+ break;
153
+ case MessageType.IN: {
154
+ const data = decrypt(d, this.options.roomKey);
155
+ const userId = session.split(':')[0];
156
+ const userType = session.split(':')[2];
157
+ if (userType === 'task') {
158
+ this.stop();
159
+ printExitMessage(chalk.redBright(`unexpected input from user: ${userId} with task-token, terminating stream for safety. Please report this issue`));
160
+ exit(5);
161
+ return;
107
162
  }
108
- else {
109
- printExitMessage(chalk.redBright('connection error, terminated stream.'));
163
+ if (this.options.multiplex) {
164
+ this.term.write(data);
165
+ return;
110
166
  }
111
- exit(4);
112
- },
113
- onMessage: ({ from: { session }, t, d }) => {
114
- switch (t) {
115
- case MessageType.DIMENSIONS:
116
- userDimensions[session] = d;
117
- resizeBestFit(term, userDimensions, d.initial);
118
- break;
119
- case MessageType.IN:
120
- const data = decrypt(d, options.roomKey);
121
- const userId = session.split(':')[0];
122
- const userType = session.split(':')[2];
123
- if (userType === 'task') {
124
- printExitMessage(chalk.redBright(`unexpected input from user: ${userId} with task-token, terminating stream for safety. Please report this issue`));
125
- exit(5);
126
- return;
127
- }
128
- if (options.multiplex) {
129
- term.write(data);
130
- return;
131
- }
132
- if (userId === options.userId) {
133
- term.write(data);
134
- }
135
- else {
136
- printExitMessage(chalk.redBright(`unexpected input from user: ${userId}, terminating stream for safety. Please report this issue`));
137
- exit(5);
138
- }
167
+ if (userId === this.options.userId) {
168
+ this.term.write(data);
139
169
  }
140
- },
141
- handleSessionJoin: (s) => {
142
- sessionCount++;
143
- },
144
- handleSessionLeave: (s) => {
145
- sessionCount -= 1;
146
- s && delete userDimensions[s];
147
- resizeBestFit(term, userDimensions);
148
- },
149
- });
150
- });
151
- };
170
+ else {
171
+ this.stop();
172
+ printExitMessage(chalk.redBright(`unexpected input from user: ${userId}, terminating stream for safety. Please report this issue`));
173
+ exit(5);
174
+ }
175
+ break;
176
+ }
177
+ }
178
+ };
179
+ handleSessionJoin = () => {
180
+ this.sessionCount++;
181
+ };
182
+ handleSessionLeave = (s) => {
183
+ this.sessionCount -= 1;
184
+ if (s) {
185
+ delete this.userDimensions[s];
186
+ }
187
+ resizeBestFit(this.term, this.userDimensions);
188
+ };
189
+ stop = ({ killTerm = true, leaveChannel = true } = {}) => {
190
+ if (this.stopped) {
191
+ return;
192
+ }
193
+ this.stopped = true;
194
+ this.cleanupShell({ killTerm });
195
+ this.cleanupShell = () => { };
196
+ if (leaveChannel) {
197
+ this.channel.leave(1000);
198
+ }
199
+ };
200
+ }
@@ -3,7 +3,7 @@
3
3
  "signout": {
4
4
  "aliases": [],
5
5
  "args": {},
6
- "description": "Sign-out of oorja. Clears saved auth-token",
6
+ "description": "Sign out of SupaKit. Clears saved auth-token",
7
7
  "flags": {},
8
8
  "hasDynamicHelp": false,
9
9
  "hiddenAliases": [],
@@ -29,10 +29,10 @@
29
29
  "name": "streamKey"
30
30
  }
31
31
  },
32
- "description": "Launch a terminal streaming session in oorja.",
32
+ "description": "Launch a terminal streaming session in SupaKit.",
33
33
  "examples": [
34
34
  "\u001b[94m$ teletype\u001b[39m\nWill prompt to choose streaming destination - either enter a stream key for an existing space or create a new space.\n\n",
35
- "\u001b[94m$ teletype 'sk-xxxx:space-id#encryption-secret'\u001b[39m\nWill stream to the space using the secret stream-key. NOTE: stream-keys are personal (generated for you in the teletype app at oorja.io), do not accept them from other people, nor should\nyou share your stream-keys with others.\n\n",
35
+ "\u001b[94m$ teletype 'sk-xxxx:space-id#encryption-secret'\u001b[39m\nWill stream to the space using the secret stream-key. NOTE: stream-keys are personal (generated for you in the teletype app at supakit.app), do not accept them from other people, nor should\nyou share your stream-keys with others.\n\n",
36
36
  "\u001b[94m$ teletype -m\u001b[39m\nWill also allow participants to write to your terminal! Collaboration mode must be explicitly enabled.\n\n"
37
37
  ],
38
38
  "flags": {
@@ -47,7 +47,6 @@
47
47
  "char": "s",
48
48
  "description": "shell to use. e.g. bash, fish",
49
49
  "name": "shell",
50
- "default": "/usr/bin/zsh",
51
50
  "hasDynamicHelp": false,
52
51
  "multiple": false,
53
52
  "type": "option"
@@ -59,10 +58,15 @@
59
58
  "allowNo": false,
60
59
  "type": "boolean"
61
60
  },
62
- "new_space": {
61
+ "new": {
62
+ "aliases": [
63
+ "new-space",
64
+ "new_space"
65
+ ],
63
66
  "char": "n",
64
- "description": "Create new space",
65
- "name": "new_space",
67
+ "deprecateAliases": true,
68
+ "description": "Create a new space",
69
+ "name": "new",
66
70
  "allowNo": false,
67
71
  "type": "boolean"
68
72
  }
@@ -85,5 +89,5 @@
85
89
  ]
86
90
  }
87
91
  },
88
- "version": "2.3.0"
92
+ "version": "2.5.1"
89
93
  }
package/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "name": "oorja",
3
3
  "description": "stream terminals to the web and more.",
4
- "version": "2.3.0",
4
+ "version": "2.5.1",
5
+ "packageManager": "pnpm@11.5.2",
5
6
  "keywords": [
6
7
  "teletype",
7
8
  "terminal",
@@ -15,7 +16,16 @@
15
16
  "license": "SEE LICENSE IN license.txt",
16
17
  "author": "Akshay Kumar",
17
18
  "type": "module",
18
- "exports": "./lib/index.js",
19
+ "exports": {
20
+ ".": {
21
+ "types": "./dist/index.d.ts",
22
+ "default": "./dist/index.js"
23
+ },
24
+ "./*": {
25
+ "types": "./src/*.ts",
26
+ "default": "./dist/*.js"
27
+ }
28
+ },
19
29
  "types": "dist/index.d.ts",
20
30
  "bin": {
21
31
  "oorja": "./bin/run.js",
@@ -28,17 +38,21 @@
28
38
  ],
29
39
  "scripts": {
30
40
  "build": "shx rm -rf dist && tsc -b",
41
+ "docs:commands": "pnpm run build && pnpm run docs:commands:generate",
42
+ "docs:commands:generate": "oclif readme --no-aliases --no-source-links && node scripts/order-readme-commands.mjs",
31
43
  "lint": "eslint . --ext .ts",
32
- "prepack": "yarn build && oclif manifest && oclif readme",
33
- "postpack": "shx rm -f oclif.manifest.json",
34
- "prepare": "yarn build",
35
- "version": "oclif readme && git add README.md",
44
+ "prepack": "pnpm run build && oclif manifest && pnpm run docs:commands:generate",
45
+ "prepare": "pnpm run build",
46
+ "version": "pnpm run docs:commands && git add README.md",
36
47
  "format": "prettier --write ."
37
48
  },
38
49
  "oclif": {
39
50
  "bin": "oorja",
40
51
  "commands": "./dist/commands",
41
- "dirname": "oorja"
52
+ "dirname": "oorja",
53
+ "plugins": [
54
+ "@oclif/plugin-help"
55
+ ]
42
56
  },
43
57
  "dependencies": {
44
58
  "@msgpack/msgpack": "3.1.2",
@@ -48,24 +62,27 @@
48
62
  "chalk": "^5.6.2",
49
63
  "haversine-distance": "^1.2.4",
50
64
  "inquirer": "^12.9.4",
51
- "node-pty": "^1.0.0",
65
+ "node-pty": "^1.1.0",
52
66
  "ora": "^8.2.0",
53
67
  "phoenix": "1.8.1",
54
68
  "terminal-size": "^4.0.0"
55
69
  },
56
70
  "devDependencies": {
71
+ "@eslint/js": "^9.35.0",
57
72
  "@oclif/prettier-config": "^0.2.1",
58
73
  "@types/inquirer": "^9.0.9",
59
74
  "@types/node": "^22.10.2",
60
75
  "@types/phoenix": "^1.6.6",
61
- "eslint": "^9.35.0",
76
+ "eslint": "^9.39.4",
62
77
  "eslint-config-oclif": "^6.0.102",
63
78
  "eslint-config-prettier": "^10.1.8",
64
- "oclif": "^4.22.18",
79
+ "globals": "^16.4.0",
80
+ "oclif": "^4.23.10",
65
81
  "prettier": "^3.6.2",
66
82
  "shx": "^0.4.0",
67
83
  "ts-node": "^10.9.2",
68
- "typescript": "^5.9.2"
84
+ "typescript": "^5.9.2",
85
+ "typescript-eslint": "^8.43.0"
69
86
  },
70
87
  "engines": {
71
88
  "node": ">=22.10.0"