@@ -6,6 +6,13 @@ const { publisher, name } = require('../package.json');
6
6
// import { workspace } from 'vscode';
7
7
// import { Uri } from 'vscode';
8
8
// 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 > ( ) ;
9
16
10
17
const driverName = 'InterSystems IRIS Driver' ;
11
18
@@ -45,35 +52,113 @@ export async function activate(extContext: ExtensionContext): Promise<IDriverExt
45
52
driverName,
46
53
parseBeforeSaveConnection : ( { connInfo } ) => {
47
54
/**
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
53
57
*/
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
+ }
61
73
return connInfo ;
62
74
} ,
63
75
parseBeforeEditConnection : ( { connInfo } ) => {
64
76
/**
65
- * This hook is called before editing the connecton using the assistant
77
+ * This hook is called before editing the connection using the assistant
66
78
* so you can do any transformations before editing it.
67
79
* EG: absolute file path transformation, string manipulation etc
68
80
* Below is the exmaple for SQLite, where we use relative path to save,
69
81
* but we transform to asolute before editing
70
82
*/
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
+ }
77
162
return connInfo ;
78
163
} ,
79
164
driverAliases : DRIVER_ALIASES ,
0 commit comments