@@ -6,6 +6,13 @@ const { publisher, name } = require('../package.json');
66// import { workspace } from 'vscode';
77// import { Uri } from 'vscode';
88// import path from 'path';
9+ import * as serverManager from "@intersystems-community/intersystems-servermanager" ;
10+
11+ const smExtensionId = "intersystems-community.servermanager" ;
12+ let serverManagerApi : serverManager . ServerManagerAPI ;
13+
14+ /** Map of the intersystems.server connection specs we have resolved via the API to that extension */
15+ const resolvedConnSpecs = new Map < string , serverManager . IServerSpec > ( ) ;
916
1017const driverName = 'InterSystems IRIS Driver' ;
1118
@@ -45,35 +52,113 @@ export async function activate(extContext: ExtensionContext): Promise<IDriverExt
4552 driverName,
4653 parseBeforeSaveConnection : ( { connInfo } ) => {
4754 /**
48- * This hook is called before saving the connecton using the assistant
49- * so you can do any transformations before saving it to disk.active
50- * EG: relative file path transformation, string manipulation etc
51- * Below is the exmaple for SQLite, where we save the DB path relative to workspace
52- * and later we transform it back to absolute before editing
55+ * This hook is called before saving the connection using the assistant
56+ * so you can do any transformations before saving it
5357 */
54- // if (path.isAbsolute(connInfo.database)) {
55- // const databaseUri = Uri.file(connInfo.database);
56- // const dbWorkspace = workspace.getWorkspaceFolder(databaseUri);
57- // if (dbWorkspace) {
58- // connInfo.database = `\$\{workspaceFolder:${dbWorkspace.name}\}/${workspace.asRelativePath(connInfo.database, false)}`;
59- // }
60- // }
58+ if ( connInfo . connectionMethod === 'Server Definition' ) {
59+ // Transform to a connectString property
60+ connInfo . connectString = `${ connInfo . serverName } :${ connInfo . namespace } ` ;
61+ connInfo . serverName = undefined ;
62+ connInfo . namespace = undefined ;
63+ // Remove properties carried over from 'Server and Port' type connection
64+ connInfo . server = undefined ;
65+ connInfo . port = undefined ;
66+ connInfo . pathPrefix = undefined ;
67+ connInfo . https = undefined ;
68+ connInfo . askForPassword = undefined ;
69+ connInfo . username = undefined ;
70+ connInfo . password = undefined ;
71+
72+ }
6173 return connInfo ;
6274 } ,
6375 parseBeforeEditConnection : ( { connInfo } ) => {
6476 /**
65- * This hook is called before editing the connecton using the assistant
77+ * This hook is called before editing the connection using the assistant
6678 * so you can do any transformations before editing it.
6779 * EG: absolute file path transformation, string manipulation etc
6880 * Below is the exmaple for SQLite, where we use relative path to save,
6981 * but we transform to asolute before editing
7082 */
71- // if (!path.isAbsolute(connInfo.database) && /\$\{workspaceFolder:(.+)}/g.test(connInfo.database)) {
72- // const workspaceName = connInfo.database.match(/\$\{workspaceFolder:(.+)}/)[1];
73- // const dbWorkspace = workspace.workspaceFolders.find(w => w.name === workspaceName);
74- // if (dbWorkspace)
75- // connInfo.database = path.resolve(dbWorkspace.uri.fsPath, connInfo.database.replace(/\$\{workspaceFolder:(.+)}/g, './'));
76- // }
83+ if ( connInfo . connectionMethod === 'Server Definition' ) {
84+ const connParts = connInfo . connectString . split ( ':' ) ;
85+ connInfo . serverName = connParts [ 0 ] ;
86+ connInfo . namespace = connParts [ 1 ] ;
87+ }
88+ return connInfo ;
89+ } ,
90+ resolveConnection : async ( { connInfo } ) => {
91+ /**
92+ * This hook is called after a connection definition has been fetched
93+ * from settings and is about to be used to connect.
94+ */
95+ if ( connInfo . connectionMethod === 'Server Definition' ) {
96+ const connParts = connInfo . connectString . split ( ':' ) ;
97+ const serverName = connParts [ 0 ] ;
98+ const namespace = connParts [ 1 ] ;
99+ let connSpec = resolvedConnSpecs . get ( serverName )
100+ if ( ! connSpec ) {
101+
102+ if ( ! serverManagerApi ) {
103+
104+ // Get api for servermanager extension
105+ const smExt = vscode . extensions . getExtension ( smExtensionId ) ;
106+ if ( ! smExt ) {
107+ throw new Error ( "Server Manager extension not found" ) ;
108+ }
109+ if ( ! smExt . isActive ) await smExt . activate ( ) ;
110+ serverManagerApi = smExt . exports ;
111+ }
112+ connSpec = await serverManagerApi . getServerSpec ( serverName ) ;
113+ if ( ! connSpec ) {
114+ throw new Error ( `Failed to fetch definition of server '${ serverName } '` )
115+ }
116+ const isUnauthenticated = ( username ?: string ) : boolean => {
117+ return username && ( username == "" || username . toLowerCase ( ) == "unknownuser" ) ;
118+ }
119+ const resolvePassword = async ( serverSpec ) : Promise < void > => {
120+ if (
121+ // Connection isn't unauthenticated
122+ ( ! isUnauthenticated ( serverSpec . username ) ) &&
123+ // A password is missing
124+ typeof serverSpec . password == "undefined"
125+ ) {
126+ const scopes = [ serverSpec . name , serverSpec . username || "" ] ;
127+
128+ // Handle Server Manager extension version < 3.8.0
129+ const account = serverManagerApi . getAccount ? serverManagerApi . getAccount ( serverSpec ) : undefined ;
130+
131+ let session = await vscode . authentication . getSession ( serverManager . AUTHENTICATION_PROVIDER , scopes , {
132+ silent : true ,
133+ account,
134+ } ) ;
135+ if ( ! session ) {
136+ session = await vscode . authentication . getSession ( serverManager . AUTHENTICATION_PROVIDER , scopes , {
137+ createIfNone : true ,
138+ account,
139+ } ) ;
140+ }
141+ if ( session ) {
142+ // If original spec lacked username use the one obtained by the authprovider
143+ serverSpec . username = serverSpec . username || session . scopes [ 1 ] ;
144+ serverSpec . password = session . accessToken ;
145+ }
146+ }
147+ }
148+
149+ await resolvePassword ( connSpec ) ;
150+ resolvedConnSpecs . set ( serverName , connSpec ) ;
151+ }
152+ connInfo = { ...connInfo ,
153+ https : connSpec . webServer . scheme === 'https' ,
154+ server : connSpec . webServer . host ,
155+ port : connSpec . webServer . port ,
156+ pathPrefix : connSpec . webServer . pathPrefix || '' ,
157+ username : connSpec . username ,
158+ password : connSpec . password ,
159+ namespace,
160+ }
161+ }
77162 return connInfo ;
78163 } ,
79164 driverAliases : DRIVER_ALIASES ,
0 commit comments