@@ -9,8 +9,8 @@ import * as fs from 'fs';
9
9
import { confirm } from 'cli-ux/lib/prompt' ;
10
10
import { flags , FlagsConfig } from '@salesforce/command' ;
11
11
import { 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' ;
14
14
import { getString } from '@salesforce/ts-types' ;
15
15
import { DeployCommand } from '../../../deployCommand' ;
16
16
import { ComponentSetBuilder } from '../../../componentSetBuilder' ;
@@ -72,10 +72,10 @@ export class Delete extends DeployCommand {
72
72
} ;
73
73
protected xorFlags = [ 'metadata' , 'sourcepath' ] ;
74
74
protected readonly lifecycleEventNames = [ 'predeploy' , 'postdeploy' ] ;
75
- private sourceComponents : SourceComponent [ ] ;
76
75
private isRest = false ;
77
76
private deleteResultFormatter : DeleteResultFormatter ;
78
77
private aborted = false ;
78
+ private components : MetadataComponent [ ] ;
79
79
80
80
private updateDeployId = once ( ( id ) => {
81
81
this . displayDeployId ( id ) ;
@@ -107,26 +107,31 @@ export class Delete extends DeployCommand {
107
107
} ,
108
108
} ) ;
109
109
110
- this . sourceComponents = this . componentSet . getSourceComponents ( ) . toArray ( ) ;
110
+ this . components = this . componentSet . toArray ( ) ;
111
111
112
- if ( ! this . sourceComponents . length ) {
112
+ if ( ! this . components . length ) {
113
113
// if we didn't find any components to delete, let the user know and exit
114
114
this . deleteResultFormatter . displayNoResultsFound ( ) ;
115
115
return ;
116
116
}
117
117
118
118
// create a new ComponentSet and mark everything for deletion
119
119
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
+ }
122
127
} ) ;
123
128
this . componentSet = cs ;
124
129
125
130
this . aborted = ! ( await this . handlePrompt ( ) ) ;
126
131
if ( this . aborted ) return ;
127
132
128
133
// fire predeploy event for the delete
129
- await this . lifecycle . emit ( 'predeploy' , this . componentSet . toArray ( ) ) ;
134
+ await this . lifecycle . emit ( 'predeploy' , this . components ) ;
130
135
this . isRest = await this . isRestDeploy ( ) ;
131
136
this . ux . log ( `*** Deleting with ${ this . isRest ? 'REST' : 'SOAP' } API ***` ) ;
132
137
@@ -178,7 +183,7 @@ export class Delete extends DeployCommand {
178
183
179
184
private deleteFilesLocally ( ) : void {
180
185
if ( ! this . getFlag ( 'checkonly' ) && getString ( this . deployResult , 'response.status' ) === 'Succeeded' ) {
181
- this . sourceComponents . map ( ( component ) => {
186
+ this . components . map ( ( component : SourceComponent ) => {
182
187
// delete the content and/or the xml of the components
183
188
if ( component . content ) {
184
189
const stats = fs . lstatSync ( component . content ) ;
@@ -188,8 +193,7 @@ export class Delete extends DeployCommand {
188
193
fs . unlinkSync ( component . content ) ;
189
194
}
190
195
}
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 ) {
193
197
fs . unlinkSync ( component . xml ) ;
194
198
}
195
199
} ) ;
@@ -198,10 +202,33 @@ export class Delete extends DeployCommand {
198
202
199
203
private async handlePrompt ( ) : Promise < boolean > {
200
204
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
+ }
203
229
204
- return confirm ( promptMessage ) ;
230
+ message . push ( messages . getMessage ( 'areYouSure' ) ) ;
231
+ return confirm ( message . join ( '' ) ) ;
205
232
}
206
233
return true ;
207
234
}
0 commit comments