@@ -2,8 +2,9 @@ import * as vscode from "vscode";
22import { getServerNames } from "../api/getServerNames" ;
33import { getServerSpec } from "../api/getServerSpec" ;
44import { getServerSummary } from "../api/getServerSummary" ;
5- import { IServerName } from "@intersystems-community/intersystems-servermanager" ;
5+ import { IServerName , IServerSpec } from "@intersystems-community/intersystems-servermanager" ;
66import { makeRESTRequest } from "../makeRESTRequest" ;
7+ import { OBJECTSCRIPT_EXTENSIONID } from "../extension" ;
78
89const SETTINGS_VERSION = "v1" ;
910
@@ -271,10 +272,12 @@ function allServers(treeItem: SMTreeItem, params?: any): ServerTreeItem[] {
271272 return children ;
272273}
273274
274- function currentServers ( element : SMTreeItem , params ?: any ) : ServerTreeItem [ ] {
275+ async function currentServers ( element : SMTreeItem , params ?: any ) : Promise < ServerTreeItem [ ] > {
275276 const children = new Map < string , ServerTreeItem > ( ) ;
277+ const dockerLocalPorts = new Map < number , string > ( ) ;
276278
277- vscode . workspace . workspaceFolders ?. map ( ( folder ) => {
279+ const workspaceFolders = vscode . workspace . workspaceFolders || [ ] ;
280+ await Promise . all ( workspaceFolders . map ( async ( folder ) => {
278281 const serverName = folder . uri . authority . split ( ":" ) [ 0 ] ;
279282 if ( [ "isfs" , "isfs-readonly" ] . includes ( folder . uri . scheme ) ) {
280283 const serverSummary = getServerSummary ( serverName ) ;
@@ -284,10 +287,25 @@ function currentServers(element: SMTreeItem, params?: any): ServerTreeItem[] {
284287 new ServerTreeItem ( { parent : element , label : serverName , id : serverName } , serverSummary ) ,
285288 ) ;
286289 }
290+ return ;
287291 }
288292 const conn = vscode . workspace . getConfiguration ( "objectscript.conn" , folder ) ;
289293 const connServer = conn . get < string > ( "server" ) ;
290- if ( connServer ) {
294+ if ( conn . get ( "docker-compose" ) ) {
295+ const objectScriptExtension = vscode . extensions . getExtension ( OBJECTSCRIPT_EXTENSIONID ) ;
296+ if ( objectScriptExtension ) {
297+ if ( ! objectScriptExtension . isActive ) {
298+ await objectScriptExtension . activate ( ) ;
299+ }
300+ if ( objectScriptExtension . isActive && objectScriptExtension . exports ?. asyncServerForUri ) {
301+ const server = await objectScriptExtension . exports . asyncServerForUri ( folder . uri ) ;
302+ if ( server && server . host === "localhost" && server . port > 0 && ! dockerLocalPorts . has ( server . port ) ) {
303+ dockerLocalPorts . set ( server . port , folder . name ) ;
304+ }
305+ }
306+ }
307+ }
308+ else if ( connServer ) {
291309 const serverSummary = getServerSummary ( connServer ) ;
292310 if ( serverSummary ) {
293311 children . set (
@@ -296,7 +314,18 @@ function currentServers(element: SMTreeItem, params?: any): ServerTreeItem[] {
296314 ) ;
297315 }
298316 }
299- } ) ;
317+
318+ } ) ) ;
319+
320+ dockerLocalPorts . forEach ( ( name , port ) => {
321+ if ( ! children . has ( name ) ) {
322+ const serverSummary : IServerName = { name, description : `Docker service bound to local port ${ port } for folder '${ name } '` , detail : `http://localhost:${ port } /` } ;
323+ children . set (
324+ name ,
325+ new ServerTreeItem ( { parent : element , label : `docker:${ port } ` , id : name } , serverSummary ) ,
326+ ) ;
327+ }
328+ } )
300329
301330 return Array . from ( children . values ( ) ) . sort ( ( a , b ) => a . name < b . name ? - 1 : a . name > b . name ? 1 : 0 ) ;
302331}
@@ -347,7 +376,7 @@ export class ServerTreeItem extends SMTreeItem {
347376 super ( {
348377 getChildren : serverFeatures ,
349378 id : parentFolderId + ":" + serverSummary . name ,
350- label : serverSummary . name ,
379+ label : element . label ? element . label : serverSummary . name ,
351380 params : { serverSummary } ,
352381 parent : element . parent ,
353382 tooltip : new vscode . MarkdownString ( wrappedDetail ) . appendMarkdown ( escapedDescription ? `\n\n*${ escapedDescription } *` : "" ) ,
@@ -377,12 +406,12 @@ async function serverFeatures(element: ServerTreeItem, params?: any): Promise<Fe
377406 const children : FeatureTreeItem [ ] = [ ] ;
378407
379408 if ( params ?. serverSummary ) {
380- const name = params . serverSummary . name ;
381- const serverSpec = await getServerSpec ( name ) ;
409+ let serverSpec = await specFromServerSummary ( params . serverSummary ) ;
382410 if ( ! serverSpec ) {
383411 return undefined ;
384412 }
385413
414+ const name = serverSpec . name ;
386415 let response = await makeRESTRequest ( "HEAD" , serverSpec ) ;
387416 if ( response ?. status === 401 ) {
388417 // Authentication error, so retry in case first attempt cleared a no-longer-valid stored password
@@ -392,12 +421,21 @@ async function serverFeatures(element: ServerTreeItem, params?: any): Promise<Fe
392421 if ( response ?. status !== 200 ) {
393422 children . push ( new OfflineTreeItem ( { parent : element , label : name , id : name } , serverSpec . username || 'UnknownUser' ) ) ;
394423 } else {
395- children . push ( new NamespacesTreeItem ( { parent : element , label : name , id : name } , element . name , serverSpec . username || 'UnknownUser' ) ) ;
424+ children . push ( new NamespacesTreeItem ( { parent : element , label : name , id : name } , element . name , serverSpec , serverSpec . username || 'UnknownUser' ) ) ;
396425 }
397426 }
398427 return children ;
399428}
400429
430+ async function specFromServerSummary ( serverSummary : IServerName ) : Promise < IServerSpec | undefined > {
431+ const { name, description, detail } = serverSummary ;
432+ const dockerDetail = detail . match ( / ^ h t t p : \/ \/ l o c a l h o s t : ( \d + ) \/ $ / ) ;
433+ if ( dockerDetail ) {
434+ return { name, description, webServer : { scheme : "http" , host : "127.0.0.1" , port : parseInt ( dockerDetail [ 1 ] , 10 ) , pathPrefix : "" } } ;
435+ }
436+ return getServerSpec ( name ) ;
437+ }
438+
401439// tslint:disable-next-line: max-classes-per-file
402440export class FeatureTreeItem extends SMTreeItem {
403441}
@@ -428,14 +466,15 @@ export class NamespacesTreeItem extends FeatureTreeItem {
428466 constructor (
429467 element : ISMItem ,
430468 serverName : string ,
469+ serverSpec : IServerSpec ,
431470 username : string
432471 ) {
433472 const parentFolderId = element . parent ?. id || "" ;
434473 super ( {
435474 getChildren : serverNamespaces ,
436475 id : parentFolderId + ":namespaces" ,
437476 label : "Namespaces" ,
438- params : { serverName } ,
477+ params : { serverName, serverSpec } ,
439478 parent : element . parent ,
440479 tooltip : `Namespaces '${ username } ' can access` ,
441480 } ) ;
@@ -457,7 +496,7 @@ async function serverNamespaces(element: ServerTreeItem, params?: any): Promise<
457496
458497 if ( params ?. serverName ) {
459498 const name : string = params . serverName ;
460- const serverSpec = await getServerSpec ( name ) ;
499+ const serverSpec : IServerSpec | undefined = params . serverSpec ;
461500 if ( ! serverSpec ) {
462501 return undefined ;
463502 }
@@ -468,7 +507,7 @@ async function serverNamespaces(element: ServerTreeItem, params?: any): Promise<
468507 } else {
469508 const serverApiVersion = response . data . result . content . api ;
470509 response . data . result . content . namespaces . map ( ( namespace : string ) => {
471- children . push ( new NamespaceTreeItem ( { parent : element , label : name , id : name } , namespace , name , serverApiVersion ) ) ;
510+ children . push ( new NamespaceTreeItem ( { parent : element , label : name , id : name } , namespace , name , serverSpec , serverApiVersion ) ) ;
472511 } ) ;
473512 }
474513 }
@@ -483,6 +522,7 @@ export class NamespaceTreeItem extends SMTreeItem {
483522 element : ISMItem ,
484523 name : string ,
485524 serverName : string ,
525+ serverSpec : IServerSpec ,
486526 serverApiVersion : number
487527 ) {
488528 const parentFolderId = element . parent ?. id || "" ;
@@ -493,7 +533,7 @@ export class NamespaceTreeItem extends SMTreeItem {
493533 parent : element . parent ,
494534 tooltip : `${ name } on ${ serverName } ` ,
495535 getChildren : namespaceFeatures ,
496- params : { serverName, serverApiVersion }
536+ params : { serverName, serverSpec , serverApiVersion }
497537 } ) ;
498538 this . name = name ;
499539 this . contextValue = `${ serverApiVersion . toString ( ) } /${ name === "%SYS" ? "sysnamespace" : "namespace" } ` ;
@@ -510,8 +550,8 @@ export class NamespaceTreeItem extends SMTreeItem {
510550 */
511551async function namespaceFeatures ( element : NamespaceTreeItem , params ?: any ) : Promise < FeatureTreeItem [ ] | undefined > {
512552 return [
513- new ProjectsTreeItem ( { parent : element , id : element . name , label : element . name } , params . serverName , params . serverApiVersion ) ,
514- new WebAppsTreeItem ( { parent : element , id : element . name , label : element . name } , params . serverName , params . serverApiVersion )
553+ new ProjectsTreeItem ( { parent : element , id : element . name , label : element . name } , params . serverName , params . serverSpec , params . serverApiVersion ) ,
554+ new WebAppsTreeItem ( { parent : element , id : element . name , label : element . name } , params . serverName , params . serverSpec , params . serverApiVersion )
515555 ] ;
516556}
517557
@@ -520,6 +560,7 @@ export class ProjectsTreeItem extends FeatureTreeItem {
520560 constructor (
521561 element : ISMItem ,
522562 serverName : string ,
563+ serverSpec : IServerSpec ,
523564 serverApiVersion : number
524565 ) {
525566 const parentFolderId = element . parent ?. id || '' ;
@@ -529,7 +570,7 @@ export class ProjectsTreeItem extends FeatureTreeItem {
529570 id : parentFolderId + ':projects' ,
530571 tooltip : `Projects in this namespace` ,
531572 getChildren : namespaceProjects ,
532- params : { serverName, serverApiVersion, ns : element . label }
573+ params : { serverName, serverSpec , serverApiVersion, ns : element . label }
533574 } ) ;
534575 this . name = 'Projects' ;
535576 this . contextValue = serverApiVersion . toString ( ) + '/projects' ;
@@ -549,7 +590,7 @@ async function namespaceProjects(element: ProjectsTreeItem, params?: any): Promi
549590
550591 if ( params ?. serverName && params . ns ) {
551592 const name : string = params . serverName ;
552- const serverSpec = await getServerSpec ( name )
593+ const serverSpec : IServerSpec | undefined = params . serverSpec ;
553594 if ( ! serverSpec ) {
554595 return undefined
555596 }
@@ -607,6 +648,7 @@ export class WebAppsTreeItem extends FeatureTreeItem {
607648 constructor (
608649 element : ISMItem ,
609650 serverName : string ,
651+ serverSpec : IServerSpec ,
610652 serverApiVersion : number
611653 ) {
612654 const parentFolderId = element . parent ?. id || '' ;
@@ -616,7 +658,7 @@ export class WebAppsTreeItem extends FeatureTreeItem {
616658 id : parentFolderId + ':webapps' ,
617659 tooltip : `Web Applications in this namespace` ,
618660 getChildren : namespaceWebApps ,
619- params : { serverName, serverApiVersion, ns : element . label }
661+ params : { serverName, serverSpec , serverApiVersion, ns : element . label }
620662 } ) ;
621663 this . name = 'Web Applications' ;
622664 this . contextValue = serverApiVersion . toString ( ) + '/webapps' ;
@@ -636,7 +678,7 @@ async function namespaceWebApps(element: ProjectsTreeItem, params?: any): Promis
636678
637679 if ( params ?. serverName && params . ns ) {
638680 const name : string = params . serverName ;
639- const serverSpec = await getServerSpec ( name )
681+ const serverSpec : IServerSpec | undefined = params . serverSpec ;
640682 if ( ! serverSpec ) {
641683 return undefined
642684 }
0 commit comments