@@ -296,7 +296,7 @@ export interface MultipartBodyOptions {
296
296
/**
297
297
* `Content-Transfer-Encoding` header specifying part encoding.
298
298
*
299
- * @default undefined - don't add this header
299
+ * @default undefined - body is not encoded
300
300
*/
301
301
readonly transferEncoding ?: string ;
302
302
@@ -312,6 +312,15 @@ export interface MultipartBodyOptions {
312
312
* The base class for all classes which can be used as {@link MultipartUserData}.
313
313
*/
314
314
export abstract class MultipartBody {
315
+ /**
316
+ * Content type for shell scripts
317
+ */
318
+ public static readonly SHELL_SCRIPT = 'text/x-shellscript; charset="utf-8"' ;
319
+
320
+ /**
321
+ * Content type for boot hooks
322
+ */
323
+ public static readonly CLOUD_BOOTHOOK = 'text/cloud-boothook; charset="utf-8"' ;
315
324
316
325
/**
317
326
* Constructs the new `MultipartBody` wrapping existing `UserData`. Modification to `UserData` are reflected
@@ -336,83 +345,72 @@ export abstract class MultipartBody {
336
345
return new MultipartBodyRaw ( opts ) ;
337
346
}
338
347
339
- protected static readonly DEFAULT_CONTENT_TYPE = 'text/x-shellscript; charset="utf-8"' ;
340
-
341
- /** The body of this MIME part. */
342
- public abstract get body ( ) : string | undefined ;
343
-
344
- /** `Content-Type` header of this part */
345
- public abstract get contentType ( ) : string ;
348
+ public constructor ( ) {
349
+ }
346
350
347
351
/**
348
- * `Content-Transfer-Encoding` header specifying part encoding .
352
+ * Render body part as the string .
349
353
*
350
- * @default undefined - don't add this header
354
+ * Subclasses should not add leading nor trailing new line characters (\r \n)
351
355
*/
352
- public abstract get transferEncoding ( ) : string | undefined ;
356
+ public abstract renderBodyPart ( ) : string [ ] ;
357
+ }
353
358
354
- public constructor ( ) {
359
+ /**
360
+ * The raw part of multi-part user data, which can be added to {@link MultipartUserData}.
361
+ */
362
+ class MultipartBodyRaw extends MultipartBody {
363
+ public constructor ( private readonly props : MultipartBodyOptions ) {
364
+ super ( ) ;
355
365
}
356
366
357
367
/**
358
368
* Render body part as the string.
359
- *
360
- * Subclasses should not add leading nor trailing new line characters (\r \n)
361
369
*/
362
- public renderBodyPart ( ) : string {
370
+ public renderBodyPart ( ) : string [ ] {
363
371
const result : string [ ] = [ ] ;
364
372
365
- result . push ( `Content-Type: ${ this . contentType } ` ) ;
373
+ result . push ( `Content-Type: ${ this . props . contentType } ` ) ;
366
374
367
- if ( this . transferEncoding != null ) {
368
- result . push ( `Content-Transfer-Encoding: ${ this . transferEncoding } ` ) ;
375
+ if ( this . props . transferEncoding != null ) {
376
+ result . push ( `Content-Transfer-Encoding: ${ this . props . transferEncoding } ` ) ;
369
377
}
370
378
// One line free after separator
371
379
result . push ( '' ) ;
372
380
373
- if ( this . body != null ) {
374
- result . push ( this . body ) ;
381
+ if ( this . props . body != null ) {
382
+ result . push ( this . props . body ) ;
375
383
// The new line added after join will be consumed by encapsulating or closing boundary
376
384
}
377
385
378
- return result . join ( '\n' ) ;
379
- }
380
- }
381
-
382
- /**
383
- * The raw part of multi-part user data, which can be added to {@link MultipartUserData}.
384
- */
385
- class MultipartBodyRaw extends MultipartBody {
386
- public readonly body : string | undefined ;
387
- public readonly contentType : string ;
388
- public readonly transferEncoding : string | undefined ;
389
-
390
- public constructor ( props : MultipartBodyOptions ) {
391
- super ( ) ;
392
-
393
- this . body = props . body ;
394
- this . contentType = props . contentType ;
386
+ return result ;
395
387
}
396
388
}
397
389
398
390
/**
399
391
* Wrapper for `UserData`.
400
392
*/
401
393
class MultipartBodyUserDataWrapper extends MultipartBody {
394
+ private readonly contentType : string ;
402
395
403
- public readonly contentType : string ;
404
- public readonly transferEncoding : string | undefined ;
405
-
406
- public constructor ( public readonly userData : UserData , contentType ?: string ) {
396
+ public constructor ( private readonly userData : UserData , contentType ?: string ) {
407
397
super ( ) ;
408
398
409
- this . contentType = contentType || MultipartBody . DEFAULT_CONTENT_TYPE ;
410
- this . transferEncoding = 'base64' ;
399
+ this . contentType = contentType || MultipartBody . SHELL_SCRIPT ;
411
400
}
412
401
413
- public get body ( ) : string {
414
- // Wrap rendered user data with Base64 function, in case data contains non ASCII characters
415
- return Fn . base64 ( this . userData . render ( ) ) ;
402
+ /**
403
+ * Render body part as the string.
404
+ */
405
+ public renderBodyPart ( ) : string [ ] {
406
+ const result : string [ ] = [ ] ;
407
+
408
+ result . push ( `Content-Type: ${ this . contentType } ` ) ;
409
+ result . push ( 'Content-Transfer-Encoding: base64' ) ;
410
+ result . push ( '' ) ;
411
+ result . push ( Fn . base64 ( this . userData . render ( ) ) ) ;
412
+
413
+ return result ;
416
414
}
417
415
}
418
416
@@ -469,10 +467,21 @@ export class MultipartUserData extends UserData {
469
467
/**
470
468
* Adds a part to the list of parts.
471
469
*/
472
- public addPart ( part : MultipartBody ) : this {
470
+ public addPart ( part : MultipartBody ) {
473
471
this . parts . push ( part ) ;
472
+ }
474
473
475
- return this ;
474
+ /**
475
+ * Adds a multipart part based on a UserData object
476
+ *
477
+ * This is the same as calling:
478
+ *
479
+ * ```ts
480
+ * multiPart.addPart(MultipartBody.fromUserData(userData, contentType));
481
+ * ```
482
+ */
483
+ public addUserDataPart ( userData : UserData , contentType ?: string ) {
484
+ this . addPart ( MultipartBody . fromUserData ( userData , contentType ) ) ;
476
485
}
477
486
478
487
public render ( ) : string {
@@ -491,7 +500,7 @@ export class MultipartUserData extends UserData {
491
500
// Add parts - each part starts with boundary
492
501
this . parts . forEach ( part => {
493
502
resultArchive . push ( `--${ boundary } ` ) ;
494
- resultArchive . push ( part . renderBodyPart ( ) ) ;
503
+ resultArchive . push ( ... part . renderBodyPart ( ) ) ;
495
504
} ) ;
496
505
497
506
// Add closing boundary
0 commit comments