diff --git a/src/models/serverObject.ts b/src/models/serverObject.ts index 39c9d7c3..fe8ff9c7 100644 --- a/src/models/serverObject.ts +++ b/src/models/serverObject.ts @@ -11,10 +11,6 @@ * specific language governing permissions and limitations under the License. */ -import { LocalConnection } from "../classes/localConnection"; -import { loadServerObjects } from "../commands/serverCommand"; -import { ext } from "../extensionVariables"; - export interface ServerObject { id: number; pid: number; @@ -25,122 +21,3 @@ export interface ServerObject { context: object; isNs: boolean; } - -export async function loadNamespaces(root?: string): Promise { - const serverObjects = await loadServerObjects(); - if (serverObjects !== undefined) { - const ns = serverObjects.filter((value) => { - return value.isNs ? value : undefined; - }); - - const sorted = sortObjects(ns); - - return getNamespaces(sorted, root); - } - return new Array(); -} - -export async function loadDictionaries(ns: string): Promise { - const serverObjects = await loadServerObjects(); - if (serverObjects !== undefined) { - const dicts = serverObjects.filter((value) => { - return value.typeNum === 99 && !value.isNs && value.namespace === ns - ? value - : undefined; - }); - return sortObjects(dicts); - } - return new Array(); -} - -export async function loadFunctions(ns: string): Promise { - const serverObjects = await loadServerObjects(); - if (serverObjects !== undefined) { - const funcs = serverObjects.filter((value) => { - return value.typeNum === 100 && !value.isNs && value.namespace === ns - ? value - : undefined; - }); - return sortObjects(funcs); - } - return new Array(); -} - -export async function loadTables(ns: string): Promise { - const serverObjects = await loadServerObjects(); - if (serverObjects !== undefined) { - const tables = serverObjects.filter((value) => { - return value.typeNum === 98 && !value.isNs && value.namespace === ns - ? value - : undefined; - }); - return sortObjects(tables); - } - return new Array(); -} - -export async function loadVariables(ns: string): Promise { - const serverObjects = await loadServerObjects(); - const views = await loadViews(); - - if (serverObjects !== undefined) { - const vars = serverObjects.filter((value) => { - return views.indexOf(value.name) === -1 && - value.typeNum < 98 && - !value.isNs && - value.namespace === ns - ? value - : undefined; - }); - return sortObjects(vars); - } - return new Array(); -} - -export async function loadViews(): Promise { - if (ext.activeConnection instanceof LocalConnection) { - const rawViewArray = await ext.activeConnection?.executeQuery("views`"); - const views = rawViewArray?.filter((item: any) => { - return item !== "s#" && item !== "" && item !== ","; - }); - const sorted = views?.sort((object1: any, object2: any) => { - if (object1 < object2) { - return -1; - } else if (object1 > object2) { - return 1; - } - return 0; - }); - return sorted ?? new Array(); - } - return new Array(); -} - -function getNamespaces(input: ServerObject[], root = "."): ServerObject[] { - const output: ServerObject[] = []; - - input.forEach((v, i) => { - let index = -1; - if (root === v.namespace) { - index = i; - } - - if (index != -1) { - output.push(v); - } - }); - - return output; -} - -function sortObjects(input: ServerObject[]): ServerObject[] { - const sorted = input.sort((object1, object2) => { - if (object1.fname < object2.fname) { - return -1; - } else if (object1.fname > object2.fname) { - return 1; - } - return 0; - }); - return sorted; -} diff --git a/src/services/kdbTreeProvider.ts b/src/services/kdbTreeProvider.ts index 465d867a..22b5fb17 100644 --- a/src/services/kdbTreeProvider.ts +++ b/src/services/kdbTreeProvider.ts @@ -22,14 +22,6 @@ import { commands, } from "vscode"; import { ext } from "../extensionVariables"; -import { - loadDictionaries, - loadFunctions, - loadNamespaces, - loadTables, - loadVariables, - loadViews, -} from "../models/serverObject"; import { getInsightsAlias, getServerAlias, @@ -53,6 +45,7 @@ import { Server, ServerDetails, } from "../models/connectionsModels"; +import { KdbTreeService } from "./kdbTreeService"; export class KdbTreeProvider implements TreeDataProvider { private _onDidChangeTreeData: EventEmitter< @@ -214,7 +207,7 @@ export class KdbTreeProvider implements TreeDataProvider { /* istanbul ignore next */ private async getNamespaces(connLabel?: string): Promise { - const ns = await loadNamespaces(); + const ns = await KdbTreeService.loadNamespaces(); const result = ns.map( (x) => new QNamespaceNode( @@ -272,7 +265,9 @@ export class KdbTreeProvider implements TreeDataProvider { serverType instanceof QCategoryNode ? serverType.connLabel : ""; if (serverType.label === ext.qObjectCategories[0]) { // dictionaries - const dicts = await loadDictionaries(serverType.contextValue ?? ""); + const dicts = await KdbTreeService.loadDictionaries( + serverType.contextValue ?? "", + ); const result = dicts.map( (x) => new QServerNode( @@ -291,7 +286,9 @@ export class KdbTreeProvider implements TreeDataProvider { } } else if (serverType.label === ext.qObjectCategories[1]) { // functions - const funcs = await loadFunctions(serverType.contextValue ?? ""); + const funcs = await KdbTreeService.loadFunctions( + serverType.contextValue ?? "", + ); const result = funcs.map( (x) => new QServerNode( @@ -310,7 +307,9 @@ export class KdbTreeProvider implements TreeDataProvider { } } else if (serverType.label === ext.qObjectCategories[2]) { // tables - const tables = await loadTables(serverType.contextValue ?? ""); + const tables = await KdbTreeService.loadTables( + serverType.contextValue ?? "", + ); const result = tables.map( (x) => new QServerNode( @@ -329,7 +328,9 @@ export class KdbTreeProvider implements TreeDataProvider { } } else if (serverType.label === ext.qObjectCategories[3]) { // variables - const vars = await loadVariables(serverType.contextValue ?? ""); + const vars = await KdbTreeService.loadVariables( + serverType.contextValue ?? "", + ); const result = vars.map( (x) => new QServerNode( @@ -348,7 +349,7 @@ export class KdbTreeProvider implements TreeDataProvider { } } else if (serverType.label === ext.qObjectCategories[4]) { // views - const views = await loadViews(); + const views = await KdbTreeService.loadViews(); const result = views.map( (x) => new QServerNode( diff --git a/src/services/kdbTreeService.ts b/src/services/kdbTreeService.ts new file mode 100644 index 00000000..ba672795 --- /dev/null +++ b/src/services/kdbTreeService.ts @@ -0,0 +1,128 @@ +import { ServerObject } from "../models/serverObject"; +import { ext } from "../extensionVariables"; +import { loadServerObjects } from "../commands/serverCommand"; +import { LocalConnection } from "../classes/localConnection"; + +export class KdbTreeService { + static async loadNamespaces(root?: string): Promise { + const serverObjects = await loadServerObjects(); + if (serverObjects !== undefined) { + const ns = serverObjects.filter((value) => { + return value.isNs ? value : undefined; + }); + + const sorted = KdbTreeService.sortObjects(ns); + + return KdbTreeService.getNamespaces(sorted, root); + } + return new Array(); + } + + static async loadDictionaries(ns: string): Promise { + const serverObjects = await loadServerObjects(); + if (serverObjects !== undefined) { + const dicts = serverObjects.filter((value) => { + return value.typeNum === 99 && !value.isNs && value.namespace === ns + ? value + : undefined; + }); + return KdbTreeService.sortObjects(dicts); + } + return new Array(); + } + + static async loadFunctions(ns: string): Promise { + const serverObjects = await loadServerObjects(); + if (serverObjects !== undefined) { + const funcs = serverObjects.filter((value) => { + return value.typeNum === 100 && !value.isNs && value.namespace === ns + ? value + : undefined; + }); + return KdbTreeService.sortObjects(funcs); + } + return new Array(); + } + + static async loadTables(ns: string): Promise { + const serverObjects = await loadServerObjects(); + if (serverObjects !== undefined) { + const tables = serverObjects.filter((value) => { + return value.typeNum === 98 && !value.isNs && value.namespace === ns + ? value + : undefined; + }); + return KdbTreeService.sortObjects(tables); + } + return new Array(); + } + + static async loadVariables(ns: string): Promise { + const serverObjects = await loadServerObjects(); + const views = await KdbTreeService.loadViews(); + + if (serverObjects !== undefined) { + const vars = serverObjects.filter((value) => { + return views.indexOf(value.name) === -1 && + value.typeNum < 98 && + !value.isNs && + value.namespace === ns + ? value + : undefined; + }); + return KdbTreeService.sortObjects(vars); + } + return new Array(); + } + + static async loadViews(): Promise { + if (ext.activeConnection instanceof LocalConnection) { + const rawViewArray = await ext.activeConnection?.executeQuery("views`"); + const views = rawViewArray?.filter((item: any) => { + return item !== "s#" && item !== "" && item !== ","; + }); + const sorted = views?.sort((object1: any, object2: any) => { + if (object1 < object2) { + return -1; + } else if (object1 > object2) { + return 1; + } + return 0; + }); + return sorted ?? new Array(); + } + return new Array(); + } + + private static getNamespaces( + input: ServerObject[], + root = ".", + ): ServerObject[] { + const output: ServerObject[] = []; + + input.forEach((v, i) => { + let index = -1; + if (root === v.namespace) { + index = i; + } + + if (index != -1) { + output.push(v); + } + }); + + return output; + } + + private static sortObjects(input: ServerObject[]): ServerObject[] { + const sorted = input.sort((object1, object2) => { + if (object1.fname < object2.fname) { + return -1; + } else if (object1.fname > object2.fname) { + return 1; + } + return 0; + }); + return sorted; + } +} diff --git a/test/suite/models.test.ts b/test/suite/models.test.ts deleted file mode 100644 index 903593eb..00000000 --- a/test/suite/models.test.ts +++ /dev/null @@ -1,284 +0,0 @@ -/* - * 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 assert from "assert"; -import sinon from "sinon"; -import { ext } from "../../src/extensionVariables"; -import { - ServerObject, - loadDictionaries, - loadFunctions, - loadNamespaces, - loadTables, - 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"); -// eslint-disable-next-line @typescript-eslint/no-var-requires -const vw = require("../../src/models/serverObject"); - -describe("Models", () => { - it("Should return empty ServerObjects array when none are loaded", async () => { - sinon.stub(so, "loadServerObjects").resolves(undefined); - const result = await loadNamespaces(""); - assert.strictEqual(result.length, 0, "Namespaces returned should be zero."); - sinon.restore(); - }); - - it("Should return a single server object that ia a namespace", async () => { - const testObject: ServerObject[] = [ - { - id: 1, - pid: 1, - name: "test", - fname: "test1", - typeNum: 1, - namespace: ".", - context: {}, - isNs: true, - }, - { - id: 2, - pid: 2, - name: "test", - fname: "test2", - typeNum: 1, - namespace: ".", - context: {}, - isNs: true, - }, - ]; - sinon.stub(so, "loadServerObjects").resolves(testObject); - const result = await loadNamespaces(); - assert.strictEqual( - result[0], - testObject[0], - "Single server object that is a namespace should be returned.", - ); - sinon.restore(); - }); - - it("Should return a single server object that ia a namespace (reverse sort)", async () => { - const testObject0: ServerObject[] = [ - { - id: 1, - pid: 1, - name: "test", - fname: "test", - typeNum: 1, - namespace: ".", - context: {}, - isNs: true, - }, - { - id: 0, - pid: 0, - name: "test", - fname: "test0", - typeNum: 1, - namespace: ".", - context: {}, - isNs: true, - }, - ]; - sinon.stub(so, "loadServerObjects").resolves(testObject0); - const result = await loadNamespaces(); - assert.strictEqual( - result[0], - testObject0[0], - "Single server object that is a namespace should be returned.", - ); - sinon.restore(); - }); - - it("Should return a single server object that ia a namespace", async () => { - const testObject2: ServerObject[] = [ - { - id: 1, - pid: 1, - name: "test", - fname: "test", - typeNum: 1, - namespace: ".", - context: {}, - isNs: true, - }, - ]; - sinon.stub(so, "loadServerObjects").resolves(testObject2); - const result = await loadNamespaces("."); - assert.strictEqual( - result[0], - testObject2[0], - `Single server object that is a namespace should be returned: ${JSON.stringify( - result, - )}`, - ); - sinon.restore(); - }); - - it("Should return empty ServerObjects array when none are loaded", async () => { - sinon.stub(so, "loadServerObjects").resolves(undefined); - const result = await loadDictionaries(""); - assert.strictEqual( - result.length, - 0, - "ServerObjects returned should be zero.", - ); - sinon.restore(); - }); - - it("Should return a single server object that ia a dictionary", async () => { - const testObject: ServerObject[] = [ - { - id: 1, - pid: 1, - name: "test", - fname: "test", - typeNum: 99, - namespace: ".", - context: {}, - isNs: false, - }, - ]; - sinon.stub(so, "loadServerObjects").resolves(testObject); - const result = await loadDictionaries("."); - assert.strictEqual( - result[0], - testObject[0], - "Single server object that is a namespace should be returned.", - ); - sinon.restore(); - }); - - it("Should return empty ServerObjects array when none are loaded", async () => { - sinon.stub(so, "loadServerObjects").resolves(undefined); - const result = await loadFunctions("."); - assert.strictEqual( - result.length, - 0, - "ServerObjects returned should be zero.", - ); - sinon.restore(); - }); - - it("Should return a single server object that ia a function", async () => { - const testObject: ServerObject[] = [ - { - id: 1, - pid: 1, - name: "test", - fname: "test", - typeNum: 100, - namespace: ".", - context: {}, - isNs: false, - }, - ]; - sinon.stub(so, "loadServerObjects").resolves(testObject); - const result = await loadFunctions("."); - assert.strictEqual( - result[0], - testObject[0], - "Single server object that is a namespace should be returned.", - ); - sinon.restore(); - }); - - it("Should return empty ServerObjects array when none are loaded", async () => { - sinon.stub(so, "loadServerObjects").resolves(undefined); - const result = await loadTables("."); - assert.strictEqual( - result.length, - 0, - "ServerObjects returned should be zero.", - ); - sinon.restore(); - }); - - it("Should return a single server object that ia a table", async () => { - const testObject: ServerObject[] = [ - { - id: 1, - pid: 1, - name: "test", - fname: "test", - typeNum: 98, - namespace: ".", - context: {}, - isNs: false, - }, - ]; - sinon.stub(so, "loadServerObjects").resolves(testObject); - const result = await loadTables("."); - assert.strictEqual( - result[0], - testObject[0], - "Single server object that is a namespace should be returned.", - ); - sinon.restore(); - }); - - it("Should return empty ServerObjects array when none are loaded", async () => { - sinon.stub(so, "loadServerObjects").resolves(undefined); - const result = await loadVariables("."); - assert.strictEqual( - result.length, - 0, - "ServerObjects returned should be zero.", - ); - sinon.restore(); - }); - - it("Should return a single server object that ia a variable", async () => { - const testObject: ServerObject[] = [ - { - id: 1, - pid: 1, - name: "test", - fname: "test", - typeNum: -7, - namespace: ".", - context: {}, - isNs: false, - }, - ]; - sinon.stub(so, "loadServerObjects").resolves(testObject); - sinon.stub(vw, "loadViews").resolves([]); - const result = await loadVariables("."); - assert.strictEqual( - result[0], - testObject[0], - "Single server object that is a namespace should be returned.", - ); - sinon.restore(); - }); - - it("Should return sorted views", async () => { - ext.activeConnection = new LocalConnection("localhost:5001", "server1"); - sinon.stub(ext.activeConnection, "executeQuery").resolves(["vw1", "vw2"]); - const result = await loadViews(); - assert.strictEqual(result[0], "vw1", "Should return the first view"); - sinon.restore(); - }); - - it("Should return sorted views (reverse order)", async () => { - ext.activeConnection = new LocalConnection("localhost:5001", "server1"); - sinon.stub(ext.activeConnection, "executeQuery").resolves(["vw1", "vw2"]); - const result = await loadViews(); - assert.strictEqual(result[0], "vw1", "Should return the first view"); - sinon.restore(); - }); -}); diff --git a/test/suite/services.test.ts b/test/suite/services.test.ts index ea205c54..814c6322 100644 --- a/test/suite/services.test.ts +++ b/test/suite/services.test.ts @@ -70,6 +70,9 @@ import { } from "../../src/models/connectionsModels"; import AuthSettings from "../../src/utils/secretStorage"; import * as coreUtils from "../../src/utils/core"; +import { KdbTreeService } from "../../src/services/kdbTreeService"; +import * as serverCommand from "../../src/commands/serverCommand"; +import { ServerObject } from "../../src/models/serverObject"; // eslint-disable-next-line @typescript-eslint/no-var-requires const codeFlow = require("../../src/services/kdbInsights/codeFlowLogin"); @@ -2160,3 +2163,256 @@ describe("MetaContentProvider", () => { ); }); }); + +describe("kdbTreeService", () => { + it("Should return empty ServerObjects array when none are loaded", async () => { + sinon.stub(serverCommand, "loadServerObjects").resolves(undefined); + const result = await KdbTreeService.loadNamespaces(""); + assert.strictEqual(result.length, 0, "Namespaces returned should be zero."); + sinon.restore(); + }); + + it("Should return a single server object that ia a namespace", async () => { + const testObject: ServerObject[] = [ + { + id: 1, + pid: 1, + name: "test", + fname: "test1", + typeNum: 1, + namespace: ".", + context: {}, + isNs: true, + }, + { + id: 2, + pid: 2, + name: "test", + fname: "test2", + typeNum: 1, + namespace: ".", + context: {}, + isNs: true, + }, + ]; + sinon.stub(serverCommand, "loadServerObjects").resolves(testObject); + const result = await KdbTreeService.loadNamespaces(); + assert.strictEqual( + result[0], + testObject[0], + "Single server object that is a namespace should be returned.", + ); + sinon.restore(); + }); + + it("Should return a single server object that ia a namespace (reverse sort)", async () => { + const testObject0: ServerObject[] = [ + { + id: 1, + pid: 1, + name: "test", + fname: "test", + typeNum: 1, + namespace: ".", + context: {}, + isNs: true, + }, + { + id: 0, + pid: 0, + name: "test", + fname: "test0", + typeNum: 1, + namespace: ".", + context: {}, + isNs: true, + }, + ]; + sinon.stub(serverCommand, "loadServerObjects").resolves(testObject0); + const result = await KdbTreeService.loadNamespaces(); + assert.strictEqual( + result[0], + testObject0[0], + "Single server object that is a namespace should be returned.", + ); + sinon.restore(); + }); + + it("Should return a single server object that ia a namespace", async () => { + const testObject2: ServerObject[] = [ + { + id: 1, + pid: 1, + name: "test", + fname: "test", + typeNum: 1, + namespace: ".", + context: {}, + isNs: true, + }, + ]; + sinon.stub(serverCommand, "loadServerObjects").resolves(testObject2); + const result = await KdbTreeService.loadNamespaces("."); + assert.strictEqual( + result[0], + testObject2[0], + `Single server object that is a namespace should be returned: ${JSON.stringify( + result, + )}`, + ); + sinon.restore(); + }); + + it("Should return empty ServerObjects array when none are loaded", async () => { + sinon.stub(serverCommand, "loadServerObjects").resolves(undefined); + const result = await KdbTreeService.loadDictionaries(""); + assert.strictEqual( + result.length, + 0, + "ServerObjects returned should be zero.", + ); + sinon.restore(); + }); + + it("Should return a single server object that ia a dictionary", async () => { + const testObject: ServerObject[] = [ + { + id: 1, + pid: 1, + name: "test", + fname: "test", + typeNum: 99, + namespace: ".", + context: {}, + isNs: false, + }, + ]; + sinon.stub(serverCommand, "loadServerObjects").resolves(testObject); + const result = await KdbTreeService.loadDictionaries("."); + assert.strictEqual( + result[0], + testObject[0], + "Single server object that is a namespace should be returned.", + ); + sinon.restore(); + }); + + it("Should return empty ServerObjects array when none are loaded", async () => { + sinon.stub(serverCommand, "loadServerObjects").resolves(undefined); + const result = await KdbTreeService.loadFunctions("."); + assert.strictEqual( + result.length, + 0, + "ServerObjects returned should be zero.", + ); + sinon.restore(); + }); + + it("Should return a single server object that ia a function", async () => { + const testObject: ServerObject[] = [ + { + id: 1, + pid: 1, + name: "test", + fname: "test", + typeNum: 100, + namespace: ".", + context: {}, + isNs: false, + }, + ]; + sinon.stub(serverCommand, "loadServerObjects").resolves(testObject); + const result = await KdbTreeService.loadFunctions("."); + assert.strictEqual( + result[0], + testObject[0], + "Single server object that is a namespace should be returned.", + ); + sinon.restore(); + }); + + it("Should return empty ServerObjects array when none are loaded", async () => { + sinon.stub(serverCommand, "loadServerObjects").resolves(undefined); + const result = await KdbTreeService.loadTables("."); + assert.strictEqual( + result.length, + 0, + "ServerObjects returned should be zero.", + ); + sinon.restore(); + }); + + it("Should return a single server object that ia a table", async () => { + const testObject: ServerObject[] = [ + { + id: 1, + pid: 1, + name: "test", + fname: "test", + typeNum: 98, + namespace: ".", + context: {}, + isNs: false, + }, + ]; + sinon.stub(serverCommand, "loadServerObjects").resolves(testObject); + const result = await KdbTreeService.loadTables("."); + assert.strictEqual( + result[0], + testObject[0], + "Single server object that is a namespace should be returned.", + ); + sinon.restore(); + }); + + it("Should return empty ServerObjects array when none are loaded", async () => { + sinon.stub(serverCommand, "loadServerObjects").resolves(undefined); + const result = await KdbTreeService.loadVariables("."); + assert.strictEqual( + result.length, + 0, + "ServerObjects returned should be zero.", + ); + sinon.restore(); + }); + + it("Should return a single server object that ia a variable", async () => { + const testObject: ServerObject[] = [ + { + id: 1, + pid: 1, + name: "test", + fname: "test", + typeNum: -7, + namespace: ".", + context: {}, + isNs: false, + }, + ]; + sinon.stub(serverCommand, "loadServerObjects").resolves(testObject); + sinon.stub(KdbTreeService, "loadViews").resolves([]); + const result = await KdbTreeService.loadVariables("."); + assert.strictEqual( + result[0], + testObject[0], + "Single server object that is a namespace should be returned.", + ); + sinon.restore(); + }); + + it("Should return sorted views", async () => { + ext.activeConnection = new LocalConnection("localhost:5001", "server1"); + sinon.stub(ext.activeConnection, "executeQuery").resolves(["vw1", "vw2"]); + const result = await KdbTreeService.loadViews(); + assert.strictEqual(result[0], "vw1", "Should return the first view"); + sinon.restore(); + }); + + it("Should return sorted views (reverse order)", async () => { + ext.activeConnection = new LocalConnection("localhost:5001", "server1"); + sinon.stub(ext.activeConnection, "executeQuery").resolves(["vw1", "vw2"]); + const result = await KdbTreeService.loadViews(); + assert.strictEqual(result[0], "vw1", "Should return the first view"); + sinon.restore(); + }); +});