Procházet zdrojové kódy

@uppy/aws-s3,@uppy/aws-s3-multipart: update types (#4611)

Antoine du Hamel před 1 rokem
rodič
revize
39e870f487

+ 129 - 30
packages/@uppy/aws-s3-multipart/types/index.d.ts

@@ -2,11 +2,28 @@ import type { BasePlugin, PluginOptions, UppyFile } from '@uppy/core'
 
 type MaybePromise<T> = T | Promise<T>
 
+export type AwsS3UploadParameters = {
+  method: 'POST'
+  url: string
+  fields: Record<string, string>
+  expires?: number
+  headers?: Record<string, string>
+} | {
+  method?: 'PUT'
+  url: string
+  fields?: never
+  expires?: number
+  headers?: Record<string, string>
+}
+
 export interface AwsS3Part {
   PartNumber?: number
   Size?: number
   ETag?: string
 }
+/**
+ * @deprecated use {@link AwsS3UploadParameters} instead
+ */
 export interface AwsS3SignedPart {
   url: string
   headers?: Record<string, string>
@@ -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<AwsS3UploadParameters>
+}
+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<AwsS3Part[]>
+  signPart: (
+    file: UppyFile,
+    opts: { uploadId: string; key: string; partNumber: number; body: Blob; signal: AbortSignal }
+  ) => MaybePromise<AwsS3UploadParameters>
+  abortMultipartUpload: (
+    file: UppyFile,
+    opts: { uploadId: string; key: string; signal: AbortSignal }
+  ) => MaybePromise<void>
+  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<string, string>
+  companionCookiesRule?: string
+  getTemporarySecurityCredentials?: true
+}
+type AWSS3WithoutCompanion = {
+  companionUrl?: never
+  companionHeaders?: never
+  companionCookiesRule?: never
+  getTemporarySecurityCredentials?: (options?: {signal?: AbortSignal}) => MaybePromise<AwsS3STSResponse>
+}
+
+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<AwsS3Part[]>
-    signPart?: (
-      file: UppyFile,
-      opts: { uploadId: string; key: string; partNumber: number; body: Blob; signal: AbortSignal }
-    ) => MaybePromise<AwsS3SignedPart>
+    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<number, string>, headers?: Record<number, Record<string, string>> }>
-    abortMultipartUpload?: (
-      file: UppyFile,
-      opts: { uploadId: string; key: string; signal: AbortSignal }
-    ) => MaybePromise<void>
-    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
 > {}

+ 11 - 9
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<UppyFile>(file)
       return { uploadId: '', key: '' }
@@ -17,12 +18,13 @@ import type { AwsS3Part } from '..'
       expectType<string>(opts.key)
       return []
     },
-    prepareUploadParts (file, partData) {
+    signPart (file, opts) {
       expectType<UppyFile>(file)
-      expectType<string>(partData.uploadId)
-      expectType<string>(partData.key)
-      expectType<[{number: number, chunk: Blob}]>(partData.parts)
-      return { presignedUrls: {} }
+      expectType<string>(opts.uploadId)
+      expectType<string>(opts.key)
+      expectType<Blob>(opts.body)
+      expectType<AbortSignal>(opts.signal)
+      return { url: '' }
     },
     abortMultipartUpload (file, opts) {
       expectType<UppyFile>(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 })
 }

+ 19 - 18
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> = T | Promise<T>
 
-export interface AwsS3UploadParameters {
-    method?: string
-    url: string
-    fields?: { [type: string]: string }
-    headers?: { [type: string]: string }
+export type AwsS3UploadParameters = {
+  method?: 'POST'
+  url: string
+  fields?: Record<string, string>
+  expires?: number
+  headers?: Record<string, string>
+} | {
+  method: 'PUT'
+  url: string
+  fields?: never
+  expires?: number
+  headers?: Record<string, string>
 }
 
-export interface AwsS3Options extends PluginOptions {
+interface LegacyAwsS3Options extends PluginOptions {
+    shouldUseMultipart?: never
     companionUrl?: string | null
     companionHeaders?: Record<string, string>
     allowedMetaFields?: Array<string> | null
-    getUploadParameters?: (file: UppyFile) => MaybePromise<{
-      method?: 'POST'
-      url: string
-      fields?: Record<string, string>
-      headers?: Record<string, string>
-    } | {
-      method: 'PUT'
-      url: string
-      fields: never
-      headers?: Record<string, string>
-    }>
+    getUploadParameters?: (file: UppyFile) => MaybePromise<AwsS3UploadParameters>
     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<AwsS3Options> {}
 

+ 61 - 2
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<UppyFile>(file)
-      return { method: 'POST', url: '', fields: {}, headers: {} }
+      return { method: 'POST', url: '' }
+    },
+  })
+  expectError(uppy.use(AwsS3, {
+    shouldUseMultipart: false,
+    getUploadParameters (file) {
+      expectType<UppyFile>(file)
+      return { method: 'POST', url: '' }
+    },
+  }))
+  uppy.use(AwsS3, {
+    shouldUseMultipart: false,
+    getUploadParameters (file) {
+      expectType<UppyFile>(file)
+      return { method: 'POST', url: '', fields: {} }
+    },
+  })
+  expectError(uppy.use(AwsS3, {
+    shouldUseMultipart: true,
+    getUploadParameters (file) {
+      expectType<UppyFile>(file)
+      return { method: 'PUT', url: '' }
+    },
+  }))
+  uppy.use(AwsS3, {
+    shouldUseMultipart: () => Math.random() > 0.5,
+    getUploadParameters (file) {
+      expectType<UppyFile>(file)
+      return { method: 'PUT', url: '' }
+    },
+    createMultipartUpload (file) {
+      expectType<UppyFile>(file)
+      return { uploadId: '', key: '' }
+    },
+    listParts (file, opts) {
+      expectType<UppyFile>(file)
+      expectType<string>(opts.uploadId)
+      expectType<string>(opts.key)
+      return []
+    },
+    signPart (file, opts) {
+      expectType<UppyFile>(file)
+      expectType<string>(opts.uploadId)
+      expectType<string>(opts.key)
+      expectType<Blob>(opts.body)
+      expectType<AbortSignal>(opts.signal)
+      return { url: '' }
+    },
+    abortMultipartUpload (file, opts) {
+      expectType<UppyFile>(file)
+      expectType<string>(opts.uploadId)
+      expectType<string>(opts.key)
+    },
+    completeMultipartUpload (file, opts) {
+      expectType<UppyFile>(file)
+      expectType<string>(opts.uploadId)
+      expectType<string>(opts.key)
+      expectType<AwsS3Part>(opts.parts[0])
+      return {}
     },
   })
 }