Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@uppy/aws-s3,@uppy/aws-s3-multipart; fixes #4575 updating types to match web docs #4576

Merged
merged 11 commits into from
Aug 7, 2023

Conversation

bdirito
Copy link
Contributor

@bdirito bdirito commented Jul 13, 2023

Given the types were different between the typescript types & the web documentation I took the approach of assuming the web documents were correct. This may not actually be the case but I didn't have the time to dig into the underlying code to find out.

There are a couple of particular other changes that were questionable. I've tried to point those out in a review.

@@ -22,7 +22,8 @@ export interface AwsS3STSResponse {
region: string
}

export interface AwsS3MultipartOptions extends PluginOptions {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PluginOptions contains only an id and a replaceTargetContent fields. Given that replaceTargetContent is not used / documented I removed the inheritance.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we want to keep the inheritence, even if we don't use the parents definitions, it's still useful to match the type PluginOptions.

Copy link
Contributor Author

@bdirito bdirito Jul 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok; I dug into the code a bit here. It looks like the option replaceTargetContent is used in cases where we are using a UIPlugin uppy/packages/@uppy/core/src/UIPlugin.js:90. UIPlugin extends BasePlugin. Neither AwsS3 or AwsS3Multipart is a UIPlugin. Their inheritance is AwsS3[Multipart] extends UploaderPlugin extends BasePlugin.

I disagree strongly with having types that dont actually match reality. However I think by changing the types to actually reflect the real inheritance we can have inheritance and have proper types.

Thus i propose:
BasePluginOptions UIPluginOptions UploaderPluginOptions
replaceTargetContents becomes a member of UIPluginOptions
id becomes a member of BasePluginOptions (though it doesn't appear to be an actual inherited attribute but rather implemented in each Plugin in order to have it default to the plugin name - see uppy/packages/@uppy/aws-s3/src/index.js:122 for example)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Murderlon is considering removing UploaderPlugin in #4573, so maybe we shouldn't include it in our plans

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok - i pushed new types such that classes that extend UIPlugin take UIPluginOptions; classes that extend BasePlugin take PluginOptions. Other plugins have been updated with this type information though I did not check for type correctness beyond updating plugins that cited inheriting from UIPlugin to have their options inherit from UIPluginOptions

This comment was marked as resolved.

This comment was marked as resolved.

signPart?: (
file: UppyFile,
opts: { uploadId: string; key: string; partNumber: number; body: Blob, signal: AbortSignal }
opts: { uploadId: string; key: string; partNumber: number; body: Blob; signal: AbortSignal }
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to match the style as it was done; however this appears to be an inconsistency so I did change it here.

packages/@uppy/aws-s3-multipart/types/index.d.ts Outdated Show resolved Hide resolved
@@ -10,8 +9,20 @@ export interface AwsS3UploadParameters {
headers?: { [type: string]: string }
}

export interface AwsS3Options extends AwsS3MultipartOptions {
/** @deprecated future versions of this plugin will use the Expires value from the backend */
export interface AwsS3Options {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There I removed the inheritance from AwsS3MultipartOptions. Its possible that they should both inherit from a BaseS3Options but I did not do that here.

getUploadParameters?: (file: UppyFile) => MaybePromise<{
method: "PUT" | "POST"
url: string
fields: Record<string, string> | null
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fields was a difficult one. On the one hand the docs say that the promise should fulfills with an object, with keys { method, url, fields, headers }. To have the key to me means it should not be allowed to be undefined.

However it also says that For presigned PUT uploads, this should be left empty.

I decided that empty but defined meant null was an option.

The docs say the other option was to return an object with form fields. Record<string, string> is almost certainly too strict; I would expect it to actually support something like Record<string, string | Array<string> | number | Array<number>> or even more. But I wanted to default into something as strict as possible over just using something like Object;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a better type would be

{
 method: 'POST'
 url: string
 fields: Record<string,string>
} | {
  method: 'PUT'
  url: string
}

method: "PUT" | "POST"
url: string
fields: Record<string, string> | null
headers: Record<string, string>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the same way as above Record<string, string> is probably too strict.

packages/@uppy/aws-s3/types/index.d.ts Show resolved Hide resolved
import AwsS3 from '..'

{
const uppy = new Uppy()
uppy.use(AwsS3, {
getUploadParameters (file) {
expectType<UppyFile>(file)
return { url: '' }
return { method: 'POST', url: '', fields: null, headers: {} }
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what we want for this. These seemed sane test values.

partData: { uploadId: string; key: string; parts: [{ number: number, chunk: Blob }], signal: AbortSignal }
) => MaybePromise<{ presignedUrls: { [k: number]: string }, headers?: { [k: string]: string } }>
partData: { uploadId: string; key: string; parts: [{ number: number, chunk: Blob }] }
) => MaybePromise<{ presignedUrls: { [k: number]: string }, headers?: Record<number, Record<string, string>> }>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The webpage documentation (and examples) do not match the types. In particular it looks like the types are missing an object level.

From the docs as an example return value:

{
    "presignedUrls": {
        "1": "https://bucket.region.amazonaws.com/path/to/file.jpg?partNumber=1&...",
        "2": "https://bucket.region.amazonaws.com/path/to/file.jpg?partNumber=2&...",
        "3": "https://bucket.region.amazonaws.com/path/to/file.jpg?partNumber=3&..."
    },
    "headers": {
        "1": { "Content-MD5": "foo" },
        "2": { "Content-MD5": "bar" },
        "3": { "Content-MD5": "baz" }
    }
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we have k: number for presignedUrls and Record for headers?

Copy link
Contributor Author

@bdirito bdirito Jul 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if there is any sort of Uppy standard as to the preferred approach. Record is definitely used throughout the codebase as well as the {[k: type]: type} syntax. For example the core types use the Record style as in packages/@uppy/core/types/index.d.ts. I think I would suspect that the core style to be more likely to be the preferred approach.

Either way styles should probably not be mixed across a single file, or worse a single function type declaration. Thus I have updated the presignedUrl here to use Record as well

@bdirito bdirito changed the title fixes #4575 updating types of s3options & s3multipartOptions to match web docs @uppy/aws-s3; @uppy/aws-s3-multipart; fixes #4575 updating types to match web docs Jul 13, 2023
@bdirito bdirito changed the title @uppy/aws-s3; @uppy/aws-s3-multipart; fixes #4575 updating types to match web docs @uppy/aws-s3,@uppy/aws-s3-multipart; fixes #4575 updating types to match web docs Jul 13, 2023
@Murderlon Murderlon requested a review from aduh95 July 17, 2023 08:48
Copy link
Member

@Murderlon Murderlon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot for diving deep into this 👍

partData: { uploadId: string; key: string; parts: [{ number: number, chunk: Blob }], signal: AbortSignal }
) => MaybePromise<{ presignedUrls: { [k: number]: string }, headers?: { [k: string]: string } }>
partData: { uploadId: string; key: string; parts: [{ number: number, chunk: Blob }] }
) => MaybePromise<{ presignedUrls: { [k: number]: string }, headers?: Record<number, Record<string, string>> }>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we have k: number for presignedUrls and Record for headers?

Copy link
Member

@Murderlon Murderlon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One Q, otherwise LGTM

packages/@uppy/aws-s3/types/index.d.ts Show resolved Hide resolved
Copy link
Contributor

@aduh95 aduh95 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks ❤️

@aduh95 aduh95 merged commit f3ce884 into transloadit:main Aug 7, 2023
@github-actions github-actions bot mentioned this pull request Aug 15, 2023
github-actions bot added a commit that referenced this pull request Aug 15, 2023
| Package                   | Version | Package                   | Version |
| ------------------------- | ------- | ------------------------- | ------- |
| @uppy/audio               |   1.1.2 | @uppy/locales             |   3.3.0 |
| @uppy/aws-s3              |   3.2.2 | @uppy/onedrive            |   3.1.3 |
| @uppy/aws-s3-multipart    |   3.5.3 | @uppy/progress-bar        |   3.0.3 |
| @uppy/box                 |   2.1.3 | @uppy/provider-views      |   3.5.0 |
| @uppy/companion           |   4.8.0 | @uppy/redux-dev-tools     |   3.0.3 |
| @uppy/companion-client    |   3.3.0 | @uppy/screen-capture      |   3.1.2 |
| @uppy/core                |   3.4.0 | @uppy/status-bar          |   3.2.4 |
| @uppy/dashboard           |   3.5.1 | @uppy/thumbnail-generator |   3.0.4 |
| @uppy/drag-drop           |   3.0.3 | @uppy/transloadit         |   3.2.1 |
| @uppy/dropbox             |   3.1.3 | @uppy/tus                 |   3.1.3 |
| @uppy/facebook            |   3.1.2 | @uppy/unsplash            |   3.2.2 |
| @uppy/file-input          |   3.0.3 | @uppy/url                 |   3.3.3 |
| @uppy/google-drive        |   3.2.1 | @uppy/webcam              |   3.3.2 |
| @uppy/image-editor        |   2.1.3 | @uppy/xhr-upload          |   3.3.2 |
| @uppy/informer            |   3.0.3 | @uppy/zoom                |   2.1.2 |
| @uppy/instagram           |   3.1.2 | uppy                      |  3.14.0 |

- meta: Readme improvements (Artur Paikin / #4622)
- @uppy/companion: Fix typos and add env vars to .env.example (Dominik Schmidt / #4624)
- @uppy/aws-s3-multipart: pass the `uploadURL` back to the caller (Antoine du Hamel / #4614)
- meta: update to node-18.17.0-alpine,  (odselsevier / #4617)
- @uppy/aws-s3,@uppy/aws-s3-multipart: update types (Antoine du Hamel / #4611)
- @uppy/aws-s3-multipart,@uppy/aws-s3,@uppy/companion,@uppy/transloadit,@uppy/xhr-upload: use uppercase HTTP method names (Antoine du Hamel / #4612)
- meta: e2e: fix race condition in transloadit test (Antoine du Hamel / #4616)
- @uppy/aws-s3,@uppy/aws-s3-multipart: update types (bdirito / #4576)
- @uppy/core: allow duplicate files with onBeforeFileAdded (Merlijn Vos / #4594)
- @uppy/companion: make CSRF protection helpers available to providers (Dominik Schmidt / #4554)
- @uppy/companion: fix Redis key default TTL (Subha Sarkar / #4607)
- @uppy/companion: Fix Uploader.js metadata normalisation (Subha Sarkar / #4608)
- @uppy/companion-client,@uppy/provider-views: make authentication optional (Dominik Schmidt / #4556)
- @uppy/provider-views: fix ProviderView error on empty plugin.icon (Dominik Schmidt / #4553)
- @uppy/aws-s3,@uppy/tus,@uppy/xhr-upload:  Invoke headers function for remote uploads (Dominik Schmidt / #4596)
- @uppy/companion: Unify redis initialization (Dominik Schmidt / #4597)
- meta: lock node-js version on ci (Mikael Finstad / #4606)
- @uppy/companion: allow dynamic S3 bucket (rmoura-92 / #4579)
- @uppy/status-bar: e2e: add test for retrying and pausing uploads (Antoine du Hamel / #3599)
- meta: e2e: remove too short timeout (Antoine du Hamel / #4602)
Murderlon added a commit that referenced this pull request Aug 24, 2023
* main: (28 commits)
  Release: uppy@3.14.1 (#4644)
  @uppy/aws-s3-multipart: fix types when using deprecated option (#4634)
  @uppy/companion: harden lint rules (#4641)
  allow empty objects for `fields` types (#4631)
  meta: upgrade Node.js docker version (#4630)
  Release: uppy@3.14.0 (#4626)
  Readme improvements (#4622)
  Fix typos and add env vars to .env.example (#4624)
  @uppy/aws-s3-multipart: pass the `uploadURL` back to the caller (#4614)
  update to node-18.17.0-alpine,  (#4617)
  @uppy/aws-s3,@uppy/aws-s3-multipart: update types (#4611)
  use uppercase HTTP method names (#4612)
  e2e: fix race condition in transloadit test (#4616)
  @uppy/aws-s3,@uppy/aws-s3-multipart: update types (#4576)
  @uppy/core: allow duplicate files with onBeforeFileAdded (#4594)
  @uppy/companion: make CSRF protection helpers available to providers (#4554)
  @uppy/companion: fix Redis key default TTL (#4607)
  @uppy/companion: Fix Uploader.js metadata normalisation (#4608)
  @uppy/companion-client,@uppy/provider-views: make authentication optional (#4556)
  @uppy/provider-views: fix ProviderView error on empty plugin.icon (#4553)
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

@uppy/AwsS3 and @uppy/AwsS3Multipart options type information does not match the documentation
3 participants