1
- import { ReadWriteConnection } from "../common/connection" ;
2
- import { NewEvalMessage , ServerMessage , EvalDoneMessage , EvalFailedMessage , TypedValue , ClientMessage , NewSessionMessage , TTYDimensions , SessionOutputMessage , CloseSessionInputMessage } from "../proto" ;
3
- import { Emitter } from "@coder/events" ;
1
+ import { ReadWriteConnection , InitData , OperatingSystem } from "../common/connection" ;
2
+ import { NewEvalMessage , ServerMessage , EvalDoneMessage , EvalFailedMessage , TypedValue , ClientMessage , NewSessionMessage , TTYDimensions , SessionOutputMessage , CloseSessionInputMessage , InitMessage } from "../proto" ;
3
+ import { Emitter , Event } from "@coder/events" ;
4
4
import { logger , field } from "@coder/logger" ;
5
5
import { ChildProcess , SpawnOptions , ServerProcess } from "./command" ;
6
6
@@ -15,12 +15,17 @@ export class Client {
15
15
private sessionId : number = 0 ;
16
16
private sessions : Map < number , ServerProcess > = new Map ( ) ;
17
17
18
+ private _initData : InitData | undefined ;
19
+ private initDataEmitter : Emitter < InitData > = new Emitter ( ) ;
20
+
18
21
/**
19
22
* @param connection Established connection to the server
20
23
*/
21
24
public constructor (
22
25
private readonly connection : ReadWriteConnection ,
23
26
) {
27
+ this . initDataEmitter = new Emitter ( ) ;
28
+
24
29
connection . onMessage ( ( data ) => {
25
30
try {
26
31
this . handleMessage ( ServerMessage . deserializeBinary ( data ) ) ;
@@ -30,6 +35,14 @@ export class Client {
30
35
} ) ;
31
36
}
32
37
38
+ public get onInitData ( ) : Event < InitData > {
39
+ return this . initDataEmitter . event ;
40
+ }
41
+
42
+ public get initData ( ) : InitData | undefined {
43
+ return this . _initData ;
44
+ }
45
+
33
46
public evaluate < R > ( func : ( ) => R | Promise < R > ) : Promise < R > ;
34
47
public evaluate < R , T1 > ( func : ( a1 : T1 ) => R | Promise < R > , a1 : T1 ) : Promise < R > ;
35
48
public evaluate < R , T1 , T2 > ( func : ( a1 : T1 , a2 : T2 ) => R | Promise < R > , a1 : T1 , a2 : T2 ) : Promise < R > ;
@@ -47,7 +60,7 @@ export class Client {
47
60
* console.log(returned);
48
61
* // output: "hi"
49
62
* @param func Function to evaluate
50
- * @returns { Promise } Promise rejected or resolved from the evaluated function
63
+ * @returns Promise rejected or resolved from the evaluated function
51
64
*/
52
65
public evaluate < R , T1 , T2 , T3 , T4 , T5 , T6 > ( func : ( a1 ?: T1 , a2 ?: T2 , a3 ?: T3 , a4 ?: T4 , a5 ?: T5 , a6 ?: T6 ) => R | Promise < R > , a1 ?: T1 , a2 ?: T2 , a3 ?: T3 , a4 ?: T4 , a5 ?: T5 , a6 ?: T6 ) : Promise < R > {
53
66
const newEval = new NewEvalMessage ( ) ;
@@ -61,8 +74,8 @@ export class Client {
61
74
this . connection . send ( clientMsg . serializeBinary ( ) ) ;
62
75
63
76
let res : ( value ?: R ) => void ;
64
- let rej : ( err ?: any ) => void ;
65
- const prom = new Promise < R > ( ( r , e ) => {
77
+ let rej : ( err ?: Error ) => void ;
78
+ const prom = new Promise < R > ( ( r , e ) : void => {
66
79
res = r ;
67
80
rej = e ;
68
81
} ) ;
@@ -80,6 +93,7 @@ export class Client {
80
93
}
81
94
82
95
const rt = resp . getType ( ) ;
96
+ // tslint:disable-next-line
83
97
let val : any ;
84
98
switch ( rt ) {
85
99
case TypedValue . Type . BOOLEAN :
@@ -107,7 +121,7 @@ export class Client {
107
121
d1 . dispose ( ) ;
108
122
d2 . dispose ( ) ;
109
123
110
- rej ( failedMsg . getMessage ( ) ) ;
124
+ rej ( new Error ( failedMsg . getMessage ( ) ) ) ;
111
125
}
112
126
} ) ;
113
127
@@ -120,7 +134,6 @@ export class Client {
120
134
* const cp = this.client.spawn("echo", ["test"]);
121
135
* cp.stdout.on("data", (data) => console.log(data.toString()));
122
136
* cp.on("exit", (code) => console.log("exited with", code));
123
- * @param command
124
137
* @param args Arguments
125
138
* @param options Options to execute for the command
126
139
*/
@@ -167,14 +180,14 @@ export class Client {
167
180
168
181
const serverProc = new ServerProcess ( this . connection , id , options ? options . tty !== undefined : false ) ;
169
182
serverProc . stdin . on ( "close" , ( ) => {
170
- console . log ( "stdin closed" ) ;
171
183
const c = new CloseSessionInputMessage ( ) ;
172
184
c . setId ( id ) ;
173
185
const cm = new ClientMessage ( ) ;
174
186
cm . setCloseSessionInput ( c ) ;
175
187
this . connection . send ( cm . serializeBinary ( ) ) ;
176
188
} ) ;
177
189
this . sessions . set ( id , serverProc ) ;
190
+
178
191
return serverProc ;
179
192
}
180
193
@@ -183,7 +196,31 @@ export class Client {
183
196
* routed through here.
184
197
*/
185
198
private handleMessage ( message : ServerMessage ) : void {
186
- if ( message . hasEvalDone ( ) ) {
199
+ if ( message . hasInit ( ) ) {
200
+ const init = message . getInit ( ) ! ;
201
+ let opSys : OperatingSystem ;
202
+ switch ( init . getOperatingSystem ( ) ) {
203
+ case InitMessage . OperatingSystem . WINDOWS :
204
+ opSys = OperatingSystem . Windows ;
205
+ break ;
206
+ case InitMessage . OperatingSystem . LINUX :
207
+ opSys = OperatingSystem . Linux ;
208
+ break ;
209
+ case InitMessage . OperatingSystem . MAC :
210
+ opSys = OperatingSystem . Mac ;
211
+ break ;
212
+ default :
213
+ throw new Error ( `unsupported operating system ${ init . getOperatingSystem ( ) } ` ) ;
214
+ }
215
+ this . _initData = {
216
+ dataDirectory : init . getDataDirectory ( ) ,
217
+ homeDirectory : init . getHomeDirectory ( ) ,
218
+ tmpDirectory : init . getTmpDirectory ( ) ,
219
+ workingDirectory : init . getWorkingDirectory ( ) ,
220
+ os : opSys ,
221
+ } ;
222
+ this . initDataEmitter . emit ( this . _initData ) ;
223
+ } else if ( message . hasEvalDone ( ) ) {
187
224
this . evalDoneEmitter . emit ( message . getEvalDone ( ) ! ) ;
188
225
} else if ( message . hasEvalFailed ( ) ) {
189
226
this . evalFailedEmitter . emit ( message . getEvalFailed ( ) ! ) ;
0 commit comments