@@ -9,8 +9,8 @@ import * as fs from 'fs';
99import { confirm } from 'cli-ux/lib/prompt' ;
1010import { flags , FlagsConfig } from '@salesforce/command' ;
1111import { Messages } from '@salesforce/core' ;
12- import { ComponentSet , RequestStatus , SourceComponent } from '@salesforce/source-deploy-retrieve' ;
13- import { Duration , once , env } from '@salesforce/kit' ;
12+ import { ComponentSet , MetadataComponent , RequestStatus , SourceComponent } from '@salesforce/source-deploy-retrieve' ;
13+ import { Duration , env , once } from '@salesforce/kit' ;
1414import { getString } from '@salesforce/ts-types' ;
1515import { DeployCommand } from '../../../deployCommand' ;
1616import { ComponentSetBuilder } from '../../../componentSetBuilder' ;
@@ -72,10 +72,10 @@ export class Delete extends DeployCommand {
7272 } ;
7373 protected xorFlags = [ 'metadata' , 'sourcepath' ] ;
7474 protected readonly lifecycleEventNames = [ 'predeploy' , 'postdeploy' ] ;
75- private sourceComponents : SourceComponent [ ] ;
7675 private isRest = false ;
7776 private deleteResultFormatter : DeleteResultFormatter ;
7877 private aborted = false ;
78+ private components : MetadataComponent [ ] ;
7979
8080 private updateDeployId = once ( ( id ) => {
8181 this . displayDeployId ( id ) ;
@@ -107,26 +107,31 @@ export class Delete extends DeployCommand {
107107 } ,
108108 } ) ;
109109
110- this . sourceComponents = this . componentSet . getSourceComponents ( ) . toArray ( ) ;
110+ this . components = this . componentSet . toArray ( ) ;
111111
112- if ( ! this . sourceComponents . length ) {
112+ if ( ! this . components . length ) {
113113 // if we didn't find any components to delete, let the user know and exit
114114 this . deleteResultFormatter . displayNoResultsFound ( ) ;
115115 return ;
116116 }
117117
118118 // create a new ComponentSet and mark everything for deletion
119119 const cs = new ComponentSet ( [ ] ) ;
120- this . sourceComponents . map ( ( component ) => {
121- cs . add ( component , true ) ;
120+ this . components . map ( ( component ) => {
121+ if ( component instanceof SourceComponent ) {
122+ cs . add ( component , true ) ;
123+ } else {
124+ // a remote-only delete
125+ cs . add ( new SourceComponent ( { name : component . fullName , type : component . type } ) , true ) ;
126+ }
122127 } ) ;
123128 this . componentSet = cs ;
124129
125130 this . aborted = ! ( await this . handlePrompt ( ) ) ;
126131 if ( this . aborted ) return ;
127132
128133 // fire predeploy event for the delete
129- await this . lifecycle . emit ( 'predeploy' , this . componentSet . toArray ( ) ) ;
134+ await this . lifecycle . emit ( 'predeploy' , this . components ) ;
130135 this . isRest = await this . isRestDeploy ( ) ;
131136 this . ux . log ( `*** Deleting with ${ this . isRest ? 'REST' : 'SOAP' } API ***` ) ;
132137
@@ -178,7 +183,7 @@ export class Delete extends DeployCommand {
178183
179184 private deleteFilesLocally ( ) : void {
180185 if ( ! this . getFlag ( 'checkonly' ) && getString ( this . deployResult , 'response.status' ) === 'Succeeded' ) {
181- this . sourceComponents . map ( ( component ) => {
186+ this . components . map ( ( component : SourceComponent ) => {
182187 // delete the content and/or the xml of the components
183188 if ( component . content ) {
184189 const stats = fs . lstatSync ( component . content ) ;
@@ -188,8 +193,7 @@ export class Delete extends DeployCommand {
188193 fs . unlinkSync ( component . content ) ;
189194 }
190195 }
191- // the xml could've been deleted as part of a bundle type above
192- if ( component . xml && fs . existsSync ( component . xml ) ) {
196+ if ( component . xml ) {
193197 fs . unlinkSync ( component . xml ) ;
194198 }
195199 } ) ;
@@ -198,10 +202,33 @@ export class Delete extends DeployCommand {
198202
199203 private async handlePrompt ( ) : Promise < boolean > {
200204 if ( ! this . getFlag ( 'noprompt' ) ) {
201- const paths = this . sourceComponents . flatMap ( ( component ) => [ component . xml , ...component . walkContent ( ) ] ) ;
202- const promptMessage = messages . getMessage ( 'prompt' , [ [ ...new Set ( paths ) ] . join ( '\n' ) ] ) ;
205+ const remote : string [ ] = [ ] ;
206+ const local : string [ ] = [ ] ;
207+ const message : string [ ] = [ ] ;
208+
209+ this . components . flatMap ( ( component ) => {
210+ if ( component instanceof SourceComponent ) {
211+ local . push ( component . xml , ...component . walkContent ( ) ) ;
212+ } else {
213+ // remote only metadata
214+ remote . push ( `${ component . type . name } :${ component . fullName } ` ) ;
215+ }
216+ } ) ;
217+
218+ if ( remote . length ) {
219+ message . push ( messages . getMessage ( 'remotePrompt' , [ [ ...new Set ( remote ) ] . join ( '\n' ) ] ) ) ;
220+ }
221+
222+ if ( local . length ) {
223+ if ( message . length ) {
224+ // add a whitespace between remote and local
225+ message . push ( '\n' ) ;
226+ }
227+ message . push ( '\n' , messages . getMessage ( 'localPrompt' , [ [ ...new Set ( local ) ] . join ( '\n' ) ] ) ) ;
228+ }
203229
204- return confirm ( promptMessage ) ;
230+ message . push ( messages . getMessage ( 'areYouSure' ) ) ;
231+ return confirm ( message . join ( '' ) ) ;
205232 }
206233 return true ;
207234 }
0 commit comments