diff --git a/packages/@uppy/aws-s3-multipart/types/index.d.ts b/packages/@uppy/aws-s3-multipart/types/index.d.ts index 65488c3f68..aebe139d29 100644 --- a/packages/@uppy/aws-s3-multipart/types/index.d.ts +++ b/packages/@uppy/aws-s3-multipart/types/index.d.ts @@ -2,11 +2,28 @@ import type { BasePlugin, PluginOptions, UppyFile } from '@uppy/core' type MaybePromise = T | Promise +export type AwsS3UploadParameters = { + method: 'POST' + url: string + fields: Record + expires?: number + headers?: Record +} | { + method?: 'PUT' + url: string + fields?: never + expires?: number + headers?: Record +} + export interface AwsS3Part { PartNumber?: number Size?: number ETag?: string } +/** + * @deprecated use {@link AwsS3UploadParameters} instead + */ export interface AwsS3SignedPart { url: string headers?: Record @@ -22,44 +39,126 @@ export interface AwsS3STSResponse { region: string } -export interface AwsS3MultipartOptions extends PluginOptions { - companionHeaders?: { [type: string]: string } - companionUrl?: string - companionCookiesRule?: string +type AWSS3NonMultipartWithCompanionMandatory = { + getUploadParameters?: never +} + +type AWSS3NonMultipartWithoutCompanionMandatory = { + getUploadParameters: ( + file: UppyFile + ) => MaybePromise +} +type AWSS3NonMultipartWithCompanion = AWSS3WithCompanion & + AWSS3NonMultipartWithCompanionMandatory & + { + shouldUseMultipart: false + createMultipartUpload?: never + listParts?: never + signPart?: never + abortMultipartUpload?: never + completeMultipartUpload?: never + } + +type AWSS3NonMultipartWithoutCompanion = AWSS3WithoutCompanion & + AWSS3NonMultipartWithoutCompanionMandatory & + { + shouldUseMultipart: false + createMultipartUpload?: never + listParts?: never + signPart?: never + abortMultipartUpload?: never + completeMultipartUpload?: never + } + +type AWSS3MultipartWithCompanionMandatory = { + getChunkSize?: (file: UppyFile) => number + createMultipartUpload?: never + listParts?: never + signPart?: never + abortMultipartUpload?: never + completeMultipartUpload?: never +} +type AWSS3MultipartWithoutCompanionMandatory = { + getChunkSize?: (file: UppyFile) => number + createMultipartUpload: ( + file: UppyFile + ) => MaybePromise<{ uploadId: string; key: string }> + listParts: ( + file: UppyFile, + opts: { uploadId: string; key: string; signal: AbortSignal } + ) => MaybePromise + signPart: ( + file: UppyFile, + opts: { uploadId: string; key: string; partNumber: number; body: Blob; signal: AbortSignal } + ) => MaybePromise + abortMultipartUpload: ( + file: UppyFile, + opts: { uploadId: string; key: string; signal: AbortSignal } + ) => MaybePromise + completeMultipartUpload: ( + file: UppyFile, + opts: { uploadId: string; key: string; parts: AwsS3Part[]; signal: AbortSignal } + ) => MaybePromise<{ location?: string }> +} +type AWSS3MultipartWithoutCompanion = AWSS3WithoutCompanion & + AWSS3MultipartWithoutCompanionMandatory & + { + shouldUseMultipart?: true + getUploadParameters?: never + } + +type AWSS3MultipartWithCompanion = AWSS3WithCompanion & + AWSS3MultipartWithCompanionMandatory & + { + shouldUseMultipart?: true + getUploadParameters?: never + } + +type AWSS3MaybeMultipartWithCompanion = AWSS3WithCompanion & + AWSS3MultipartWithCompanionMandatory & + AWSS3NonMultipartWithCompanionMandatory & + { + shouldUseMultipart: ((file: UppyFile) => boolean) + } + +type AWSS3MaybeMultipartWithoutCompanion = AWSS3WithoutCompanion & + AWSS3MultipartWithoutCompanionMandatory & + AWSS3NonMultipartWithoutCompanionMandatory & + { + shouldUseMultipart: ((file: UppyFile) => boolean) + } + +type AWSS3WithCompanion = { + companionUrl: string + companionHeaders?: Record + companionCookiesRule?: string + getTemporarySecurityCredentials?: true +} +type AWSS3WithoutCompanion = { + companionUrl?: never + companionHeaders?: never + companionCookiesRule?: never + getTemporarySecurityCredentials?: (options?: {signal?: AbortSignal}) => MaybePromise +} + +interface _AwsS3MultipartOptions extends PluginOptions { allowedMetaFields?: string[] | null - getChunkSize?: (file: UppyFile) => number - createMultipartUpload?: ( - file: UppyFile - ) => MaybePromise<{ uploadId: string; key: string }> - listParts?: ( - file: UppyFile, - opts: { uploadId: string; key: string; signal: AbortSignal } - ) => MaybePromise - signPart?: ( - file: UppyFile, - opts: { uploadId: string; key: string; partNumber: number; body: Blob; signal: AbortSignal } - ) => MaybePromise + limit?: number + retryDelays?: number[] | null /** @deprecated Use signPart instead */ prepareUploadParts?: ( file: UppyFile, partData: { uploadId: string; key: string; parts: [{ number: number, chunk: Blob }] } ) => MaybePromise<{ presignedUrls: Record, headers?: Record> }> - abortMultipartUpload?: ( - file: UppyFile, - opts: { uploadId: string; key: string; signal: AbortSignal } - ) => MaybePromise - completeMultipartUpload?: ( - file: UppyFile, - opts: { uploadId: string; key: string; parts: AwsS3Part[]; signal: AbortSignal } - ) => MaybePromise<{ location?: string }> - limit?: number - shouldUseMultipart?: boolean | ((file: UppyFile) => boolean) - retryDelays?: number[] | null - getUploadParameters?: ( - file: UppyFile - ) => MaybePromise<{ url: string }> } +export type AwsS3MultipartOptions = _AwsS3MultipartOptions & (AWSS3NonMultipartWithCompanion | + AWSS3NonMultipartWithoutCompanion | + AWSS3MultipartWithCompanion | + AWSS3MultipartWithoutCompanion | + AWSS3MaybeMultipartWithCompanion | + AWSS3MaybeMultipartWithoutCompanion) + declare class AwsS3Multipart extends BasePlugin< AwsS3MultipartOptions > {} diff --git a/packages/@uppy/aws-s3-multipart/types/index.test-d.ts b/packages/@uppy/aws-s3-multipart/types/index.test-d.ts index 95793af2b8..4ccadd71a8 100644 --- a/packages/@uppy/aws-s3-multipart/types/index.test-d.ts +++ b/packages/@uppy/aws-s3-multipart/types/index.test-d.ts @@ -7,6 +7,7 @@ import type { AwsS3Part } from '..' { const uppy = new Uppy() uppy.use(AwsS3Multipart, { + shouldUseMultipart: true, createMultipartUpload (file) { expectType(file) return { uploadId: '', key: '' } @@ -17,12 +18,13 @@ import type { AwsS3Part } from '..' expectType(opts.key) return [] }, - prepareUploadParts (file, partData) { + signPart (file, opts) { expectType(file) - expectType(partData.uploadId) - expectType(partData.key) - expectType<[{number: number, chunk: Blob}]>(partData.parts) - return { presignedUrls: {} } + expectType(opts.uploadId) + expectType(opts.key) + expectType(opts.body) + expectType(opts.signal) + return { url: '' } }, abortMultipartUpload (file, opts) { expectType(file) @@ -41,8 +43,8 @@ import type { AwsS3Part } from '..' { const uppy = new Uppy() - expectError(uppy.use(AwsS3Multipart, { getChunkSize: 100 })) - expectError(uppy.use(AwsS3Multipart, { getChunkSize: () => 'not a number' })) - uppy.use(AwsS3Multipart, { getChunkSize: () => 100 }) - uppy.use(AwsS3Multipart, { getChunkSize: (file) => file.size }) + expectError(uppy.use(AwsS3Multipart, { companionUrl: '', getChunkSize: 100 })) + expectError(uppy.use(AwsS3Multipart, { companionUrl: '', getChunkSize: () => 'not a number' })) + uppy.use(AwsS3Multipart, { companionUrl: '', getChunkSize: () => 100 }) + uppy.use(AwsS3Multipart, { companionUrl: '', getChunkSize: (file) => file.size }) } diff --git a/packages/@uppy/aws-s3/types/index.d.ts b/packages/@uppy/aws-s3/types/index.d.ts index 8908eff9df..5d43dd28f3 100644 --- a/packages/@uppy/aws-s3/types/index.d.ts +++ b/packages/@uppy/aws-s3/types/index.d.ts @@ -1,35 +1,36 @@ +import { AwsS3MultipartOptions } from '@uppy/aws-s3-multipart' import type { BasePlugin, Locale, PluginOptions, UppyFile } from '@uppy/core' type MaybePromise = T | Promise -export interface AwsS3UploadParameters { - method?: string - url: string - fields?: { [type: string]: string } - headers?: { [type: string]: string } +export type AwsS3UploadParameters = { + method?: 'POST' + url: string + fields?: Record + expires?: number + headers?: Record +} | { + method: 'PUT' + url: string + fields?: never + expires?: number + headers?: Record } -export interface AwsS3Options extends PluginOptions { +interface LegacyAwsS3Options extends PluginOptions { + shouldUseMultipart?: never companionUrl?: string | null companionHeaders?: Record allowedMetaFields?: Array | null - getUploadParameters?: (file: UppyFile) => MaybePromise<{ - method?: 'POST' - url: string - fields?: Record - headers?: Record - } | { - method: 'PUT' - url: string - fields: never - headers?: Record - }> + getUploadParameters?: (file: UppyFile) => MaybePromise limit?: number /** @deprecated this option will not be supported in future versions of this plugin */ getResponseData?: (responseText: string, response: XMLHttpRequest) => void locale?: Locale, timeout?: number -} + } + +export type AwsS3Options = LegacyAwsS3Options | AwsS3MultipartOptions; declare class AwsS3 extends BasePlugin {} diff --git a/packages/@uppy/aws-s3/types/index.test-d.ts b/packages/@uppy/aws-s3/types/index.test-d.ts index c4f80da6f1..0e922b81bc 100644 --- a/packages/@uppy/aws-s3/types/index.test-d.ts +++ b/packages/@uppy/aws-s3/types/index.test-d.ts @@ -1,5 +1,6 @@ import { Uppy, UppyFile } from '@uppy/core' -import { expectType } from 'tsd' +import { expectType, expectError } from 'tsd' +import type { AwsS3Part } from '@uppy/aws-s3-multipart' import AwsS3 from '..' { @@ -7,7 +8,65 @@ import AwsS3 from '..' uppy.use(AwsS3, { getUploadParameters (file) { expectType(file) - return { method: 'POST', url: '', fields: {}, headers: {} } + return { method: 'POST', url: '' } + }, + }) + expectError(uppy.use(AwsS3, { + shouldUseMultipart: false, + getUploadParameters (file) { + expectType(file) + return { method: 'POST', url: '' } + }, + })) + uppy.use(AwsS3, { + shouldUseMultipart: false, + getUploadParameters (file) { + expectType(file) + return { method: 'POST', url: '', fields: {} } + }, + }) + expectError(uppy.use(AwsS3, { + shouldUseMultipart: true, + getUploadParameters (file) { + expectType(file) + return { method: 'PUT', url: '' } + }, + })) + uppy.use(AwsS3, { + shouldUseMultipart: () => Math.random() > 0.5, + getUploadParameters (file) { + expectType(file) + return { method: 'PUT', url: '' } + }, + createMultipartUpload (file) { + expectType(file) + return { uploadId: '', key: '' } + }, + listParts (file, opts) { + expectType(file) + expectType(opts.uploadId) + expectType(opts.key) + return [] + }, + signPart (file, opts) { + expectType(file) + expectType(opts.uploadId) + expectType(opts.key) + expectType(opts.body) + expectType(opts.signal) + return { url: '' } + }, + abortMultipartUpload (file, opts) { + expectType(file) + expectType(opts.uploadId) + expectType(opts.key) + }, + completeMultipartUpload (file, opts) { + expectType(file) + expectType(opts.uploadId) + expectType(opts.key) + expectType(opts.parts[0]) + return {} }, }) }