|
1 | 1 | "use strict";
|
2 |
| -importaxios,{isAxiosError}from"axios"; |
3 |
| -import{getErrorMessage}from"coder/site/src/api/errors"; |
4 | 2 | import*asmodulefrom"module";
|
5 | 3 | import*asvscodefrom"vscode";
|
6 | 4 | import{makeCoderSdk,needToken}from"./api";
|
7 |
| -import{errToStr}from"./api-helper"; |
8 | 5 | import{Commands}from"./commands";
|
9 |
| -import{getErrorDetail}from"./error"; |
| 6 | +import{ExtensionDependencies}from"./extension/dependencies"; |
| 7 | +import{ExtensionInitializer}from"./extension/initializer"; |
10 | 8 | import{Logger}from"./logger";
|
11 |
| -import{Remote}from"./remote"; |
12 | 9 | import{Storage}from"./storage";
|
13 |
| -import{DefaultUIProvider}from"./uiProvider"; |
14 | 10 | import{toSafeHost}from"./util";
|
15 | 11 | import{WorkspaceQuery,WorkspaceProvider}from"./workspacesProvider";
|
16 | 12 |
|
17 |
| -classExtensionDependencies{ |
18 |
| -publicreadonlyvscodeProposed:typeofvscode; |
19 |
| -publicreadonlyremoteSSHExtension:vscode.Extension<unknown>|undefined; |
20 |
| -publicreadonlyoutput:vscode.OutputChannel; |
21 |
| -publicreadonlystorage:Storage; |
22 |
| -publicreadonlylogger:Logger; |
23 |
| -publicreadonlyrestClient:ReturnType<typeofmakeCoderSdk>; |
24 |
| -publicreadonlyuiProvider:DefaultUIProvider; |
25 |
| -publicreadonlycommands:Commands; |
26 |
| -publicreadonlymyWorkspacesProvider:WorkspaceProvider; |
27 |
| -publicreadonlyallWorkspacesProvider:WorkspaceProvider; |
28 |
| - |
29 |
| -privateconstructor( |
30 |
| -vscodeProposed:typeofvscode, |
31 |
| -remoteSSHExtension:vscode.Extension<unknown>|undefined, |
32 |
| -output:vscode.OutputChannel, |
33 |
| -storage:Storage, |
34 |
| -logger:Logger, |
35 |
| -restClient:ReturnType<typeofmakeCoderSdk>, |
36 |
| -uiProvider:DefaultUIProvider, |
37 |
| -commands:Commands, |
38 |
| -myWorkspacesProvider:WorkspaceProvider, |
39 |
| -allWorkspacesProvider:WorkspaceProvider, |
40 |
| -){ |
41 |
| -this.vscodeProposed=vscodeProposed; |
42 |
| -this.remoteSSHExtension=remoteSSHExtension; |
43 |
| -this.output=output; |
44 |
| -this.storage=storage; |
45 |
| -this.logger=logger; |
46 |
| -this.restClient=restClient; |
47 |
| -this.uiProvider=uiProvider; |
48 |
| -this.commands=commands; |
49 |
| -this.myWorkspacesProvider=myWorkspacesProvider; |
50 |
| -this.allWorkspacesProvider=allWorkspacesProvider; |
51 |
| -} |
52 |
| - |
53 |
| -staticasynccreate( |
54 |
| -ctx:vscode.ExtensionContext, |
55 |
| -):Promise<ExtensionDependencies>{ |
56 |
| -// Setup remote SSH extension |
57 |
| -const{ vscodeProposed, remoteSSHExtension}=setupRemoteSSHExtension(); |
58 |
| - |
59 |
| -// Create output channel |
60 |
| -constoutput=vscode.window.createOutputChannel("Coder"); |
61 |
| - |
62 |
| -// Initialize infrastructure |
63 |
| -const{ storage, logger}=awaitinitializeInfrastructure(ctx,output); |
64 |
| - |
65 |
| -// Initialize REST client |
66 |
| -constrestClient=awaitinitializeRestClient(storage); |
67 |
| - |
68 |
| -// Setup tree views |
69 |
| -const{ myWorkspacesProvider, allWorkspacesProvider}=setupTreeViews( |
70 |
| -restClient, |
71 |
| -storage, |
72 |
| -); |
73 |
| - |
74 |
| -// Create UI provider and commands |
75 |
| -constuiProvider=newDefaultUIProvider(vscodeProposed.window); |
76 |
| -constcommands=newCommands( |
77 |
| -vscodeProposed, |
78 |
| -restClient, |
79 |
| -storage, |
80 |
| -uiProvider, |
81 |
| -); |
82 |
| - |
83 |
| -returnnewExtensionDependencies( |
84 |
| -vscodeProposed, |
85 |
| -remoteSSHExtension, |
86 |
| -output, |
87 |
| -storage, |
88 |
| -logger, |
89 |
| -restClient, |
90 |
| -uiProvider, |
91 |
| -commands, |
92 |
| -myWorkspacesProvider, |
93 |
| -allWorkspacesProvider, |
94 |
| -); |
95 |
| -} |
96 |
| -} |
97 |
| - |
98 | 13 | exportfunctionsetupRemoteSSHExtension():{
|
99 | 14 | vscodeProposed:typeofvscode;
|
100 | 15 | remoteSSHExtension:vscode.Extension<unknown>|undefined;
|
@@ -367,153 +282,6 @@ export function registerCommands(
|
367 | 282 | );
|
368 | 283 | }
|
369 | 284 |
|
370 |
| -classRemoteEnvironmentHandler{ |
371 |
| -privatereadonlyvscodeProposed:typeofvscode; |
372 |
| -privatereadonlyremoteSSHExtension:vscode.Extension<unknown>|undefined; |
373 |
| -privatereadonlyrestClient:ReturnType<typeofmakeCoderSdk>; |
374 |
| -privatereadonlystorage:Storage; |
375 |
| -privatereadonlycommands:Commands; |
376 |
| -privatereadonlyextensionMode:vscode.ExtensionMode; |
377 |
| - |
378 |
| -constructor( |
379 |
| -deps:ExtensionDependencies, |
380 |
| -extensionMode:vscode.ExtensionMode, |
381 |
| -){ |
382 |
| -this.vscodeProposed=deps.vscodeProposed; |
383 |
| -this.remoteSSHExtension=deps.remoteSSHExtension; |
384 |
| -this.restClient=deps.restClient; |
385 |
| -this.storage=deps.storage; |
386 |
| -this.commands=deps.commands; |
387 |
| -this.extensionMode=extensionMode; |
388 |
| -} |
389 |
| - |
390 |
| -asyncinitialize():Promise<boolean>{ |
391 |
| -// Skip if no remote SSH extension or no remote authority |
392 |
| -if(!this.remoteSSHExtension||!this.vscodeProposed.env.remoteAuthority){ |
393 |
| -returntrue;// No remote environment to handle |
394 |
| -} |
395 |
| - |
396 |
| -constremote=newRemote( |
397 |
| -this.vscodeProposed, |
398 |
| -this.storage, |
399 |
| -this.commands, |
400 |
| -this.extensionMode, |
401 |
| -); |
402 |
| - |
403 |
| -try{ |
404 |
| -constdetails=awaitremote.setup( |
405 |
| -this.vscodeProposed.env.remoteAuthority, |
406 |
| -); |
407 |
| -if(details){ |
408 |
| -// Authenticate the plugin client |
409 |
| -this.restClient.setHost(details.url); |
410 |
| -this.restClient.setSessionToken(details.token); |
411 |
| -} |
412 |
| -returntrue;// Success |
413 |
| -}catch(ex){ |
414 |
| -awaitthis.handleRemoteError(ex); |
415 |
| -// Always close remote session when we fail to open a workspace |
416 |
| -awaitremote.closeRemote(); |
417 |
| -returnfalse;// Failed |
418 |
| -} |
419 |
| -} |
420 |
| - |
421 |
| -privateasynchandleRemoteError(error:unknown):Promise<void>{ |
422 |
| -if( |
423 |
| -error&& |
424 |
| -typeoferror==="object"&& |
425 |
| -"x509Err"inerror&& |
426 |
| -"showModal"inerror |
427 |
| -){ |
428 |
| -constcertError=erroras{ |
429 |
| -x509Err?:string; |
430 |
| -message?:string; |
431 |
| -showModal:(title:string)=>Promise<void>; |
432 |
| -}; |
433 |
| -this.storage.writeToCoderOutputChannel( |
434 |
| -certError.x509Err||certError.message||"Certificate error", |
435 |
| -); |
436 |
| -awaitcertError.showModal("Failed to open workspace"); |
437 |
| -}elseif(isAxiosError(error)){ |
438 |
| -constmsg=getErrorMessage(error,"None"); |
439 |
| -constdetail=getErrorDetail(error)||"None"; |
440 |
| -consturlString=axios.getUri(error.config); |
441 |
| -constmethod=error.config?.method?.toUpperCase()||"request"; |
442 |
| -conststatus=error.response?.status||"None"; |
443 |
| -constmessage=`API${method} to '${urlString}' failed.\nStatus code:${status}\nMessage:${msg}\nDetail:${detail}`; |
444 |
| -this.storage.writeToCoderOutputChannel(message); |
445 |
| -awaitthis.vscodeProposed.window.showErrorMessage( |
446 |
| -"Failed to open workspace", |
447 |
| -{ |
448 |
| -detail:message, |
449 |
| -modal:true, |
450 |
| -useCustom:true, |
451 |
| -}, |
452 |
| -); |
453 |
| -}else{ |
454 |
| -constmessage=errToStr(error,"No error message was provided"); |
455 |
| -this.storage.writeToCoderOutputChannel(message); |
456 |
| -awaitthis.vscodeProposed.window.showErrorMessage( |
457 |
| -"Failed to open workspace", |
458 |
| -{ |
459 |
| -detail:message, |
460 |
| -modal:true, |
461 |
| -useCustom:true, |
462 |
| -}, |
463 |
| -); |
464 |
| -} |
465 |
| -} |
466 |
| -} |
467 |
| - |
468 |
| -classExtensionInitializer{ |
469 |
| -privatereadonlydeps:ExtensionDependencies; |
470 |
| -privatereadonlyctx:vscode.ExtensionContext; |
471 |
| - |
472 |
| -constructor(deps:ExtensionDependencies,ctx:vscode.ExtensionContext){ |
473 |
| -this.deps=deps; |
474 |
| -this.ctx=ctx; |
475 |
| -} |
476 |
| - |
477 |
| -asyncinitialize():Promise<void>{ |
478 |
| -// Register URI handler and commands |
479 |
| -this.registerHandlers(); |
480 |
| - |
481 |
| -// Handle remote environment if applicable |
482 |
| -constremoteHandler=newRemoteEnvironmentHandler( |
483 |
| -this.deps, |
484 |
| -this.ctx.extensionMode, |
485 |
| -); |
486 |
| -constremoteHandled=awaitremoteHandler.initialize(); |
487 |
| -if(!remoteHandled){ |
488 |
| -return;// Exit early if remote setup failed |
489 |
| -} |
490 |
| - |
491 |
| -// Initialize authentication |
492 |
| -awaitinitializeAuthentication( |
493 |
| -this.deps.restClient, |
494 |
| -this.deps.storage, |
495 |
| -this.deps.myWorkspacesProvider, |
496 |
| -this.deps.allWorkspacesProvider, |
497 |
| -); |
498 |
| -} |
499 |
| - |
500 |
| -privateregisterHandlers():void{ |
501 |
| -// Register URI handler |
502 |
| -registerUriHandler( |
503 |
| -this.deps.commands, |
504 |
| -this.deps.restClient, |
505 |
| -this.deps.storage, |
506 |
| -); |
507 |
| - |
508 |
| -// Register commands |
509 |
| -registerCommands( |
510 |
| -this.deps.commands, |
511 |
| -this.deps.myWorkspacesProvider, |
512 |
| -this.deps.allWorkspacesProvider, |
513 |
| -); |
514 |
| -} |
515 |
| -} |
516 |
| - |
517 | 285 | exportasyncfunctioninitializeAuthentication(
|
518 | 286 | restClient:ReturnType<typeofmakeCoderSdk>,
|
519 | 287 | storage:Storage,
|
|