|
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, |
|