From 4097b3edfe04a4a4a0b522a41fddd6845451ac60 Mon Sep 17 00:00:00 2001 From: Murderlon Date: Wed, 11 Sep 2024 12:55:52 +0200 Subject: [PATCH 1/3] @uppy/tus: set response from tus-js-client --- docs/uploader/tus.mdx | 24 ++++++++++++++++++++++++ packages/@uppy/tus/package.json | 2 +- packages/@uppy/tus/src/index.test.ts | 13 +++++++++++-- packages/@uppy/tus/src/index.ts | 18 ++++++++++++++---- packages/@uppy/utils/src/UppyFile.ts | 4 ++++ yarn.lock | 17 ++++++++++++++++- 6 files changed, 70 insertions(+), 8 deletions(-) diff --git a/docs/uploader/tus.mdx b/docs/uploader/tus.mdx index 9c3abf39fd..3f0e95b306 100644 --- a/docs/uploader/tus.mdx +++ b/docs/uploader/tus.mdx @@ -81,6 +81,30 @@ new Uppy() .use(Tus, { endpoint: 'https://tusd.tusdemo.net/files/' }); ``` +### TypeScript + +If you want the `response` argument on the `upload-success` event and +`file.response.body` to be typed, you have to pass a generic to the Uppy class. + +```ts showLineNumbers +// ... +import Tus, { type TusBody } from '@uppy/tus'; + +type MyMeta = { + /* your added meta data */ +}; + +const uppy = new Uppy().use(Tus, { + endpoint: 'https://tusd.tusdemo.net/files/', +}); + +const [firstFile] = uppy.getFiles(); + +// Correctly typed as XMLHttpRequest. +// Populated after uppy.upload() +firstFile.response.body.xhr; +``` + ## API ### Options diff --git a/packages/@uppy/tus/package.json b/packages/@uppy/tus/package.json index a39ce60013..e1f7aada0f 100644 --- a/packages/@uppy/tus/package.json +++ b/packages/@uppy/tus/package.json @@ -24,7 +24,7 @@ "dependencies": { "@uppy/companion-client": "workspace:^", "@uppy/utils": "workspace:^", - "tus-js-client": "^4.1.0" + "tus-js-client": "^4.2.0" }, "devDependencies": { "vitest": "^1.2.1" diff --git a/packages/@uppy/tus/src/index.test.ts b/packages/@uppy/tus/src/index.test.ts index 949830500f..a6759566b8 100644 --- a/packages/@uppy/tus/src/index.test.ts +++ b/packages/@uppy/tus/src/index.test.ts @@ -1,6 +1,6 @@ -import { describe, expect, it } from 'vitest' +import { describe, expect, expectTypeOf, it } from 'vitest' import Core from '@uppy/core' -import Tus from './index.ts' +import Tus, { type TusBody } from './index.ts' describe('Tus', () => { it('Throws errors if autoRetry option is true', () => { @@ -35,4 +35,13 @@ describe('Tus', () => { /The `autoRetry` option was deprecated and has been removed/, ) }) + + it('propagates the TusBody type', () => { + const uppy = new Core() + const id = uppy.addFile({ name: 'test.jpg', data: { size: 1024 } }) + const file = uppy.getFile(id) + expectTypeOf(file.response?.body).toEqualTypeOf< + { xhr: XMLHttpRequest } | undefined + >() + }) }) diff --git a/packages/@uppy/tus/src/index.ts b/packages/@uppy/tus/src/index.ts index 81ebd2eb97..5c1ea439a0 100644 --- a/packages/@uppy/tus/src/index.ts +++ b/packages/@uppy/tus/src/index.ts @@ -31,6 +31,8 @@ type RestTusUploadOptions = Omit< export type TusDetailedError = tus.DetailedError +export type TusBody = { xhr: XMLHttpRequest } + export interface TusOpts extends PluginOpts, RestTusUploadOptions { @@ -307,11 +309,19 @@ export default class Tus extends BasePlugin< }) } - uploadOptions.onSuccess = () => { - const uploadResp = { + uploadOptions.onSuccess = (payload) => { + const uploadResp: UppyFile['response'] = { uploadURL: upload.url ?? undefined, status: 200, - body: {} as B, + body: { + // We have to put `as XMLHttpRequest` because tus-js-client + // returns `any`, as the type differs in Node.js and the browser. + // In the browser it's always `XMLHttpRequest`. + xhr: payload.lastResponse.getUnderlyingObject() as XMLHttpRequest, + // Body extends Record and thus `xhr` is not known + // but we export the `TusBody` type, which people pass as a generic into the Uppy class, + // so on the implementer side it works as expected. + } as unknown as B, } this.resetUploaderReferences(file.id) @@ -325,7 +335,7 @@ export default class Tus extends BasePlugin< this.uppy.log(`Download ${name} from ${upload.url}`) } if (typeof opts.onSuccess === 'function') { - opts.onSuccess() + opts.onSuccess(payload) } resolve(upload) diff --git a/packages/@uppy/utils/src/UppyFile.ts b/packages/@uppy/utils/src/UppyFile.ts index 8867c53306..6c11e8d724 100644 --- a/packages/@uppy/utils/src/UppyFile.ts +++ b/packages/@uppy/utils/src/UppyFile.ts @@ -2,6 +2,10 @@ import type { FileProgress } from './FileProgress.ts' export type Meta = Record +/** The response of the uploader. + * This is emitted in the upload-success event + * and it put on UppyFile.response.body. + */ export type Body = Record export type InternalMetadata = { name: string; type?: string } diff --git a/yarn.lock b/yarn.lock index b013513658..395d2b0323 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9084,7 +9084,7 @@ __metadata: dependencies: "@uppy/companion-client": "workspace:^" "@uppy/utils": "workspace:^" - tus-js-client: "npm:^4.1.0" + tus-js-client: "npm:^4.2.0" vitest: "npm:^1.2.1" peerDependencies: "@uppy/core": "workspace:^" @@ -28689,6 +28689,21 @@ __metadata: languageName: node linkType: hard +"tus-js-client@npm:^4.2.0": + version: 4.2.1 + resolution: "tus-js-client@npm:4.2.1" + dependencies: + buffer-from: "npm:^1.1.2" + combine-errors: "npm:^3.0.3" + is-stream: "npm:^2.0.0" + js-base64: "npm:^3.7.2" + lodash.throttle: "npm:^4.1.1" + proper-lockfile: "npm:^4.1.2" + url-parse: "npm:^1.5.7" + checksum: 10/aaf90b54aba61ee8efb7f584f9d25a991aa0edd0ef72aa94b817a0401fbbc12e17118669e7d60e880d23d3f82398734c3efab2b0480856aabeac116fc7897698 + languageName: node + linkType: hard + "tv4@npm:^1.3.0": version: 1.3.0 resolution: "tv4@npm:1.3.0" From 99054ebc0f1a8c0407abee87e9aa0c992f9cdc9a Mon Sep 17 00:00:00 2001 From: Murderlon Date: Wed, 11 Sep 2024 12:57:49 +0200 Subject: [PATCH 2/3] Revert UppyFile comment --- packages/@uppy/utils/src/UppyFile.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/@uppy/utils/src/UppyFile.ts b/packages/@uppy/utils/src/UppyFile.ts index 6c11e8d724..8867c53306 100644 --- a/packages/@uppy/utils/src/UppyFile.ts +++ b/packages/@uppy/utils/src/UppyFile.ts @@ -2,10 +2,6 @@ import type { FileProgress } from './FileProgress.ts' export type Meta = Record -/** The response of the uploader. - * This is emitted in the upload-success event - * and it put on UppyFile.response.body. - */ export type Body = Record export type InternalMetadata = { name: string; type?: string } From 475546590f555838ca611e2cc35cafbae1ce9b61 Mon Sep 17 00:00:00 2001 From: Murderlon Date: Thu, 12 Sep 2024 10:38:33 +0200 Subject: [PATCH 3/3] Bump tus-js-client --- packages/@uppy/tus/package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/@uppy/tus/package.json b/packages/@uppy/tus/package.json index e1f7aada0f..8994d1d22f 100644 --- a/packages/@uppy/tus/package.json +++ b/packages/@uppy/tus/package.json @@ -24,7 +24,7 @@ "dependencies": { "@uppy/companion-client": "workspace:^", "@uppy/utils": "workspace:^", - "tus-js-client": "^4.2.0" + "tus-js-client": "^4.2.3" }, "devDependencies": { "vitest": "^1.2.1" diff --git a/yarn.lock b/yarn.lock index 395d2b0323..d0a355f32e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9084,7 +9084,7 @@ __metadata: dependencies: "@uppy/companion-client": "workspace:^" "@uppy/utils": "workspace:^" - tus-js-client: "npm:^4.2.0" + tus-js-client: "npm:^4.2.3" vitest: "npm:^1.2.1" peerDependencies: "@uppy/core": "workspace:^" @@ -28689,9 +28689,9 @@ __metadata: languageName: node linkType: hard -"tus-js-client@npm:^4.2.0": - version: 4.2.1 - resolution: "tus-js-client@npm:4.2.1" +"tus-js-client@npm:^4.2.3": + version: 4.2.3 + resolution: "tus-js-client@npm:4.2.3" dependencies: buffer-from: "npm:^1.1.2" combine-errors: "npm:^3.0.3" @@ -28700,7 +28700,7 @@ __metadata: lodash.throttle: "npm:^4.1.1" proper-lockfile: "npm:^4.1.2" url-parse: "npm:^1.5.7" - checksum: 10/aaf90b54aba61ee8efb7f584f9d25a991aa0edd0ef72aa94b817a0401fbbc12e17118669e7d60e880d23d3f82398734c3efab2b0480856aabeac116fc7897698 + checksum: 10/5beaa5901a4d3f9f8c61b2c10e776a34b0401327c83919239e3a19539321fcc05a4b5051bcdb5e8880d0887c3a857b7c27224730734d3617c17c3d66d64004a4 languageName: node linkType: hard