|
1 | | -import type { Mime } from 'mime'; |
2 | | -import mime from 'mime'; |
3 | 1 | import type * as Models from './models'; |
4 | 2 | import type * as Parameters from './parameters'; |
5 | 3 | import type { Client } from '../clients'; |
6 | 4 | import type { Callback } from '../callback'; |
7 | 5 | import type { Request } from '../request'; |
| 6 | +import { FormDataService } from '../services/formDataService'; |
8 | 7 |
|
9 | 8 | export class IssueAttachments { |
10 | 9 | constructor(private client: Client) {} |
@@ -121,6 +120,7 @@ export class IssueAttachments { |
121 | 120 | async getAttachmentThumbnail<T = Buffer>(parameters: Parameters.GetAttachmentThumbnail | string): Promise<void | T> { |
122 | 121 | const id = typeof parameters === 'string' ? parameters : parameters.id; |
123 | 122 |
|
| 123 | + // todo |
124 | 124 | const config: Request = { |
125 | 125 | url: `/rest/api/2/attachment/thumbnail/${id}`, |
126 | 126 | method: 'GET', |
@@ -381,112 +381,29 @@ export class IssueAttachments { |
381 | 381 | */ |
382 | 382 | async addAttachment<T = Models.Attachment[]>(parameters: Parameters.AddAttachment, callback?: never): Promise<T>; |
383 | 383 | async addAttachment<T = Models.Attachment[]>(parameters: Parameters.AddAttachment): Promise<void | T> { |
384 | | - const formData = new FormData(); |
| 384 | + const formDataService = new FormDataService(); |
385 | 385 | const attachments = Array.isArray(parameters.attachment) ? parameters.attachment : [parameters.attachment]; |
386 | 386 |
|
387 | | - // eslint-disable-next-line @typescript-eslint/consistent-type-imports |
388 | | - let Readable: typeof import('stream').Readable | undefined; |
389 | | - |
390 | | - if (typeof window === 'undefined') { |
391 | | - const { Readable: NodeReadable } = await import('stream'); |
392 | | - |
393 | | - Readable = NodeReadable; |
394 | | - } |
395 | | - |
396 | | - for await (const attachment of attachments) { |
397 | | - const file = await this._convertToFile(attachment, mime, Readable); |
398 | | - |
399 | | - if (!(file instanceof File || file instanceof Blob)) { |
400 | | - throw new Error(`Unsupported file type for attachment: ${typeof file}`); |
401 | | - } |
402 | | - |
403 | | - formData.append('file', file, attachment.filename); |
404 | | - } |
| 387 | + await Promise.all( |
| 388 | + attachments.map(attachment => |
| 389 | + formDataService.append(attachment.content, attachment.filename, { |
| 390 | + contentLength: attachment.contentLength, |
| 391 | + contentType: attachment.contentType, |
| 392 | + }), |
| 393 | + ), |
| 394 | + ); |
405 | 395 |
|
406 | 396 | const config: Request = { |
407 | 397 | url: `/rest/api/2/issue/${parameters.issueIdOrKey}/attachments`, |
408 | 398 | method: 'POST', |
409 | 399 | headers: { |
410 | 400 | 'X-Atlassian-Token': 'no-check', |
411 | | - // 'Content-Type': 'multipart/form-data', |
412 | 401 | }, |
413 | | - body: formData, |
414 | | - // maxBodyLength: Infinity, // todo |
415 | | - // maxContentLength: Infinity, // todo |
| 402 | + body: formDataService.formData, |
| 403 | + // maxBodyLength: Infinity, // todo needed? |
| 404 | + // maxContentLength: Infinity, // todo needed? |
416 | 405 | }; |
417 | 406 |
|
418 | 407 | return this.client.sendRequest(config); |
419 | 408 | } |
420 | | - |
421 | | - private async _convertToFile( |
422 | | - attachment: Parameters.Attachment, |
423 | | - mime: Mime, |
424 | | - // eslint-disable-next-line @typescript-eslint/consistent-type-imports |
425 | | - Readable?: typeof import('stream').Readable, |
426 | | - ): Promise<File | Blob> { |
427 | | - const mimeType = attachment.mimeType ?? (mime.getType(attachment.filename) || undefined); |
428 | | - |
429 | | - if (attachment.file instanceof Blob || attachment.file instanceof File) { |
430 | | - return attachment.file; |
431 | | - } |
432 | | - |
433 | | - if (typeof attachment.file === 'string') { |
434 | | - return new File([attachment.file], attachment.filename, { type: mimeType }); |
435 | | - } |
436 | | - |
437 | | - if (Readable && attachment.file instanceof Readable) { |
438 | | - return this._streamToBlob(attachment.file, attachment.filename, mimeType); |
439 | | - } |
440 | | - |
441 | | - if (attachment.file instanceof ReadableStream) { |
442 | | - return this._streamToBlob(attachment.file, attachment.filename, mimeType); |
443 | | - } |
444 | | - |
445 | | - if (ArrayBuffer.isView(attachment.file) || attachment.file instanceof ArrayBuffer) { |
446 | | - return new File([attachment.file], attachment.filename, { type: mimeType }); |
447 | | - } |
448 | | - |
449 | | - throw new Error('Unsupported attachment file type.'); |
450 | | - } |
451 | | - |
452 | | - private async _streamToBlob( |
453 | | - // eslint-disable-next-line @typescript-eslint/consistent-type-imports |
454 | | - stream: import('stream').Readable | ReadableStream, |
455 | | - filename: string, |
456 | | - mimeType?: string, |
457 | | - ): Promise<File> { |
458 | | - if (typeof window === 'undefined' && stream instanceof (await import('stream')).Readable) { |
459 | | - return new Promise((resolve, reject) => { |
460 | | - const chunks: Uint8Array[] = []; |
461 | | - |
462 | | - stream.on('data', chunk => chunks.push(chunk)); |
463 | | - stream.on('end', () => { |
464 | | - const blob = new Blob(chunks, { type: mimeType }); |
465 | | - |
466 | | - resolve(new File([blob], filename, { type: mimeType })); |
467 | | - }); |
468 | | - stream.on('error', reject); |
469 | | - }); |
470 | | - } |
471 | | - |
472 | | - if (stream instanceof ReadableStream) { |
473 | | - const reader = stream.getReader(); |
474 | | - const chunks: Uint8Array[] = []; |
475 | | - |
476 | | - let done = false; |
477 | | - |
478 | | - while (!done) { |
479 | | - const { value, done: streamDone } = await reader.read(); |
480 | | - |
481 | | - if (value) chunks.push(value); |
482 | | - done = streamDone; |
483 | | - } |
484 | | - |
485 | | - const blob = new Blob(chunks, { type: mimeType }); |
486 | | - |
487 | | - return new File([blob], filename, { type: mimeType }); |
488 | | - } |
489 | | - |
490 | | - throw new Error('Unsupported stream type.'); |
491 | | - } |
492 | 409 | } |
0 commit comments