oorja 2.0.8 → 2.1.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 +2 -2
- package/dist/commands/teletype/index.js +2 -1
- package/dist/lib/config.d.ts +1 -1
- package/dist/lib/config.js +1 -1
- package/dist/lib/connect/index.d.ts +4 -1
- package/dist/lib/connect/index.js +66 -31
- package/dist/lib/teletype/index.js +26 -4
- package/oclif.manifest.json +1 -1
- package/package.json +15 -16
package/README.md
CHANGED
|
@@ -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://
|
|
12
|
+
<img width="600" src="https://oorja.io/images/cli-demo.svg">
|
|
13
13
|
</p>
|
|
14
14
|
|
|
15
15
|
<p align="center">
|
|
16
|
-
<img src="https://
|
|
16
|
+
<img src="https://oorja.io/images/teletype-session.png">
|
|
17
17
|
</p>
|
|
18
18
|
|
|
19
19
|
Your stream can be view-only or collaboration enabled (command-line flag).
|
|
@@ -95,9 +95,10 @@ Will also allow participants to write to your terminal!
|
|
|
95
95
|
text: chalk.bold('Creating space with TeleType app'),
|
|
96
96
|
discardStdin: false,
|
|
97
97
|
}).start();
|
|
98
|
+
const now = new Date();
|
|
98
99
|
const { roomKey } = await app
|
|
99
100
|
.createRoom({
|
|
100
|
-
roomName:
|
|
101
|
+
roomName: `Teletype session - ${os.hostname()} @ ${now.getHours()}:${now.getMinutes().toString().padStart(2, '0')}`,
|
|
101
102
|
apps: {
|
|
102
103
|
defaultFocus: '39',
|
|
103
104
|
appList: [
|
package/dist/lib/config.d.ts
CHANGED
package/dist/lib/config.js
CHANGED
|
@@ -5,9 +5,12 @@ export declare class ApiClientError extends Error {
|
|
|
5
5
|
}
|
|
6
6
|
export declare class ConnectClient {
|
|
7
7
|
private config;
|
|
8
|
-
private
|
|
8
|
+
private baseURL;
|
|
9
|
+
private headers;
|
|
10
|
+
private timeout;
|
|
9
11
|
private socket?;
|
|
10
12
|
constructor(env: env, region: string);
|
|
13
|
+
private _fetch;
|
|
11
14
|
fetchCliManifest: () => Promise<CliManifest>;
|
|
12
15
|
fetchSessionUser: () => Promise<User>;
|
|
13
16
|
createRoom: ({ roomName, apps }: CreateRoomOptions) => Promise<Room>;
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
// backend api client
|
|
2
|
-
import https from 'https';
|
|
3
|
-
import axios, { AxiosError } from 'axios';
|
|
4
2
|
import { Encoder, Decoder } from '@msgpack/msgpack';
|
|
5
|
-
const encoder = new Encoder(
|
|
3
|
+
const encoder = new Encoder();
|
|
6
4
|
const decoder = new Decoder();
|
|
7
5
|
import { defaultParser } from './resources.js';
|
|
8
6
|
import { getConnectConfig } from '../config.js';
|
|
@@ -13,28 +11,51 @@ export class ApiClientError extends Error {
|
|
|
13
11
|
}
|
|
14
12
|
export class ConnectClient {
|
|
15
13
|
config;
|
|
16
|
-
|
|
14
|
+
baseURL;
|
|
15
|
+
headers;
|
|
16
|
+
timeout;
|
|
17
17
|
socket;
|
|
18
18
|
constructor(env, region) {
|
|
19
19
|
const config = getConnectConfig(env, region);
|
|
20
|
-
this.
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
timeout: 5000,
|
|
27
|
-
responseType: 'json',
|
|
28
|
-
headers: {
|
|
29
|
-
'x-access-token': config.token || '',
|
|
30
|
-
},
|
|
31
|
-
});
|
|
20
|
+
this.baseURL = connectBaseURL(config.host);
|
|
21
|
+
this.headers = {
|
|
22
|
+
'x-access-token': config.token || '',
|
|
23
|
+
'Content-Type': 'application/json',
|
|
24
|
+
};
|
|
25
|
+
this.timeout = 5000;
|
|
32
26
|
this.config = config;
|
|
33
27
|
}
|
|
28
|
+
// Private helper to encapsulate fetch with timeout and consistent error handling.
|
|
29
|
+
async _fetch(path, options = {}) {
|
|
30
|
+
const controller = new AbortController();
|
|
31
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
32
|
+
try {
|
|
33
|
+
const response = await fetch(`${this.baseURL}${path}`, {
|
|
34
|
+
...options,
|
|
35
|
+
headers: this.headers,
|
|
36
|
+
signal: controller.signal,
|
|
37
|
+
});
|
|
38
|
+
if (!response.ok) {
|
|
39
|
+
// Throw an object that mimics the AxiosError structure for the handleError function.
|
|
40
|
+
throw { response };
|
|
41
|
+
}
|
|
42
|
+
return response;
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
if (error.name === 'AbortError') {
|
|
46
|
+
throw new Error('Request timed out');
|
|
47
|
+
}
|
|
48
|
+
throw error; // Re-throw other errors (like the custom {response} or network errors)
|
|
49
|
+
}
|
|
50
|
+
finally {
|
|
51
|
+
clearTimeout(timeoutId);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
34
54
|
fetchCliManifest = async () => {
|
|
35
55
|
try {
|
|
36
|
-
const response = await this.
|
|
37
|
-
|
|
56
|
+
const response = await this._fetch('/cli');
|
|
57
|
+
const data = await response.json();
|
|
58
|
+
return camelcaseKeys(data);
|
|
38
59
|
}
|
|
39
60
|
catch (error) {
|
|
40
61
|
return handleError(error);
|
|
@@ -42,8 +63,9 @@ export class ConnectClient {
|
|
|
42
63
|
};
|
|
43
64
|
fetchSessionUser = async () => {
|
|
44
65
|
try {
|
|
45
|
-
const response = await this.
|
|
46
|
-
|
|
66
|
+
const response = await this._fetch('/session/user');
|
|
67
|
+
const data = await response.json();
|
|
68
|
+
return defaultParser(data.data);
|
|
47
69
|
}
|
|
48
70
|
catch (error) {
|
|
49
71
|
return handleError(error);
|
|
@@ -58,8 +80,12 @@ export class ConnectClient {
|
|
|
58
80
|
},
|
|
59
81
|
};
|
|
60
82
|
try {
|
|
61
|
-
const response = await this.
|
|
62
|
-
|
|
83
|
+
const response = await this._fetch('/rooms', {
|
|
84
|
+
method: 'POST',
|
|
85
|
+
body: JSON.stringify(body),
|
|
86
|
+
});
|
|
87
|
+
const data = await response.json();
|
|
88
|
+
return defaultParser(data.data);
|
|
63
89
|
}
|
|
64
90
|
catch (error) {
|
|
65
91
|
return handleError(error);
|
|
@@ -67,8 +93,9 @@ export class ConnectClient {
|
|
|
67
93
|
};
|
|
68
94
|
createAnonymousUser = async () => {
|
|
69
95
|
try {
|
|
70
|
-
const response = await this.
|
|
71
|
-
|
|
96
|
+
const response = await this._fetch('/session/anon', { method: 'POST' });
|
|
97
|
+
const data = await response.json();
|
|
98
|
+
return data.access_token;
|
|
72
99
|
}
|
|
73
100
|
catch (error) {
|
|
74
101
|
return handleError(error);
|
|
@@ -76,11 +103,15 @@ export class ConnectClient {
|
|
|
76
103
|
};
|
|
77
104
|
accessTokenFromRoomParticipantOTP = async (roomId, otp) => {
|
|
78
105
|
try {
|
|
79
|
-
const response = await this.
|
|
80
|
-
|
|
81
|
-
|
|
106
|
+
const response = await this._fetch('/access_tokens/from_room_participant_otp', {
|
|
107
|
+
method: 'POST',
|
|
108
|
+
body: JSON.stringify({
|
|
109
|
+
room_id: roomId,
|
|
110
|
+
otp: otp,
|
|
111
|
+
}),
|
|
82
112
|
});
|
|
83
|
-
|
|
113
|
+
const data = await response.json();
|
|
114
|
+
return data.data.token;
|
|
84
115
|
}
|
|
85
116
|
catch (error) {
|
|
86
117
|
return handleError(error);
|
|
@@ -88,8 +119,9 @@ export class ConnectClient {
|
|
|
88
119
|
};
|
|
89
120
|
fetchRoom = async (roomId) => {
|
|
90
121
|
try {
|
|
91
|
-
const response = await this.
|
|
92
|
-
|
|
122
|
+
const response = await this._fetch(`/rooms/${roomId}`);
|
|
123
|
+
const data = await response.json();
|
|
124
|
+
return defaultParser(data.data);
|
|
93
125
|
}
|
|
94
126
|
catch (error) {
|
|
95
127
|
return handleError(error);
|
|
@@ -182,7 +214,10 @@ export class ConnectClient {
|
|
|
182
214
|
}
|
|
183
215
|
const connectBaseURL = (host) => `https://${host}/api/v1`;
|
|
184
216
|
const handleError = (error) => {
|
|
185
|
-
|
|
217
|
+
// This function was originally designed for AxiosError.
|
|
218
|
+
// The custom _fetch method now throws an object with a `response` key
|
|
219
|
+
// for HTTP errors (`{ response }`), allowing this logic to remain unchanged.
|
|
220
|
+
if (error?.response) {
|
|
186
221
|
const { response } = error;
|
|
187
222
|
if (response) {
|
|
188
223
|
switch (response.status) {
|
|
@@ -27,6 +27,7 @@ export const teletypeApp = (options) => {
|
|
|
27
27
|
resizeBestFit(term, userDimensions);
|
|
28
28
|
};
|
|
29
29
|
return new Promise((resolve, reject) => {
|
|
30
|
+
let sessionCount = 0;
|
|
30
31
|
const channel = options.joinChannel({
|
|
31
32
|
channel: `teletype:${options.roomKey.roomId}`,
|
|
32
33
|
params: {
|
|
@@ -44,15 +45,33 @@ export const teletypeApp = (options) => {
|
|
|
44
45
|
cols: dimensions.cols,
|
|
45
46
|
rows: dimensions.rows,
|
|
46
47
|
cwd: options.process.cwd(),
|
|
47
|
-
// @ts-ignore
|
|
48
48
|
env: options.process.env,
|
|
49
49
|
});
|
|
50
|
+
setTimeout(() => {
|
|
51
|
+
if (options.shell.endsWith('bash')) {
|
|
52
|
+
stdout.write('Adjusting shell prompt to show streaming indicator\n');
|
|
53
|
+
term.write("export PS1='📡 [streaming] '$PS1\n");
|
|
54
|
+
}
|
|
55
|
+
if (options.shell.endsWith('zsh')) {
|
|
56
|
+
stdout.write('Adjusting shell prompt to show streaming indicator\n');
|
|
57
|
+
const zshCommand = '_streaming_prompt_precmd() { if [[ "$PROMPT" != *\'📡 [streaming] \'* ]]; then PROMPT="📡 [streaming] $PROMPT"; fi; }; precmd_functions+=(_streaming_prompt_precmd)\n';
|
|
58
|
+
term.write(zshCommand);
|
|
59
|
+
}
|
|
60
|
+
if (options.shell.endsWith('fish')) {
|
|
61
|
+
stdout.write('Adjusting shell prompt to show streaming indicator\n');
|
|
62
|
+
term.write('functions -c fish_prompt __orig_fish_prompt; ' +
|
|
63
|
+
"function fish_prompt; echo -n '📡 [streaming] '; __orig_fish_prompt; end\n");
|
|
64
|
+
}
|
|
65
|
+
}, 100); // wait for shell to be ready
|
|
50
66
|
// track own dimensions and keep it up to date
|
|
51
67
|
setInterval(reEvaluateOwnDimensions, 1000);
|
|
52
68
|
term.onData((d) => {
|
|
53
69
|
stdout.write(d);
|
|
54
|
-
|
|
55
|
-
|
|
70
|
+
if (sessionCount < 2) {
|
|
71
|
+
// 1 sub for own channel session
|
|
72
|
+
// < 2 means no subscribers. no point pushing data.
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
56
75
|
channel.push('new_msg', {
|
|
57
76
|
t: MessageType.OUT,
|
|
58
77
|
b: true,
|
|
@@ -102,8 +121,11 @@ export const teletypeApp = (options) => {
|
|
|
102
121
|
}
|
|
103
122
|
}
|
|
104
123
|
},
|
|
105
|
-
handleSessionJoin: (s) => {
|
|
124
|
+
handleSessionJoin: (s) => {
|
|
125
|
+
sessionCount++;
|
|
126
|
+
},
|
|
106
127
|
handleSessionLeave: (s) => {
|
|
128
|
+
sessionCount -= 1;
|
|
107
129
|
s && delete userDimensions[s];
|
|
108
130
|
resizeBestFit(term, userDimensions);
|
|
109
131
|
},
|
package/oclif.manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "oorja",
|
|
3
3
|
"description": "stream terminals to the web and more.",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.1.1",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"teletype",
|
|
7
7
|
"terminal",
|
|
@@ -45,34 +45,33 @@
|
|
|
45
45
|
]
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@msgpack/msgpack": "
|
|
49
|
-
"@oclif/core": "^4.
|
|
50
|
-
"@oclif/plugin-help": "^6.2.
|
|
51
|
-
"axios": "^1.7.9",
|
|
48
|
+
"@msgpack/msgpack": "2.8.0",
|
|
49
|
+
"@oclif/core": "^4.4.0",
|
|
50
|
+
"@oclif/plugin-help": "^6.2.29",
|
|
52
51
|
"camelcase-keys": "^9.1.3",
|
|
53
52
|
"chalk": "^5.4.1",
|
|
54
53
|
"conf-cli": "0.1.9",
|
|
55
|
-
"haversine-distance": "^1.2.
|
|
56
|
-
"inquirer": "^12.
|
|
54
|
+
"haversine-distance": "^1.2.4",
|
|
55
|
+
"inquirer": "^12.6.3",
|
|
57
56
|
"node-pty": "^1.0.0",
|
|
58
57
|
"ora": "^8.2.0",
|
|
59
|
-
"phoenix": "1.7.
|
|
58
|
+
"phoenix": "1.7.21",
|
|
60
59
|
"terminal-size": "^4.0.0"
|
|
61
60
|
},
|
|
62
61
|
"devDependencies": {
|
|
63
62
|
"@oclif/prettier-config": "^0.2.1",
|
|
64
|
-
"@types/inquirer": "^9.0.
|
|
63
|
+
"@types/inquirer": "^9.0.8",
|
|
65
64
|
"@types/node": "^22.10.2",
|
|
66
65
|
"@types/phoenix": "^1.6.6",
|
|
67
|
-
"eslint": "^9.
|
|
68
|
-
"eslint-config-oclif": "^
|
|
69
|
-
"eslint-config-oclif-typescript": "^3.1.
|
|
66
|
+
"eslint": "^9.29.0",
|
|
67
|
+
"eslint-config-oclif": "^6.0.72",
|
|
68
|
+
"eslint-config-oclif-typescript": "^3.1.14",
|
|
70
69
|
"eslint-config-prettier": "^9.1.0",
|
|
71
|
-
"oclif": "^4.
|
|
72
|
-
"prettier": "^3.
|
|
73
|
-
"shx": "^0.
|
|
70
|
+
"oclif": "^4.19.0",
|
|
71
|
+
"prettier": "^3.5.3",
|
|
72
|
+
"shx": "^0.4.0",
|
|
74
73
|
"ts-node": "^10.9.2",
|
|
75
|
-
"typescript": "^5.
|
|
74
|
+
"typescript": "^5.8.3"
|
|
76
75
|
},
|
|
77
76
|
"engines": {
|
|
78
77
|
"node": ">=22.10.0"
|