diff --git a/package.json b/package.json index 928b32ec..52a359c6 100644 --- a/package.json +++ b/package.json @@ -1289,7 +1289,11 @@ "type": "string" }, "internalPort": { - "description": "Target port inside the service in docker-compose.", + "description": "Target webserver port inside the service in docker-compose.", + "type": "number" + }, + "internalSuperserverPort": { + "description": "Target superserver port inside the service in docker-compose.", "type": "number" }, "file": { diff --git a/src/api/index.ts b/src/api/index.ts index 38983986..d2e70dc2 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -30,6 +30,7 @@ interface ConnectionSettings { https: boolean; host: string; port: number; + superserverPort?: number; pathPrefix: string; ns: string; username: string; @@ -67,6 +68,9 @@ export class AtelierAPI { const wsKey = this.configName.toLowerCase(); const host = this.externalServer ? this._config.host : workspaceState.get(wsKey + ":host", this._config.host); const port = this.externalServer ? this._config.port : workspaceState.get(wsKey + ":port", this._config.port); + const superserverPort = this.externalServer + ? this._config.superserverPort + : workspaceState.get(wsKey + ":superserverPort", this._config.superserverPort); const password = workspaceState.get(wsKey + ":password", this._config.password); const apiVersion = workspaceState.get(wsKey + ":apiVersion", DEFAULT_API_VERSION); const serverVersion = workspaceState.get(wsKey + ":serverVersion", DEFAULT_SERVER_VERSION); @@ -80,6 +84,7 @@ export class AtelierAPI { https, host, port, + superserverPort, pathPrefix, ns, username, @@ -211,6 +216,7 @@ export class AtelierAPI { webServer: { scheme, host, port, pathPrefix = "" }, username, password, + superServer, } = getResolvedConnectionSpec(serverName, config("intersystems.servers", workspaceFolderName).get(serverName)); this._config = { serverName, @@ -221,6 +227,7 @@ export class AtelierAPI { ns, host, port, + superserverPort: superServer.port, username, password, pathPrefix, @@ -241,6 +248,7 @@ export class AtelierAPI { webServer: { scheme, host, port, pathPrefix = "" }, username, password, + superServer, } = resolvedSpec; this._config = { serverName: "", @@ -251,6 +259,7 @@ export class AtelierAPI { ns, host, port, + superserverPort: superServer.port, username, password, pathPrefix, diff --git a/src/extension.ts b/src/extension.ts index 271392e7..d4240aa0 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -250,6 +250,9 @@ export async function resolveConnectionSpec(serverName: string, uri?: vscode.Uri port: serverForUri.port, pathPrefix: serverForUri.pathPrefix, }, + superServer: { + port: serverForUri.superserverPort, + }, username: serverForUri.username, password: serverForUri.password ? serverForUri.password : undefined, description: `Server for workspace folder '${serverName}'`, @@ -330,6 +333,7 @@ export async function checkConnection( /// clean-up cached values await workspaceState.update(wsKey + ":host", undefined); await workspaceState.update(wsKey + ":port", undefined); + await workspaceState.update(wsKey + ":superserverPort", undefined); await workspaceState.update(wsKey + ":password", undefined); await workspaceState.update(wsKey + ":apiVersion", undefined); await workspaceState.update(wsKey + ":serverVersion", undefined); @@ -337,7 +341,7 @@ export async function checkConnection( _onDidChangeConnection.fire(); } let api = new AtelierAPI(apiTarget, false); - const { active, host = "", port = 0, username, ns = "" } = api.config; + const { active, host = "", port = 0, superserverPort = 0, username, ns = "" } = api.config; vscode.commands.executeCommand("setContext", "vscode-objectscript.connectActive", active); if (!panel.text) { panel.text = `${PANEL_LABEL}`; @@ -360,11 +364,16 @@ export async function checkConnection( if (!workspaceState.get(wsKey + ":port") && !api.externalServer) { try { - const { port: dockerPort, docker: withDocker, service } = await portFromDockerCompose(); + const { + port: dockerPort, + superserverPort: dockerSuperserverPort, + docker: withDocker, + service, + } = await portFromDockerCompose(configName); workspaceState.update(wsKey + ":docker", withDocker); workspaceState.update(wsKey + ":dockerService", service); if (withDocker) { - if (!dockerPort) { + if (!dockerPort || !dockerSuperserverPort) { const errorMessage = `Something is wrong with your docker-compose connection settings, or your service is not running.`; handleError(errorMessage); panel.text = `${PANEL_LABEL} $(error)`; @@ -377,6 +386,9 @@ export async function checkConnection( workspaceState.update(wsKey + ":host", "localhost"); workspaceState.update(wsKey + ":port", dockerPort); } + if (dockerSuperserverPort !== superserverPort) { + workspaceState.update(wsKey + ":superserverPort", dockerSuperserverPort); + } connInfo = `localhost:${dockerPort}[${ns}]`; _onDidChangeConnection.fire(); } @@ -1627,6 +1639,7 @@ function serverForUri(uri: vscode.Uri): any { host = "", https, port, + superserverPort, pathPrefix, username, password, @@ -1640,6 +1653,7 @@ function serverForUri(uri: vscode.Uri): any { scheme: https ? "https" : "http", host, port, + superserverPort, pathPrefix, username, password: @@ -1661,9 +1675,14 @@ async function asyncServerForUri(uri: vscode.Uri): Promise { if (apiTarget instanceof vscode.Uri) { apiTarget = vscode.workspace.getWorkspaceFolder(apiTarget)?.name; } - const { port: dockerPort, docker: withDocker } = await portFromDockerCompose(apiTarget); - if (withDocker && dockerPort) { + const { + port: dockerPort, + superserverPort: dockerSuperserverPort, + docker: withDocker, + } = await portFromDockerCompose(apiTarget); + if (withDocker && dockerPort && dockerSuperserverPort) { server.port = dockerPort; + server.superserverPort = dockerSuperserverPort; server.host = "localhost"; server.pathPrefix = ""; server.https = false; diff --git a/src/utils/index.ts b/src/utils/index.ts index e4c89c27..fee65004 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -490,24 +490,30 @@ async function composeCommand(cwd?: string): Promise { export async function portFromDockerCompose( workspaceFolderName?: string -): Promise<{ port: number; docker: boolean; service?: string }> { +): Promise<{ port: number; superserverPort: number; docker: boolean; service?: string }> { // When running remotely, behave as if there is no docker-compose object within objectscript.conn if (extensionContext.extension.extensionKind === vscode.ExtensionKind.Workspace) { - return { docker: false, port: null }; + return { docker: false, port: null, superserverPort: null }; } // Seek a valid docker-compose object within objectscript.conn const { "docker-compose": dockerCompose = {} } = config("conn", workspaceFolderName); - const { service, file = "docker-compose.yml", internalPort = 52773, envFile } = dockerCompose; - if (!internalPort || !file || !service || service === "") { - return { docker: false, port: null }; - } - - const result = { port: null, docker: true, service }; + const { + service, + file = "docker-compose.yml", + internalPort = 52773, + internalSuperserverPort = 1972, + envFile, + } = dockerCompose; + if (!internalPort || !internalSuperserverPort || !file || !service || service === "") { + return { docker: false, port: null, superserverPort: null }; + } + + const result = { port: null, superserverPort: null, docker: true, service }; const workspaceFolder = uriOfWorkspaceFolder(workspaceFolderName); if (!workspaceFolder) { // No workspace folders are open - return { docker: false, port: null }; + return { docker: false, port: null, superserverPort: null }; } const workspaceFolderPath = workspaceFolder.fsPath; const workspaceRootPath = vscode.workspace.workspaceFolders[0].uri.fsPath; @@ -548,9 +554,23 @@ export async function portFromDockerCompose( } const [, port] = stdout.match(/:(\d+)/) || []; if (!port) { - reject(`Port ${internalPort} not published for service '${service}' in '${path.join(cwd, file)}'.`); + reject(`Webserver port ${internalPort} not published for service '${service}' in '${path.join(cwd, file)}'.`); } - resolve({ port: parseInt(port, 10), docker: true, service }); + result.port = parseInt(port, 10); + + exec(`${cmd} port --protocol=tcp ${service} ${internalSuperserverPort}`, { cwd }, (error, stdout) => { + if (error) { + reject(error.message); + } + const [, superserverPort] = stdout.match(/:(\d+)/) || []; + if (!superserverPort) { + reject( + `Superserver port ${internalSuperserverPort} not published for service '${service}' in '${path.join(cwd, file)}'.` + ); + } + result.superserverPort = parseInt(superserverPort, 10); + resolve(result); + }); }); }); });