88import { Flags , loglevel , SfCommand } from '@salesforce/sf-plugins-core' ;
99import { AuthInfo , ConfigAggregator , ConfigInfo , Connection , Org , SfError , Messages , Logger } from '@salesforce/core' ;
1010import { Interfaces } from '@oclif/core' ;
11+ import * as chalk from 'chalk' ;
1112import { OrgListUtil , identifyActiveOrgByStatus } from '../../shared/orgListUtil' ;
1213import { getStyledObject } from '../../shared/orgHighlighter' ;
1314import { ExtendedAuthFields , FullyPopulatedScratchOrgFields } from '../../shared/orgTypes' ;
@@ -89,13 +90,15 @@ export class OrgListCommand extends SfCommand<OrgListResult> {
8990 : groupedSortedOrgs . scratchOrgs . filter ( identifyActiveOrgByStatus ) ,
9091 } ;
9192
92- // this.printOrgTable(result.nonScratchOrgs, flags['skip-connection-status']);
93- this . printOrgTable ( result . devHubs , flags [ 'skip-connection-status' ] , 'DevHubs' ) ;
94- this . printOrgTable ( result . regularOrgs , flags [ 'skip-connection-status' ] , 'Orgs' ) ;
95- this . printOrgTable ( result . sandboxes , flags [ 'skip-connection-status' ] , 'Sandboxes' ) ;
96-
93+ this . printOrgTable ( {
94+ devHubs : result . devHubs ,
95+ regularOrgs : result . regularOrgs ,
96+ sandboxes : result . sandboxes ,
97+ skipconnectionstatus : flags [ 'skip-connection-status' ] ,
98+ } ) ;
9799 this . printScratchOrgTable ( result . scratchOrgs ) ;
98100
101+ this . info ( 'Legend: (D)=Default DevHub, (U)=Default Org' ) ;
99102 return result ;
100103 }
101104
@@ -128,35 +131,61 @@ export class OrgListCommand extends SfCommand<OrgListResult> {
128131 ) ;
129132 }
130133
131- protected printOrgTable ( nonScratchOrgs : ExtendedAuthFields [ ] , skipconnectionstatus : boolean , title : string ) : void {
132- if ( ! nonScratchOrgs . length ) {
133- this . info ( messages . getMessage ( 'noResultsFound' , [ title ] ) ) ;
134- } else {
135- this . info ( title ) ;
136- const rows = nonScratchOrgs
137- . map ( ( row ) => getStyledObject ( row ) )
138- . map ( ( org ) =>
139- Object . fromEntries (
140- Object . entries ( org ) . filter ( ( [ key ] ) =>
141- [ 'defaultMarker' , 'alias' , 'username' , 'orgId' , 'connectedStatus' ] . includes ( key )
142- )
143- )
144- ) ;
134+ protected printOrgTable ( {
135+ devHubs,
136+ regularOrgs,
137+ sandboxes,
138+ skipconnectionstatus,
139+ } : {
140+ devHubs : ExtendedAuthFields [ ] ;
141+ regularOrgs : ExtendedAuthFields [ ] ;
142+ sandboxes : ExtendedAuthFields [ ] ;
143+ skipconnectionstatus : boolean ;
144+ } ) : void {
145+ if ( ! devHubs . length && ! regularOrgs . length && ! sandboxes . length ) {
146+ this . info ( messages . getMessage ( 'noResultsFound' ) ) ;
147+ return ;
148+ }
149+ this . log ( ) ;
150+ this . info ( 'Non-scratch orgs' ) ;
151+ const nonScratchOrgs = [
152+ ...devHubs
153+ . map ( addType ( 'DevHub' ) )
154+ . map ( colorEveryFieldButConnectedStatus ( chalk . cyanBright ) )
155+ . map ( ( row ) => getStyledObject ( row ) ) ,
145156
146- this . table ( rows , {
157+ ...regularOrgs . map ( colorEveryFieldButConnectedStatus ( chalk . magentaBright ) ) . map ( ( row ) => getStyledObject ( row ) ) ,
158+
159+ ...sandboxes
160+ . map ( addType ( 'Sandbox' ) )
161+ . map ( colorEveryFieldButConnectedStatus ( chalk . yellowBright ) )
162+ . map ( ( row ) => getStyledObject ( row ) ) ,
163+ ] ;
164+
165+ this . table (
166+ nonScratchOrgs . map ( ( org ) =>
167+ Object . fromEntries (
168+ Object . entries ( org ) . filter ( ( [ key ] ) =>
169+ [ 'type' , 'defaultMarker' , 'alias' , 'username' , 'orgId' , 'connectedStatus' ] . includes ( key )
170+ )
171+ )
172+ ) ,
173+ {
147174 defaultMarker : {
148175 header : '' ,
149- get : ( data ) : string => data . defaultMarker ?? '' ,
176+ } ,
177+ type : {
178+ header : 'Type' ,
150179 } ,
151180 alias : {
152- header : 'ALIAS' ,
153- get : ( data ) : string => data . alias ?? '' ,
181+ header : 'Alias' ,
154182 } ,
155- username : { header : 'USERNAME' } ,
156- orgId : { header : 'ORG ID' } ,
157- ...( ! skipconnectionstatus ? { connectedStatus : { header : 'CONNECTED STATUS' } } : { } ) ,
158- } ) ;
159- }
183+ username : { header : 'Username' } ,
184+ orgId : { header : 'Org ID' } ,
185+ ...( ! skipconnectionstatus ? { connectedStatus : { header : 'Status' } } : { } ) ,
186+ }
187+ ) ;
188+
160189 this . log ( ) ;
161190 }
162191
@@ -165,54 +194,31 @@ export class OrgListCommand extends SfCommand<OrgListResult> {
165194 this . info ( messages . getMessage ( 'noActiveScratchOrgs' ) ) ;
166195 } else {
167196 this . info ( this . flags . all ? 'Scratch Orgs' : 'Active Scratch Orgs (use --all to see all)' ) ;
197+
168198 // One or more rows are available.
169199 // we only need a few of the props for our table. Oclif table doesn't like extra props non-string props.
170200 const rows = scratchOrgs
171201 . map ( getStyledObject )
172- . map ( ( org ) =>
173- Object . fromEntries (
174- Object . entries ( org ) . filter ( ( [ key ] ) =>
175- [
176- 'defaultMarker' ,
177- 'alias' ,
178- 'username' ,
179- 'orgId' ,
180- 'status' ,
181- 'expirationDate' ,
182- 'devHubOrgId' ,
183- 'createdDate' ,
184- 'instanceUrl' ,
185- ] . includes ( key )
186- )
187- )
188- ) ;
189- this . table (
190- rows ,
191- {
192- defaultMarker : {
193- header : '' ,
194- get : ( data ) : string => data . defaultMarker ?? '' ,
195- } ,
196- alias : {
197- header : 'ALIAS' ,
198- get : ( data ) : string => data . alias ?? '' ,
199- } ,
200- username : { header : 'USERNAME' } ,
201- orgId : { header : 'ORG ID' } ,
202- ...( this . flags . all || this . flags . verbose ? { status : { header : 'STATUS' } } : { } ) ,
203- ...( this . flags . verbose
204- ? {
205- devHubOrgId : { header : 'DEV HUB' } ,
206- createdDate : { header : 'CREATED DATE' } ,
207- instanceUrl : { header : 'INSTANCE URL' } ,
208- }
209- : { } ) ,
210- expirationDate : { header : 'EXPIRATION DATE' } ,
211- }
212- // {
213- // title: 'Scratch orgs',
214- // }
215- ) ;
202+ . map ( ( org ) => Object . fromEntries ( Object . entries ( org ) . filter ( scratchOrgFieldFilter ) ) ) ;
203+ this . table ( rows , {
204+ defaultMarker : {
205+ header : '' ,
206+ } ,
207+ alias : {
208+ header : 'Alias' ,
209+ } ,
210+ username : { header : 'Username' } ,
211+ orgId : { header : 'Org ID' } ,
212+ ...( this . flags . all || this . flags . verbose ? { status : { header : 'Status' } } : { } ) ,
213+ ...( this . flags . verbose
214+ ? {
215+ devHubOrgId : { header : 'Dev Hub ID' } ,
216+ instanceUrl : { header : 'Instance URL' } ,
217+ createdDate : { header : 'Created' , get : ( data ) : string => data . createdDate ?. split ( 'T' ) [ 0 ] ?? '' } ,
218+ }
219+ : { } ) ,
220+ expirationDate : { header : 'Expires' } ,
221+ } ) ;
216222 }
217223 this . log ( ) ;
218224 }
@@ -226,8 +232,9 @@ const decorateWithDefaultStatus = <T extends ExtendedAuthFields | FullyPopulated
226232
227233// sort by alias then username
228234const comparator = < T extends ExtendedAuthFields | FullyPopulatedScratchOrgFields > ( a : T , b : T ) : number => {
229- const aliasCompareResult = ( a . alias ?? '' ) . localeCompare ( b . alias ?? '' ) ;
230- return aliasCompareResult !== 0 ? aliasCompareResult : ( a . username ?? '' ) . localeCompare ( b . username ) ;
235+ const emptiesLast = Array ( 10 ) . fill ( 'z' ) . join ( '' ) ;
236+ const aliasCompareResult = ( a . alias ?? emptiesLast ) . localeCompare ( b . alias ?? emptiesLast ) ;
237+ return aliasCompareResult !== 0 ? aliasCompareResult : ( a . username ?? emptiesLast ) . localeCompare ( b . username ) ;
231238} ;
232239
233240const getAuthFileNames = async ( ) : Promise < string [ ] > => {
@@ -242,3 +249,32 @@ const getAuthFileNames = async (): Promise<string[]> => {
242249 }
243250 }
244251} ;
252+
253+ type ExtendedAuthFieldsWithType = ExtendedAuthFields & { type ?: string } ;
254+ const addType =
255+ ( type : string ) =>
256+ ( val : ExtendedAuthFields ) : ExtendedAuthFieldsWithType => ( { ...val , type } ) ;
257+
258+ const colorEveryFieldButConnectedStatus =
259+ ( colorFn : chalk . Chalk ) =>
260+ ( row : ExtendedAuthFieldsWithType ) : ExtendedAuthFieldsWithType =>
261+ Object . fromEntries (
262+ Object . entries ( row ) . map ( ( [ key , val ] ) => [
263+ key ,
264+ typeof val === 'string' && key !== 'connectedStatus' ? colorFn ( val ) : val ,
265+ ] )
266+ // TS is not smart enough to know this didn't change any types
267+ ) as ExtendedAuthFieldsWithType ;
268+
269+ const scratchOrgFieldFilter = ( [ key ] : [ string , string ] ) : boolean =>
270+ [
271+ 'defaultMarker' ,
272+ 'alias' ,
273+ 'username' ,
274+ 'orgId' ,
275+ 'status' ,
276+ 'expirationDate' ,
277+ 'devHubOrgId' ,
278+ 'createdDate' ,
279+ 'instanceUrl' ,
280+ ] . includes ( key ) ;
0 commit comments