Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,12 @@ jobs:
if: runner.os == 'Linux'
run: |
npx vsce package -o ${{ steps.set-version.outputs.name }}.vsix
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v4
if: runner.os == 'Linux'
with:
name: ${{ steps.set-version.outputs.name }}.vsix
path: ${{ steps.set-version.outputs.name }}.vsix
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v4
if: runner.os == 'Linux'
with:
name: meta
Expand Down
15 changes: 14 additions & 1 deletion connection.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"title": "Connect using",
"type": "string",
"minLength": 1,
"enum": ["Server and Port"],
"enum": ["Server and Port", "Server Definition"],
"default": "Server and Port"
},
"showSystem": {
Expand Down Expand Up @@ -83,6 +83,19 @@
"askForPassword": { "$ref": "#/definitions/askForPassword" }
},
"required": ["server", "port", "username"]
},
{
"properties": {
"connectionMethod": {
"enum": ["Server Definition"]
},
"serverName": {
"title": "Server name",
"type": "string",
"minLength": 1
}
},
"required": ["serverName"]
}
]
},
Expand Down
41 changes: 26 additions & 15 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
"name": "sqltools-intersystems-driver",
"displayName": "SQLTools InterSystems IRIS",
"description": "SQLTools Driver for InterSystems IRIS",
"version": "0.1.8-SNAPSHOT",
"version": "0.2.0-SNAPSHOT",
"engines": {
"vscode": "^1.66.0"
"vscode": "^1.93.0"
},
"publisher": "intersystems-community",
"license": "MIT",
Expand Down Expand Up @@ -67,8 +67,9 @@
},
"devDependencies": {
"@babel/preset-env": "^7.14.2",
"@intersystems-community/intersystems-servermanager": "^3.8.0",
"@types/node": "^14.17.0",
"@types/vscode": "^1.66.0",
"@types/vscode": "^1.93.0",
"@vscode/vsce": "^2.19.0",
"rimraf": "^3.0.2",
"ts-loader": "^9.2.1",
Expand Down
123 changes: 104 additions & 19 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ const { publisher, name } = require('../package.json');
// import { workspace } from 'vscode';
// import { Uri } from 'vscode';
// import path from 'path';
import * as serverManager from "@intersystems-community/intersystems-servermanager";

const smExtensionId = "intersystems-community.servermanager";
let serverManagerApi: serverManager.ServerManagerAPI;

/** Map of the intersystems.server connection specs we have resolved via the API to that extension */
const resolvedConnSpecs = new Map<string, serverManager.IServerSpec>();

const driverName = 'InterSystems IRIS Driver';

Expand Down Expand Up @@ -45,35 +52,113 @@ export async function activate(extContext: ExtensionContext): Promise<IDriverExt
driverName,
parseBeforeSaveConnection: ({ connInfo }) => {
/**
* This hook is called before saving the connecton using the assistant
* so you can do any transformations before saving it to disk.active
* EG: relative file path transformation, string manipulation etc
* Below is the exmaple for SQLite, where we save the DB path relative to workspace
* and later we transform it back to absolute before editing
* This hook is called before saving the connection using the assistant
* so you can do any transformations before saving it
*/
// if (path.isAbsolute(connInfo.database)) {
// const databaseUri = Uri.file(connInfo.database);
// const dbWorkspace = workspace.getWorkspaceFolder(databaseUri);
// if (dbWorkspace) {
// connInfo.database = `\$\{workspaceFolder:${dbWorkspace.name}\}/${workspace.asRelativePath(connInfo.database, false)}`;
// }
// }
if (connInfo.connectionMethod === 'Server Definition') {
// Transform to a connectString property
connInfo.connectString = `${connInfo.serverName}:${connInfo.namespace}`;
connInfo.serverName = undefined;
connInfo.namespace = undefined;
// Remove properties carried over from 'Server and Port' type connection
connInfo.server = undefined;
connInfo.port = undefined;
connInfo.pathPrefix = undefined;
connInfo.https = undefined;
connInfo.askForPassword = undefined;
connInfo.username = undefined;
connInfo.password = undefined;

}
return connInfo;
},
parseBeforeEditConnection: ({ connInfo }) => {
/**
* This hook is called before editing the connecton using the assistant
* This hook is called before editing the connection using the assistant
* so you can do any transformations before editing it.
* EG: absolute file path transformation, string manipulation etc
* Below is the exmaple for SQLite, where we use relative path to save,
* but we transform to asolute before editing
*/
// if (!path.isAbsolute(connInfo.database) && /\$\{workspaceFolder:(.+)}/g.test(connInfo.database)) {
// const workspaceName = connInfo.database.match(/\$\{workspaceFolder:(.+)}/)[1];
// const dbWorkspace = workspace.workspaceFolders.find(w => w.name === workspaceName);
// if (dbWorkspace)
// connInfo.database = path.resolve(dbWorkspace.uri.fsPath, connInfo.database.replace(/\$\{workspaceFolder:(.+)}/g, './'));
// }
if (connInfo.connectionMethod === 'Server Definition') {
const connParts = connInfo.connectString.split(':');
connInfo.serverName = connParts[0];
connInfo.namespace = connParts[1];
}
return connInfo;
},
resolveConnection: async ({ connInfo }) => {
/**
* This hook is called after a connection definition has been fetched
* from settings and is about to be used to connect.
*/
if (connInfo.connectionMethod === 'Server Definition') {
const connParts = connInfo.connectString.split(':');
const serverName = connParts[0];
const namespace = connParts[1];
let connSpec = resolvedConnSpecs.get(serverName)
if (!connSpec) {

if (!serverManagerApi) {

// Get api for servermanager extension
const smExt = vscode.extensions.getExtension(smExtensionId);
if (!smExt) {
throw new Error("Server Manager extension not found");
}
if (!smExt.isActive) await smExt.activate();
serverManagerApi = smExt.exports;
}
connSpec = await serverManagerApi.getServerSpec(serverName);
if (!connSpec) {
throw new Error(`Failed to fetch definition of server '${serverName}'`)
}
const isUnauthenticated = (username?: string): boolean => {
return username && (username == "" || username.toLowerCase() == "unknownuser");
}
const resolvePassword = async (serverSpec): Promise<void> => {
if (
// Connection isn't unauthenticated
(!isUnauthenticated(serverSpec.username)) &&
// A password is missing
typeof serverSpec.password == "undefined"
) {
const scopes = [serverSpec.name, serverSpec.username || ""];

// Handle Server Manager extension version < 3.8.0
const account = serverManagerApi.getAccount ? serverManagerApi.getAccount(serverSpec) : undefined;

let session = await vscode.authentication.getSession(serverManager.AUTHENTICATION_PROVIDER, scopes, {
silent: true,
account,
});
if (!session) {
session = await vscode.authentication.getSession(serverManager.AUTHENTICATION_PROVIDER, scopes, {
createIfNone: true,
account,
});
}
if (session) {
// If original spec lacked username use the one obtained by the authprovider
serverSpec.username = serverSpec.username || session.scopes[1];
serverSpec.password = session.accessToken;
}
}
}

await resolvePassword(connSpec);
resolvedConnSpecs.set(serverName, connSpec);
}
connInfo = { ...connInfo,
https: connSpec.webServer.scheme === 'https',
server: connSpec.webServer.host,
port: connSpec.webServer.port,
pathPrefix: connSpec.webServer.pathPrefix || '',
username: connSpec.username,
password: connSpec.password,
namespace,
}
}
return connInfo;
},
driverAliases: DRIVER_ALIASES,
Expand Down
24 changes: 10 additions & 14 deletions src/ls/driver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,16 @@ export default class IRISDriver extends AbstractDriver<IRISdb, DriverOptions> im
this.showSystem = this.credentials.showSystem || false;
this.filter = this.credentials.filter || "";

if (this.credentials.serverName) {
throw new Error("not supported");
} else {
let { https, server: host, port, pathPrefix, username, password } = this.credentials;
config = {
https,
host,
port,
pathPrefix,
namespace,
username,
password
};
}
let { https, server: host, port, pathPrefix, username, password } = this.credentials;
config = {
https,
host,
port,
pathPrefix,
namespace,
username,
password
};

const irisdb = new IRISdb(config);
return irisdb.open()
Expand Down
Loading