6
6
*/
7
7
import { basename , dirname , extname , join } from 'path' ;
8
8
import { isString } from '@salesforce/ts-types' ;
9
+ import { create as createArchive } from 'archiver' ;
10
+ import * as fs from 'graceful-fs' ;
9
11
import { MetadataConverter } from '../convert' ;
10
12
import { ComponentLike , SourceComponent } from '../resolve' ;
11
13
import { normalizeToArray } from '../utils' ;
12
14
import { ComponentSet } from '../collections' ;
13
15
import { registry } from '../registry' ;
14
16
import { MissingJobIdError } from '../errors' ;
17
+ import { stream2buffer } from '../convert/streams' ;
15
18
import { MetadataTransfer , MetadataTransferOptions } from './metadataTransfer' ;
16
19
import {
17
20
AsyncResult ,
@@ -23,7 +26,6 @@ import {
23
26
MetadataTransferResult ,
24
27
} from './types' ;
25
28
import { DiagnosticUtil } from './diagnosticUtil' ;
26
-
27
29
export class DeployResult implements MetadataTransferResult {
28
30
public readonly response : MetadataApiDeployStatus ;
29
31
public readonly components : ComponentSet ;
@@ -208,6 +210,14 @@ export class DeployResult implements MetadataTransferResult {
208
210
209
211
export interface MetadataApiDeployOptions extends MetadataTransferOptions {
210
212
apiOptions ?: ApiOptions ;
213
+ /**
214
+ * Path to a zip file containing mdapi-formatted code and a package.xml
215
+ */
216
+ zipPath ?: string ;
217
+ /**
218
+ * Path to a directory containing mdapi-formatted code and a package.xml
219
+ */
220
+ mdapiPath ?: string ;
211
221
}
212
222
213
223
export class MetadataApiDeploy extends MetadataTransfer < MetadataApiDeployStatus , DeployResult > {
@@ -302,8 +312,7 @@ export class MetadataApiDeploy extends MetadataTransfer<MetadataApiDeployStatus,
302
312
}
303
313
304
314
protected async pre ( ) : Promise < AsyncResult > {
305
- const converter = new MetadataConverter ( ) ;
306
- const { zipBuffer } = await converter . convert ( this . components , 'metadata' , { type : 'zip' } ) ;
315
+ const zipBuffer = await this . getZipBuffer ( ) ;
307
316
const connection = await this . getConnection ( ) ;
308
317
await this . maybeSaveTempDirectory ( 'metadata' ) ;
309
318
return connection . deploy ( zipBuffer , this . options . apiOptions ) ;
@@ -313,4 +322,32 @@ export class MetadataApiDeploy extends MetadataTransfer<MetadataApiDeployStatus,
313
322
protected async post ( result : MetadataApiDeployStatus ) : Promise < DeployResult > {
314
323
return new DeployResult ( result , this . components ) ;
315
324
}
325
+
326
+ private async getZipBuffer ( ) : Promise < Buffer > {
327
+ if ( this . options . mdapiPath ) {
328
+ if ( ! fs . existsSync ( this . options . mdapiPath ) || ! fs . lstatSync ( this . options . mdapiPath ) . isDirectory ( ) ) {
329
+ throw new Error ( `Deploy directory ${ this . options . mdapiPath } does not exist or is not a directory` ) ;
330
+ }
331
+ // make a zip from the given directory
332
+ const zip = createArchive ( 'zip' , { zlib : { level : 9 } } ) ;
333
+ // anywhere not at the root level is fine
334
+ zip . directory ( this . options . mdapiPath , 'zip' ) ;
335
+ await zip . finalize ( ) ;
336
+ return stream2buffer ( zip ) ;
337
+ }
338
+ // read the zip into a buffer
339
+ if ( this . options . zipPath ) {
340
+ if ( ! fs . existsSync ( this . options . zipPath ) ) {
341
+ throw new Error ( `Zip file ${ this . options . zipPath } does not exist` ) ;
342
+ }
343
+ // does encoding matter for zip files? I don't know
344
+ return fs . promises . readFile ( this . options . zipPath ) ;
345
+ }
346
+ if ( this . options . components ) {
347
+ const converter = new MetadataConverter ( ) ;
348
+ const { zipBuffer } = await converter . convert ( this . components , 'metadata' , { type : 'zip' } ) ;
349
+ return zipBuffer ;
350
+ }
351
+ throw new Error ( 'Options should include components, zipPath, or mdapiPath' ) ;
352
+ }
316
353
}
0 commit comments