diff --git a/package.json b/package.json index 0d834efd..8872bd57 100644 --- a/package.json +++ b/package.json @@ -736,7 +736,7 @@ "moment-duration-format": "^2.3.2", "moment-timezone": "^0.5.44", "node-fetch": "^2.6.6", - "node-q": "^2.6.1", + "node-q": "^2.7.0", "pick-port": "^2.0.1", "picomatch": "^3.0.1", "semver": "^7.5.3", diff --git a/src/classes/localConnection.ts b/src/classes/localConnection.ts new file mode 100644 index 00000000..a891a90a --- /dev/null +++ b/src/classes/localConnection.ts @@ -0,0 +1,328 @@ +/* + * Copyright (c) 1998-2023 Kx Systems Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +import * as nodeq from "node-q"; +import { window } from "vscode"; +import { ext } from "../extensionVariables"; +import { delay } from "../utils/core"; +import { convertStringToArray, handleQueryResults } from "../utils/execution"; +import { queryWrapper } from "../utils/queryUtils"; +import { QueryResult, QueryResultType } from "../models/queryResult"; +import { Connection } from "node-q"; + +export class LocalConnection { + public connected: boolean; + public connLabel: string; + private options: nodeq.ConnectionParameters; + private connection?: nodeq.Connection; + private isError: boolean = false; + private result?: string; + + constructor( + connectionString: string, + connLabel: string, + creds?: string[], + tls?: boolean, + ) { + const params = connectionString.split(":"); + if (!params) { + throw new Error("Missing or invalid connection string"); + } + + const options: nodeq.ConnectionParameters = { + nanos2date: false, + socketNoDelay: true, + }; + + if (tls != undefined) { + options.useTLS = tls; + } else { + options.useTLS = false; + } + + if (params.length > 0) { + options.host = params[0]; + } + if (params.length > 1) { + options.port = +params[1]; + } + + if (creds != undefined) { + options.user = creds[0]; + options.password = creds[1]; + } + this.connLabel = connLabel; + this.options = options; + this.connected = false; + } + + public getConnection(): Connection | undefined { + return this.connection; + } + + public connect(callback: nodeq.AsyncValueCallback): void { + nodeq.connect(this.options, (err, conn) => { + if (err || !conn) { + ext.serverProvider.reload(); + + window.showErrorMessage( + `Connection to server ${this.options.host}:${this.options.port} failed! Details: ${err?.message}`, + ); + ext.outputChannel.appendLine( + `Connection to server ${this.options.host}:${this.options.port} failed! Details: ${err?.message}`, + ); + return; + } + conn.addListener("close", () => { + ext.outputChannel.appendLine( + `Connection stopped from ${this.options.host}:${this.options.port}`, + ); + this.connected = false; + }); + + if (this.connection && this.connected) { + this.connection.close(() => { + this.onConnect(err, conn, callback); + }); + } else { + this.onConnect(err, conn, callback); + } + }); + } + + public disconnect(): void { + if (this.connected) { + this.connection?.close(); + this.connected = false; + } + } + + public update(): void { + this.updateGlobal(); + this.updateReservedKeywords(); + } + + async execute(query: string): Promise { + let result; + let error; + // try 5 times, then fail + let retryCount = 0; + while (this.connection === undefined) { + if (retryCount > ext.maxRetryCount) { + return "timeout"; + } + await delay(500); + retryCount++; + } + + this.connection.k(query, function (err: Error, res: string) { + if (err) { + error = err; + result = ""; + return; + } + result = res; + }); + + // wait for result (lack of await using callbacks) + while (result === undefined || result === null) { + await delay(500); + } + + if (error) { + throw error; + } + + return result; + } + + public async executeQuery( + command: string, + context?: string, + stringify?: boolean, + ): Promise { + await this.waitForConnection(); + + if (!this.connection) { + return "timeout"; + } + const wrapper = queryWrapper(); + this.connection.k( + wrapper, + context ?? ".", + command, + !!stringify, + (err: Error, res: QueryResult) => { + if (err) { + this.isError = true; + this.result = handleQueryResults( + err.toString(), + QueryResultType.Error, + ); + } + if (res) { + this.handleQueryResult(res); + } + }, + ); + + const result = await this.waitForResult(); + + if (ext.resultsViewProvider.isVisible() && stringify) { + if (this.isError) { + this.isError = false; + return result; + } + return convertStringToArray(result); + } + + return result; + } + + public async executeQueryRaw(command: string): Promise { + let result; + let retryCount = 0; + let error; + while (this.connection === undefined) { + if (retryCount > ext.maxRetryCount) { + return "timeout"; + } + await delay(500); + retryCount++; + } + this.connection.k(command, (err: Error, res: string) => { + if (err) { + error = err; + result = ""; + return; + } + result = res; + }); + + while (result === undefined || result === null) { + await delay(500); + } + + if (error) { + throw error; + } + + return result; + } + + private async waitForConnection(): Promise { + let retryCount = 0; + while (this.connection === undefined) { + if (retryCount > ext.maxRetryCount) { + throw new Error("timeout"); + } + await delay(500); + retryCount++; + } + } + + private handleQueryResult = (res: QueryResult): void => { + if (res.errored) { + this.isError = true; + this.result = handleQueryResults( + res.error + (res.backtrace ? "\n" + res.backtrace : ""), + QueryResultType.Error, + ); + } else { + this.result = res.result; + } + }; + + private async waitForResult(): Promise { + while (this.result === undefined || this.result === null) { + await delay(500); + } + const result = this.result; + this.result = undefined; + return result; + } + + private updateGlobal() { + const globalQuery = + '{[q] t:system"T";tm:@[{$[x>0;[system"T ",string x;1b];0b]};0;{0b}];r:$[tm;@[0;(q;::);{[tm; t; msgs] if[tm;system"T ",string t];\'msgs}[tm;t]];@[q;::;{\'x}]];if[tm;system"T ",string t];r}{do[1000;2+2];{@[{.z.ide.ns.r1:x;:.z.ide.ns.r1};x;{r:y;:r}[;x]]}({:x!{![sv[`;] each x cross `Tables`Functions`Variables; system each "afv" cross enlist[" "] cross enlist string x]} each x} [{raze x,.z.s\'[{x where{@[{1#get x};x;`]~1#.q}\'[x]}` sv\'x,\'key x]}`]),(enlist `.z)!flip (`.z.Tables`.z.Functions`.z.Variables)!(enlist 0#`;enlist `ac`bm`exit`pc`pd`pg`ph`pi`pm`po`pp`ps`pw`vs`ts`s`wc`wo`ws;enlist `a`b`e`f`h`i`k`K`l`o`q`u`w`W`x`X`n`N`p`P`z`Z`t`T`d`D`c`zd)}'; + this.connection?.k(globalQuery, (err, result) => { + if (err) { + window.showErrorMessage( + `Failed to retrieve kdb+ global variables: '${err.message}`, + ); + return; + } + + this.updateGlobals(result); + }); + } + + /* eslint-disable @typescript-eslint/no-explicit-any */ + private updateGlobals(result: any): void { + const globals = result; + const entries: [string, any][] = Object.entries(globals); + + ext.functions.length = 0; + ext.tables.length = 0; + ext.variables.length = 0; + + entries.forEach(([key, value]) => { + key = key === "null" ? "." : key + "."; + const f = value[key + "Functions"]; + const t = value[key + "Tables"]; + let v = value[key + "Variables"]; + key = key === "." || key === ".q." ? "" : key; + + if (f instanceof Array) { + f.forEach((obj: any) => ext.functions.push(`${key}${obj}`)); + } + + if (t instanceof Array) { + t.forEach((obj: any) => ext.tables.push(`${key}${obj}`)); + } + + if (v instanceof Array) { + v = v.filter((x: any) => !t.includes(x)); + v.forEach((obj: any) => ext.variables.push(`${key}${obj}`)); + } + }); + } + /* eslint-disable */ + + private updateReservedKeywords() { + const reservedQuery = ".Q.res"; + this.connection?.k(reservedQuery, (err, result) => { + if (err) { + window.showErrorMessage( + `Failed to retrieve kdb+ reserved keywords: '${err.message}`, + ); + return; + } + + ext.keywords = result; + }); + } + + private onConnect( + err: Error | undefined, + conn: nodeq.Connection, + callback: nodeq.AsyncValueCallback, + ): void { + this.connected = true; + this.connection = conn; + + this.update(); + + callback(err, this); + } +} diff --git a/src/commands/serverCommand.ts b/src/commands/serverCommand.ts index f7ac18ca..9de28f7c 100644 --- a/src/commands/serverCommand.ts +++ b/src/commands/serverCommand.ts @@ -19,7 +19,6 @@ import * as url from "url"; import { Position, ProgressLocation, Range, commands, window } from "vscode"; import { ext } from "../extensionVariables"; import { isCompressed, uncompress } from "../ipc/c"; -import { Connection } from "../models/connection"; import { GetDataObjectPayload } from "../models/data"; import { DataSourceFiles, DataSourceTypes } from "../models/dataSource"; import { ExecutionTypes } from "../models/execution"; @@ -65,6 +64,7 @@ import { QueryHistory } from "../models/queryHistory"; import { runDataSource } from "./dataSourceCommand"; import { NewConnectionPannel } from "../panels/newConnection"; import { Telemetry } from "../utils/telemetryClient"; +import { ConnectionManagementService } from "../services/connectionManagerService"; export async function addNewConnection(): Promise { NewConnectionPannel.render(ext.context.extensionUri); @@ -268,7 +268,7 @@ export async function addKdbConnection( export async function removeConnection(viewItem: KdbNode): Promise { if (viewItem.label.indexOf("connected") !== -1) { - await disconnect(); + await disconnect(viewItem.label); } const servers: Server | undefined = getServers(); @@ -321,6 +321,7 @@ export async function connectInsights(viewItem: InsightsNode): Promise { Telemetry.sendEvent("Connection.Connected.Insights"); } + ext.activeConnection = undefined; ext.connectionNode = viewItem; ext.serverProvider.reload(); refreshDataSourcesPanel(); @@ -642,6 +643,7 @@ export async function removeInsightsConnection( } export async function connect(viewItem: KdbNode): Promise { + const connMngService = new ConnectionManagementService(); commands.executeCommand("kdb-results.focus"); await commands.executeCommand("setContext", "kdb.insightsConnected", false); ExecutionConsole.start(); @@ -675,76 +677,33 @@ export async function connect(viewItem: KdbNode): Promise { } } - // check for auth - const authCredentials = viewItem.details.auth - ? await ext.secretSettings.getAuthData(viewItem.children[0]) - : undefined; - - const servers: Server | undefined = getServers(); - if (servers === undefined) { - window.showErrorMessage("Server not found."); - return; - } - - const key = - viewItem.details.serverAlias != "" - ? getHash( - `${viewItem.details.serverName}${viewItem.details.serverPort}${viewItem.details.serverAlias}`, - ) - : getHash(`${viewItem.details.serverName}${viewItem.details.serverPort}`); - const connection = `${servers[key].serverName}:${servers[key].serverPort}`; - - if (authCredentials != undefined) { - const creds = authCredentials.split(":"); - ext.connection = new Connection( - connection, - creds, - viewItem.details.tls ?? false, - ); - } else { - ext.connection = new Connection( - connection, - undefined, - viewItem.details.tls ?? false, - ); - } + await connMngService.connect(viewItem.label); if (viewItem.details.tls) { process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = "0"; } - // eslint-disable-next-line @typescript-eslint/no-empty-function - ext.connection.connect((err, conn) => { - if (err) { - window.showErrorMessage(err.message); - return; - } - - if (conn) { - ext.outputChannel.appendLine( - `Connection established successfully to: ${viewItem.details.serverName}`, - ); - - commands.executeCommand("setContext", "kdb.connected", [ - `${getServerName(viewItem.details)}` + " (connected)", - ]); - ext.connectionNode = viewItem; - Telemetry.sendEvent("Connection.Connected.QProcess"); - ext.serverProvider.reload(); - } - }); refreshDataSourcesPanel(); + ext.serverProvider.reload(); } -export async function disconnect(): Promise { - ext.connection?.disconnect(); - await commands.executeCommand("setContext", "kdb.connected", false); - commands.executeCommand("setContext", "kdb.insightsConnected", false); - ext.connectionNode = undefined; - const queryConsole = ExecutionConsole.start(); - queryConsole.dispose(); - DataSourcesPanel.close(); - ext.serverProvider.reload(); +export async function disconnect(connLabel?: string): Promise { + const insightsNode = ext.kdbinsightsNodes.find((n) => + ext.connectionNode instanceof InsightsNode + ? n === ext.connectionNode?.details.alias + " (connected)" + : false, + ); + if (insightsNode) { + commands.executeCommand("setContext", "kdb.insightsConnected", false); + ext.connectionNode = undefined; + const queryConsole = ExecutionConsole.start(); + queryConsole.dispose(); + DataSourcesPanel.close(); + ext.serverProvider.reload(); + } else { + const connMngService = new ConnectionManagementService(); + await connMngService.disconnect(connLabel ? connLabel : ""); + } } export async function executeQuery( @@ -752,6 +711,7 @@ export async function executeQuery( context?: string, isPython?: boolean, ): Promise { + const connMngService = new ConnectionManagementService(); const queryConsole = ExecutionConsole.start(); if (ext.connection === undefined && ext.connectionNode === undefined) { window.showInformationMessage( @@ -791,7 +751,7 @@ export async function executeQuery( ); } else { const startTime = Date.now(); - const queryRes = await ext.connection.executeQuery(query, context, true); + const queryRes = await connMngService.executeQuery(query, context, true); const endTime = Date.now(); writeQueryResultsToConsole( queryRes, diff --git a/src/extension.ts b/src/extension.ts index 7241a801..aea38894 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -50,7 +50,6 @@ import { stopLocalProcessByServerName, } from "./commands/installTools"; import { - addAuthConnection, addInsightsConnection, addKdbConnection, addNewConnection, @@ -182,9 +181,12 @@ export async function activate(context: ExtensionContext) { await removeInsightsConnection(viewItem); }, ), - commands.registerCommand("kdb.disconnect", async () => { - await disconnect(); - }), + commands.registerCommand( + "kdb.disconnect", + async (viewItem: InsightsNode | KdbNode) => { + await disconnect(viewItem.label); + }, + ), commands.registerCommand("kdb.addConnection", async () => { await addNewConnection(); }), diff --git a/src/extensionVariables.ts b/src/extensionVariables.ts index 66aebcc0..3049b1a5 100644 --- a/src/extensionVariables.ts +++ b/src/extensionVariables.ts @@ -13,7 +13,6 @@ import { ExtensionContext, extensions, OutputChannel } from "vscode"; import { LanguageClient } from "vscode-languageclient/node"; -import { Connection } from "./models/connection"; import { LocalProcess } from "./models/localProcess"; import { MetaObjectPayload } from "./models/meta"; import { QueryHistory } from "./models/queryHistory"; @@ -27,6 +26,7 @@ import { import { QueryHistoryProvider } from "./services/queryHistoryProvider"; import { KdbResultsViewProvider } from "./services/resultsPanelProvider"; import AuthSettings from "./utils/secretStorage"; +import { LocalConnection } from "./classes/localConnection"; // eslint-disable-next-line @typescript-eslint/no-namespace export namespace ext { @@ -44,7 +44,10 @@ export namespace ext { export let isBundleQCreated: boolean; export const rowLimit = 150000000; - export let connection: Connection | undefined; + export let connection: LocalConnection | undefined; + export let activeConnection: LocalConnection | undefined; + export const connectedConnectionList: Array = []; + export const connectionsList: Array = []; export let hideDetailedConsoleQueryOutput: boolean; export let connectionNode: KdbNode | InsightsNode | undefined; export const kdbDataSourceFolder = ".kdb-datasources"; diff --git a/src/services/connectionManagerService.ts b/src/services/connectionManagerService.ts new file mode 100644 index 00000000..c94b485c --- /dev/null +++ b/src/services/connectionManagerService.ts @@ -0,0 +1,151 @@ +/* + * Copyright (c) 1998-2023 Kx Systems Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +import { LocalConnection } from "../classes/localConnection"; +import { window, commands } from "vscode"; +import { ext } from "../extensionVariables"; +import { InsightsNode, KdbNode } from "./kdbTreeProvider"; +import { Telemetry } from "../utils/telemetryClient"; + +export class ConnectionManagementService { + public retrieveConnection( + connLabel: string, + ): KdbNode | InsightsNode | undefined { + return ext.connectionsList.find( + (connections: KdbNode | InsightsNode) => connLabel === connections.label, + ); + } + + public retrieveConnectedConnection( + connLabel: string, + ): LocalConnection | undefined { + return ext.connectedConnectionList.find( + (connection: LocalConnection) => connLabel === connection.connLabel, + ); + } + + public isKdbConnection(connection: KdbNode | InsightsNode): boolean { + return connection instanceof KdbNode; + } + + public isLocalConnection(): boolean { + return ext.activeConnection instanceof LocalConnection; + } + + public retrieveLocalConnectionString(connection: KdbNode): string { + return connection.details.serverName + ":" + connection.details.serverPort; + } + + public async connect(connLabel: string): Promise { + // check if connection exists + const connection = this.retrieveConnection(connLabel); + if (!connection) { + return; + } + + if (connection instanceof KdbNode) { + const connectionString = this.retrieveLocalConnectionString(connection); + const authCredentials = connection.details.auth + ? await ext.secretSettings.getAuthData(connection.children[0]) + : undefined; + const localConnection = new LocalConnection( + connectionString, + connLabel, + authCredentials ? authCredentials.split(":") : undefined, + connection.details.tls, + ); + await localConnection.connect((err, conn) => { + if (err) { + window.showErrorMessage(err.message); + return; + } + + if (conn) { + ext.outputChannel.appendLine( + `Connection established successfully to: ${connLabel}`, + ); + + commands.executeCommand("setContext", "kdb.connected", [ + `${connLabel}` + " (connected)", + ]); + + ext.connectionNode = connection; + Telemetry.sendEvent("Connection.Connected.QProcess"); + ext.serverProvider.reload(); + + this.setActiveConnection(connLabel); + } + }); + ext.connectedConnectionList.push(localConnection); + ext.activeConnection = localConnection; + } else { + // work with Insights nodes + } + } + + public setActiveConnection(connLabel: string): void { + const connection = this.retrieveConnectedConnection(connLabel); + if (!connection) { + return; + } + commands.executeCommand("setContext", "kdb.connected.active", [ + `${connLabel}` + " (active)", + ]); + Telemetry.sendEvent("Connection.Connected.Active"); + ext.activeConnection = connection; + ext.connection = connection; + } + + public disconnect(connLabel: string): void { + const connection = this.retrieveConnectedConnection(connLabel); + if (!connection) { + return; + } + const isLocal = this.isLocalConnection(); + if (isLocal) { + connection.getConnection()?.close(() => { + ext.connectedConnectionList.splice( + ext.connectedConnectionList.indexOf(connection), + 1, + ); + ext.activeConnection = undefined; + ext.connectionNode = undefined; + commands.executeCommand("setContext", "kdb.connected", false); + commands.executeCommand("setContext", "kdb.connected.active", false); + Telemetry.sendEvent("Connection.Disconnected"); + ext.outputChannel.appendLine( + `Connection stopped from ${connection.connLabel}`, + ); + }); + } + } + + public async executeQuery( + command: string, + context?: string, + stringfy?: boolean, + ): Promise { + const connection = ext.activeConnection; + if (!connection) { + return; + } + const isLocal = this.isLocalConnection(); + if (isLocal) { + const result = await connection?.executeQuery(command, context, stringfy); + return result; + } else { + // Work with Insights nodes + return; + } + } +} diff --git a/src/services/kdbTreeProvider.ts b/src/services/kdbTreeProvider.ts index 33eeda0c..44292066 100644 --- a/src/services/kdbTreeProvider.ts +++ b/src/services/kdbTreeProvider.ts @@ -31,7 +31,12 @@ import { loadVariables, loadViews, } from "../models/serverObject"; -import { getInsightsAlias, getServerAlias, getServerName } from "../utils/core"; +import { + getInsightsAlias, + getServerAlias, + getServerIconState, + getServerName, +} from "../utils/core"; export class KdbTreeProvider implements TreeDataProvider { private _onDidChangeTreeData: EventEmitter< @@ -100,8 +105,10 @@ export class KdbTreeProvider implements TreeDataProvider { } private getMergedElements(_element?: TreeItem): TreeItem[] { + ext.connectionsList.length = 0; const servers = this.getChildElements(_element); const insights = this.getInsightsChildElements(); + ext.connectionsList.push(...servers, ...insights); ext.kdbConnectionAliasList.length = 0; getServerAlias(servers.map((x) => x.details)); getInsightsAlias(insights.map((x) => x.details)); @@ -320,9 +327,9 @@ export class KdbNode extends TreeItem { label = label + ` [${details.serverAlias}]`; } - if (ext.connectionNode != undefined && label === ext.connectionNode.label) { - label = label + " (connected)"; - } + // if (ext.connectionNode != undefined && label === ext.connectionNode.label) { + // label = label + " (connected)"; + // } // set context for root nodes if (ext.kdbrootNodes.indexOf(label) === -1) { @@ -392,10 +399,7 @@ export class KdbNode extends TreeItem { "..", "resources", "light", - ext.connectionNode != undefined && - this.label === ext.connectionNode.label + " (connected)" - ? "p-data.svg" - : "p-data.svg", + "p-data" + getServerIconState(this.label) + ".svg", ), dark: path.join( __filename, @@ -403,10 +407,7 @@ export class KdbNode extends TreeItem { "..", "resources", "dark", - ext.connectionNode != undefined && - this.label === ext.connectionNode.label + " (connected)" - ? "p-data.svg" - : "p-data.svg", + "p-data" + getServerIconState(this.label) + ".svg", ), }; @@ -460,10 +461,7 @@ export class InsightsNode extends TreeItem { "..", "resources", "light", - ext.connectionNode != undefined && - this.label === ext.connectionNode.label + " (connected)" - ? "p-insights.svg" - : "p-insights.svg", + "p-insights" + getServerIconState(this.label) + ".svg", ), dark: path.join( __filename, @@ -471,10 +469,7 @@ export class InsightsNode extends TreeItem { "..", "resources", "dark", - ext.connectionNode != undefined && - this.label === ext.connectionNode.label + " (connected)" - ? "p-insights.svg" - : "p-insights.svg", + "p-insights" + getServerIconState(this.label) + ".svg", ), }; diff --git a/src/utils/core.ts b/src/utils/core.ts index 4b1f2106..9b385a99 100644 --- a/src/utils/core.ts +++ b/src/utils/core.ts @@ -255,6 +255,17 @@ export function getInsightsAlias(insightsList: InsightDetails[]): void { }); } +export function getServerIconState(label: string): string { + if (ext.activeConnection?.connLabel === label) { + return "-active"; + } else if ( + ext.connectedConnectionList?.some((conn) => conn.connLabel === label) + ) { + return "-connected"; + } + return ""; +} + export function delay(ms: number) { return new Promise((resolve) => setTimeout(resolve, ms)); } diff --git a/test/suite/commands.test.ts b/test/suite/commands.test.ts index 3a4d9350..413f9615 100644 --- a/test/suite/commands.test.ts +++ b/test/suite/commands.test.ts @@ -42,11 +42,11 @@ import * as coreUtils from "../../src/utils/core"; import * as dataSourceUtils from "../../src/utils/dataSource"; import { ExecutionConsole } from "../../src/utils/executionConsole"; import * as queryUtils from "../../src/utils/queryUtils"; -import { Connection } from "../../src/models/connection"; import { QueryHistory } from "../../src/models/queryHistory"; -import { Server, ServerDetails, ServerType } from "../../src/models/server"; +import { ServerDetails, ServerType } from "../../src/models/server"; import { NewConnectionPannel } from "../../src/panels/newConnection"; import { MAX_STR_LEN } from "../../src/validators/kdbValidator"; +import { LocalConnection } from "../../src/classes/localConnection"; // eslint-disable-next-line @typescript-eslint/no-var-requires const dsCmd = require("../../src/commands/dataSourceCommand"); @@ -1578,7 +1578,7 @@ describe("serverCommand", () => { writeResultsViewStub, writeResultsConsoleStub: sinon.SinonStub; beforeEach(() => { - ext.connection = new Connection("localhost:5001"); + ext.connection = new LocalConnection("localhost:5001"); ext.connection.connected = true; ext.connectionNode = kdbNode; isVisibleStub = sinon.stub(ext.resultsViewProvider, "isVisible"); diff --git a/test/suite/models.test.ts b/test/suite/models.test.ts index d8a83fa5..e6ea2c51 100644 --- a/test/suite/models.test.ts +++ b/test/suite/models.test.ts @@ -14,7 +14,6 @@ import assert from "assert"; import sinon from "sinon"; import { ext } from "../../src/extensionVariables"; -import { Connection } from "../../src/models/connection"; import { ServerObject, loadDictionaries, @@ -24,6 +23,7 @@ import { loadVariables, loadViews, } from "../../src/models/serverObject"; +import { LocalConnection } from "../../src/classes/localConnection"; // eslint-disable-next-line @typescript-eslint/no-var-requires const so = require("../../src/commands/serverCommand"); @@ -66,7 +66,7 @@ describe("Models", () => { assert.strictEqual( result[0], testObject[0], - "Single server object that is a namespace should be returned." + "Single server object that is a namespace should be returned.", ); sinon.restore(); }); @@ -99,7 +99,7 @@ describe("Models", () => { assert.strictEqual( result[0], testObject0[0], - "Single server object that is a namespace should be returned." + "Single server object that is a namespace should be returned.", ); sinon.restore(); }); @@ -123,8 +123,8 @@ describe("Models", () => { result[0], testObject2[0], `Single server object that is a namespace should be returned: ${JSON.stringify( - result - )}` + result, + )}`, ); sinon.restore(); }); @@ -135,7 +135,7 @@ describe("Models", () => { assert.strictEqual( result.length, 0, - "ServerObjects returned should be zero." + "ServerObjects returned should be zero.", ); sinon.restore(); }); @@ -158,7 +158,7 @@ describe("Models", () => { assert.strictEqual( result[0], testObject[0], - "Single server object that is a namespace should be returned." + "Single server object that is a namespace should be returned.", ); sinon.restore(); }); @@ -169,7 +169,7 @@ describe("Models", () => { assert.strictEqual( result.length, 0, - "ServerObjects returned should be zero." + "ServerObjects returned should be zero.", ); sinon.restore(); }); @@ -192,7 +192,7 @@ describe("Models", () => { assert.strictEqual( result[0], testObject[0], - "Single server object that is a namespace should be returned." + "Single server object that is a namespace should be returned.", ); sinon.restore(); }); @@ -203,7 +203,7 @@ describe("Models", () => { assert.strictEqual( result.length, 0, - "ServerObjects returned should be zero." + "ServerObjects returned should be zero.", ); sinon.restore(); }); @@ -226,7 +226,7 @@ describe("Models", () => { assert.strictEqual( result[0], testObject[0], - "Single server object that is a namespace should be returned." + "Single server object that is a namespace should be returned.", ); sinon.restore(); }); @@ -237,7 +237,7 @@ describe("Models", () => { assert.strictEqual( result.length, 0, - "ServerObjects returned should be zero." + "ServerObjects returned should be zero.", ); sinon.restore(); }); @@ -261,13 +261,13 @@ describe("Models", () => { assert.strictEqual( result[0], testObject[0], - "Single server object that is a namespace should be returned." + "Single server object that is a namespace should be returned.", ); sinon.restore(); }); it("Should return sorted views", async () => { - ext.connection = new Connection("localhost:5001"); + ext.connection = new LocalConnection("localhost:5001"); sinon.stub(ext.connection, "executeQuery").resolves(["vw1", "vw2"]); const result = await loadViews(); assert.strictEqual(result[0], "vw1", "Should return the first view"); @@ -275,7 +275,7 @@ describe("Models", () => { }); it("Should return sorted views (reverse order)", async () => { - ext.connection = new Connection("localhost:5001"); + ext.connection = new LocalConnection("localhost:5001"); sinon.stub(ext.connection, "executeQuery").resolves(["vw1", "vw2"]); const result = await loadViews(); assert.strictEqual(result[0], "vw1", "Should return the first view"); @@ -283,30 +283,34 @@ describe("Models", () => { }); it("Should create a new connection object", () => { - const conn = new Connection("server:5001"); + const conn = new LocalConnection("server:5001"); assert.strictEqual( conn.connected, false, - "Connection should be created but not connected." + "Connection should be created but not connected.", ); }); it("Should create a new connection object (full options)", () => { - const conn = new Connection("server:5001", ["username", "password"], true); + const conn = new LocalConnection( + "server:5001", + ["username", "password"], + true, + ); assert.strictEqual( conn.connected, false, - "Connection should be created but not connected." + "Connection should be created but not connected.", ); }); it("Should create a new connection object", () => { - const conn = new Connection("server:5001"); + const conn = new LocalConnection("server:5001"); conn.disconnect(); assert.strictEqual( conn.connected, false, - "Connection should be created but not connected." + "Connection should be created but not connected.", ); }); });