@@ -39,13 +39,68 @@ export class ConnectionConfig implements IConnectionConfig {
3939 void this . initialize ( ) ;
4040 }
4141
42+ public getUserConnectionsGroup ( ) : IConnectionGroup | undefined {
43+ const rootGroup = this . getRootGroup ( ) ;
44+ if ( ! rootGroup ) return undefined ;
45+ const groups = this . getGroupsFromSettings ( ) ;
46+ return groups . find ( ( g ) => g . name === "User Connections" && g . parentId === rootGroup . id ) ;
47+ }
48+
49+ public getWorkspaceConnectionsGroup ( ) : IConnectionGroup | undefined {
50+ const rootGroup = this . getRootGroup ( ) ;
51+ if ( ! rootGroup ) return undefined ;
52+ const groups = this . getGroupsFromSettings ( ) ;
53+ return groups . find (
54+ ( g ) => g . name === "Workspace Connections" && g . parentId === rootGroup . id ,
55+ ) ;
56+ }
57+
58+ public getUserConnectionsGroupId ( ) : string | undefined {
59+ const group = this . getUserConnectionsGroup ( ) ;
60+ return group ?. id ;
61+ }
62+
63+ public getWorkspaceConnectionsGroupId ( ) : string | undefined {
64+ const group = this . getWorkspaceConnectionsGroup ( ) ;
65+ return group ?. id ;
66+ }
67+
4268 private async initialize ( ) : Promise < void > {
69+ // Ensure workspace arrays exist
70+ await this . ensureWorkspaceArraysInitialized ( ) ;
4371 await this . assignConnectionGroupMissingIds ( ) ;
4472 await this . assignConnectionMissingIds ( ) ;
4573
4674 this . initialized . resolve ( ) ;
4775 }
4876
77+ private async ensureWorkspaceArraysInitialized ( ) : Promise < void > {
78+ const workspaceGroups = this . getGroupsFromSettings ( ConfigurationTarget . Workspace ) ;
79+ const workspaceConnections = this . getConnectionsFromSettings ( ConfigurationTarget . Workspace ) ;
80+ let changed = false ;
81+ if ( ! workspaceGroups || workspaceGroups . length === 0 ) {
82+ await this . _vscodeWrapper . setConfiguration (
83+ Constants . extensionName ,
84+ Constants . connectionGroupsArrayName ,
85+ [ ] ,
86+ ConfigurationTarget . Workspace ,
87+ ) ;
88+ changed = true ;
89+ }
90+ if ( ! workspaceConnections || workspaceConnections . length === 0 ) {
91+ await this . _vscodeWrapper . setConfiguration (
92+ Constants . extensionName ,
93+ Constants . connectionsArrayName ,
94+ [ ] ,
95+ ConfigurationTarget . Workspace ,
96+ ) ;
97+ changed = true ;
98+ }
99+ if ( changed ) {
100+ this . _logger . logDebug ( "Initialized workspace arrays for connections and groups." ) ;
101+ }
102+ }
103+
49104 //#region Connection Profiles
50105
51106 /**
@@ -139,18 +194,26 @@ export class ConnectionConfig implements IConnectionConfig {
139194 return profiles . find ( ( profile ) => profile . id === id ) ;
140195 }
141196
142- public async addConnection ( profile : IConnectionProfile ) : Promise < void > {
197+ public async addConnection (
198+ profile : IConnectionProfile ,
199+ target : ConfigTarget = ConfigurationTarget . Global ,
200+ ) : Promise < void > {
143201 this . populateMissingConnectionIds ( profile ) ;
144202
145- let profiles = await this . getConnections ( false /* getWorkspaceConnections */ ) ;
203+ // If the group is Workspace Connections, always use workspace settings
204+ const workspaceGroupId = this . getWorkspaceConnectionsGroupId ( ) ;
205+ if ( profile . groupId === workspaceGroupId ) {
206+ target = ConfigurationTarget . Workspace ;
207+ }
208+
209+ let profiles = this . getConnectionsFromSettings ( target ) ;
146210
147211 // Remove the profile if already set
148212 profiles = profiles . filter ( ( value ) => ! Utils . isSameProfile ( value , profile ) ) ;
149213 profiles . push ( profile ) ;
150214
151- return await this . writeConnectionsToSettings ( profiles ) ;
215+ return await this . writeConnectionsToSettings ( profiles , target ) ;
152216 }
153-
154217 /**
155218 * Remove an existing connection from the connection config if it exists.
156219 * @returns true if the connection was removed, false if the connection wasn't found.
@@ -166,13 +229,25 @@ export class ConnectionConfig implements IConnectionConfig {
166229 }
167230
168231 public async updateConnection ( updatedProfile : IConnectionProfile ) : Promise < void > {
169- const profiles = await this . getConnections ( false /* getWorkspaceConnections */ ) ;
232+ return this . updateConnectionWithTarget ( updatedProfile , ConfigurationTarget . Global ) ;
233+ }
234+
235+ public async updateConnectionWithTarget (
236+ updatedProfile : IConnectionProfile ,
237+ target : ConfigTarget ,
238+ ) : Promise < void > {
239+ // If the group is Workspace Connections, always use workspace settings
240+ const workspaceGroupId = this . getWorkspaceConnectionsGroupId ( ) ;
241+ if ( updatedProfile . groupId === workspaceGroupId ) {
242+ target = ConfigurationTarget . Workspace ;
243+ }
244+ const profiles = this . getConnectionsFromSettings ( target ) ;
170245 const index = profiles . findIndex ( ( p ) => p . id === updatedProfile . id ) ;
171246 if ( index === - 1 ) {
172247 throw new Error ( `Connection with ID ${ updatedProfile . id } not found` ) ;
173248 }
174249 profiles [ index ] = updatedProfile ;
175- await this . writeConnectionsToSettings ( profiles ) ;
250+ await this . writeConnectionsToSettings ( profiles , target ) ;
176251 }
177252
178253 //#endregion
@@ -219,13 +294,20 @@ export class ConnectionConfig implements IConnectionConfig {
219294 group . id = Utils . generateGuid ( ) ;
220295 }
221296
297+ // If this is Workspace Connections or a child, use workspace settings
298+ const workspaceGroupId = this . getWorkspaceConnectionsGroupId ( ) ;
299+ let target : ConfigTarget = ConfigurationTarget . Global ;
300+ if ( group . parentId === workspaceGroupId || group . id === workspaceGroupId ) {
301+ target = ConfigurationTarget . Workspace ;
302+ }
303+
222304 if ( ! group . parentId ) {
223- group . parentId = this . getRootGroup ( ) . id ;
305+ group . parentId = this . getUserConnectionsGroupId ( ) ;
224306 }
225307
226- const groups = this . getGroupsFromSettings ( ) ;
308+ const groups = this . getGroupsFromSettings ( target ) ;
227309 groups . push ( group ) ;
228- return this . writeConnectionGroupsToSettings ( groups ) ;
310+ return this . writeConnectionGroupsToSettingsWithTarget ( groups , target ) ;
229311 }
230312
231313 /**
@@ -283,28 +365,29 @@ export class ConnectionConfig implements IConnectionConfig {
283365 // Remove all groups that were marked for removal
284366 remainingGroups = groups . filter ( ( g ) => ! groupsToRemove . has ( g . id ) ) ;
285367 } else {
286- // Move immediate child connections to root
368+ // Move immediate child connections and groups to User Connections group
369+ const userGroupId = this . getUserConnectionsGroupId ( ) ;
287370 remainingConnections = connections . map ( ( conn ) => {
288371 if ( conn . groupId === id ) {
289372 this . _logger . verbose (
290- `Moving connection '${ conn . id } ' to root group because its immediate parent group '${ id } ' was removed` ,
373+ `Moving connection '${ conn . id } ' to User Connections group because its immediate parent group '${ id } ' was removed` ,
291374 ) ;
292375 connectionModified = true ;
293- return { ...conn , groupId : rootGroup . id } ;
376+ return { ...conn , groupId : userGroupId } ;
294377 }
295378 return conn ;
296379 } ) ;
297380
298381 // First remove the target group
299382 remainingGroups = groups . filter ( ( g ) => g . id !== id ) ;
300383
301- // Then reparent immediate children to root
384+ // Then reparent immediate children to User Connections group
302385 remainingGroups = remainingGroups . map ( ( g ) => {
303386 if ( g . parentId === id ) {
304387 this . _logger . verbose (
305- `Moving group '${ g . id } ' to root group because its immediate parent group '${ id } ' was removed` ,
388+ `Moving group '${ g . id } ' to User Connections group because its immediate parent group '${ id } ' was removed` ,
306389 ) ;
307- return { ...g , parentId : rootGroup . id } ;
390+ return { ...g , parentId : userGroupId } ;
308391 }
309392 return g ;
310393 } ) ;
@@ -324,15 +407,27 @@ export class ConnectionConfig implements IConnectionConfig {
324407 }
325408
326409 public async updateGroup ( updatedGroup : IConnectionGroup ) : Promise < void > {
327- const groups = this . getGroupsFromSettings ( ) ;
410+ return this . updateGroupWithTarget ( updatedGroup , ConfigurationTarget . Global ) ;
411+ }
412+
413+ public async updateGroupWithTarget (
414+ updatedGroup : IConnectionGroup ,
415+ target : ConfigTarget ,
416+ ) : Promise < void > {
417+ // If this is Workspace Connections or a child, use workspace settings
418+ const workspaceGroupId = this . getWorkspaceConnectionsGroupId ( ) ;
419+ if ( updatedGroup . parentId === workspaceGroupId || updatedGroup . id === workspaceGroupId ) {
420+ target = ConfigurationTarget . Workspace ;
421+ }
422+ const groups = this . getGroupsFromSettings ( target ) ;
328423 const index = groups . findIndex ( ( g ) => g . id === updatedGroup . id ) ;
329424 if ( index === - 1 ) {
330425 throw Error ( `Connection group with ID ${ updatedGroup . id } not found when updating` ) ;
331426 } else {
332427 groups [ index ] = updatedGroup ;
333428 }
334429
335- return await this . writeConnectionGroupsToSettings ( groups ) ;
430+ return await this . writeConnectionGroupsToSettingsWithTarget ( groups , target ) ;
336431 }
337432
338433 //#endregion
@@ -378,9 +473,9 @@ export class ConnectionConfig implements IConnectionConfig {
378473
379474 // ensure each profile is in a group
380475 if ( profile . groupId === undefined ) {
381- const rootGroup = this . getRootGroup ( ) ;
382- if ( rootGroup ) {
383- profile . groupId = rootGroup . id ;
476+ const userGroupId = this . getUserConnectionsGroupId ( ) ;
477+ if ( userGroupId ) {
478+ profile . groupId = userGroupId ;
384479 modified = true ;
385480 }
386481 }
@@ -401,39 +496,71 @@ export class ConnectionConfig implements IConnectionConfig {
401496 private async assignConnectionGroupMissingIds ( ) : Promise < void > {
402497 let madeChanges = false ;
403498 const groups : IConnectionGroup [ ] = this . getGroupsFromSettings ( ) ;
499+ let connections : IConnectionProfile [ ] = this . getConnectionsFromSettings ( ) ;
404500
405501 // ensure ROOT group exists
406502 let rootGroup = await this . getRootGroup ( ) ;
407-
408503 if ( ! rootGroup ) {
409504 rootGroup = {
410505 name : ConnectionConfig . RootGroupName ,
411506 id : Utils . generateGuid ( ) ,
412507 } ;
413-
414508 this . _logger . logDebug ( `Adding missing ROOT group to connection groups` ) ;
415509 madeChanges = true ;
416510 groups . push ( rootGroup ) ;
417511 }
418512
419- // Clean up connection groups
420- for ( const group of groups ) {
421- if ( group . id === rootGroup . id ) {
422- continue ;
423- }
513+ // Check for User Connections and Workspace Connections under ROOT
514+ let userConnectionsGroup = groups . find (
515+ ( g ) => g . name === "User Connections" && g . parentId === rootGroup . id ,
516+ ) ;
517+ let workspaceConnectionsGroup = groups . find (
518+ ( g ) => g . name === "Workspace Connections" && g . parentId === rootGroup . id ,
519+ ) ;
424520
425- // ensure each group has an ID
426- if ( ! group . id ) {
427- group . id = Utils . generateGuid ( ) ;
521+ if ( ! userConnectionsGroup ) {
522+ userConnectionsGroup = {
523+ name : "User Connections" ,
524+ id : Utils . generateGuid ( ) ,
525+ parentId : rootGroup . id ,
526+ } ;
527+ groups . push ( userConnectionsGroup ) ;
528+ madeChanges = true ;
529+ this . _logger . logDebug ( `Created 'User Connections' group under ROOT` ) ;
530+ }
531+ if ( ! workspaceConnectionsGroup ) {
532+ workspaceConnectionsGroup = {
533+ name : "Workspace Connections" ,
534+ id : Utils . generateGuid ( ) ,
535+ parentId : rootGroup . id ,
536+ } ;
537+ groups . push ( workspaceConnectionsGroup ) ;
538+ madeChanges = true ;
539+ this . _logger . logDebug ( `Created 'Workspace Connections' group under ROOT` ) ;
540+ }
541+
542+ // Reparent all groups directly under ROOT (except the two new groups) to User Connections
543+ for ( const group of groups ) {
544+ if (
545+ group . parentId === rootGroup . id &&
546+ group . id !== userConnectionsGroup . id &&
547+ group . id !== workspaceConnectionsGroup . id
548+ ) {
549+ group . parentId = userConnectionsGroup . id ;
428550 madeChanges = true ;
429- this . _logger . logDebug ( `Adding missing ID to connection group '${ group . name } '` ) ;
551+ this . _logger . logDebug ( `Reparented group '${ group . name } ' to 'User Connections '` ) ;
430552 }
553+ }
431554
432- // ensure each group is in a group
433- if ( ! group . parentId ) {
434- group . parentId = rootGroup . id ;
555+ // Reparent all connections directly under ROOT to User Connections
556+ for ( const conn of connections ) {
557+ // If connection is under ROOT or has no group, move to User Connections
558+ if ( ! conn . groupId || conn . groupId === rootGroup . id ) {
559+ conn . groupId = userConnectionsGroup . id ;
435560 madeChanges = true ;
436- this . _logger . logDebug ( `Adding missing parentId to connection '${ group . name } '` ) ;
561+ this . _logger . logDebug (
562+ `Reparented connection '${ getConnectionDisplayName ( conn ) } ' to 'User Connections'` ,
563+ ) ;
437564 }
438565 }
439566
@@ -442,8 +569,8 @@ export class ConnectionConfig implements IConnectionConfig {
442569 this . _logger . logDebug (
443570 `Updates made to connection groups. Writing all ${ groups . length } group(s) to settings.` ,
444571 ) ;
445-
446572 await this . writeConnectionGroupsToSettings ( groups ) ;
573+ await this . writeConnectionsToSettings ( connections ) ;
447574 }
448575 }
449576
@@ -504,20 +631,34 @@ export class ConnectionConfig implements IConnectionConfig {
504631 * Replace existing profiles in the user settings with a new set of profiles.
505632 * @param profiles the set of profiles to insert into the settings file.
506633 */
507- private async writeConnectionsToSettings ( profiles : IConnectionProfile [ ] ) : Promise < void > {
508- // Save the file
634+ private async writeConnectionsToSettings (
635+ profiles : IConnectionProfile [ ] ,
636+ target : ConfigTarget = ConfigurationTarget . Global ,
637+ ) : Promise < void > {
509638 await this . _vscodeWrapper . setConfiguration (
510639 Constants . extensionName ,
511640 Constants . connectionsArrayName ,
512641 profiles ,
642+ target ,
513643 ) ;
514644 }
515645
516646 private async writeConnectionGroupsToSettings ( connGroups : IConnectionGroup [ ] ) : Promise < void > {
647+ return this . writeConnectionGroupsToSettingsWithTarget (
648+ connGroups ,
649+ ConfigurationTarget . Global ,
650+ ) ;
651+ }
652+
653+ private async writeConnectionGroupsToSettingsWithTarget (
654+ connGroups : IConnectionGroup [ ] ,
655+ target : ConfigTarget ,
656+ ) : Promise < void > {
517657 await this . _vscodeWrapper . setConfiguration (
518658 Constants . extensionName ,
519659 Constants . connectionGroupsArrayName ,
520660 connGroups ,
661+ target ,
521662 ) ;
522663 }
523664
0 commit comments