Jelajahi Sumber

Update tus-js-client dependency to v2 (#2239)

Co-authored-by: Renée Kooi <renee@kooi.me>
Marius 4 tahun lalu
induk
melakukan
541feef81e

+ 1 - 1
examples/react-native-expo/package.json

@@ -5,7 +5,7 @@
     "@uppy/dashboard": "file:../../packages/@uppy/dashboard",
     "@uppy/instagram": "file:../../packages/@uppy/instagram",
     "@uppy/react-native": "file:../../packages/@uppy/react-native",
-    "@uppy/tus": "file:../../packages/@uppy/tus",
+    "@uppy/tus": "1.6.0",
     "@uppy/url": "file:../../packages/@uppy/url",
     "@uppy/xhr-upload": "file:../../packages/@uppy/xhr-upload",
     "babel-preset-expo": "^5.0.0",

+ 25 - 33
package-lock.json

@@ -6170,11 +6170,6 @@
       "integrity": "sha512-I99sngh224D0M7XgW1s120zxCt3VYQ3IQsuw3P3jbq5GG4yc79+ZjyKznyOGIQrflfylLgcfekeZW/vk0yng6A==",
       "dev": true
     },
-    "@types/tus-js-client": {
-      "version": "1.8.0",
-      "resolved": "https://registry.npmjs.org/@types/tus-js-client/-/tus-js-client-1.8.0.tgz",
-      "integrity": "sha512-lWxu5+6qfyfwsW99GzUeJ9y9JeOSSLduKxgYMvaYM7sGTDKZsrIIHTUbHI2P016xhXtu9NxmUM3GrB4i14ie4A=="
-    },
     "@types/unist": {
       "version": "2.0.3",
       "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz",
@@ -7048,7 +7043,7 @@
         "request": "2.88.0",
         "semver": "6.3.0",
         "serialize-error": "^2.1.0",
-        "tus-js-client": "1.8.0",
+        "tus-js-client": "2.1.1",
         "uuid": "3.3.3",
         "validator": "^12.1.0",
         "ws": "6.2.1"
@@ -7502,13 +7497,12 @@
           }
         },
         "tus-js-client": {
-          "version": "1.8.0",
-          "resolved": "https://registry.npmjs.org/tus-js-client/-/tus-js-client-1.8.0.tgz",
-          "integrity": "sha512-qPX3TywqzxocTxUZtcS8X7Aik72SVMa0jKi4hWyfvRV+s9raVzzYGaP4MoJGaF0yOgm2+b6jXaVEHogxcJ8LGw==",
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/tus-js-client/-/tus-js-client-2.1.1.tgz",
+          "integrity": "sha512-ILpgHlR0nfKxmlkXfrZ2z61upkHEXhADOGbGyvXSPjp7bn1NhU50p/Mu59q577Xirayr9vlW4tmoFqUrHKcWeQ==",
           "requires": {
             "buffer-from": "^0.1.1",
             "combine-errors": "^3.0.3",
-            "extend": "^3.0.2",
             "js-base64": "^2.4.9",
             "lodash.throttle": "^4.1.1",
             "proper-lockfile": "^2.0.1",
@@ -7807,10 +7801,29 @@
     "@uppy/tus": {
       "version": "file:packages/@uppy/tus",
       "requires": {
-        "@types/tus-js-client": "^1.8.0",
         "@uppy/companion-client": "file:packages/@uppy/companion-client",
         "@uppy/utils": "file:packages/@uppy/utils",
-        "tus-js-client": "^1.8.0"
+        "tus-js-client": "^2.1.1"
+      },
+      "dependencies": {
+        "buffer-from": {
+          "version": "0.1.2",
+          "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-0.1.2.tgz",
+          "integrity": "sha512-RiWIenusJsmI2KcvqQABB83tLxCByE3upSP8QU3rJDMVFGPWLvPQJt/O1Su9moRWeH7d+Q2HYb68f6+v+tw2vg=="
+        },
+        "tus-js-client": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/tus-js-client/-/tus-js-client-2.1.1.tgz",
+          "integrity": "sha512-ILpgHlR0nfKxmlkXfrZ2z61upkHEXhADOGbGyvXSPjp7bn1NhU50p/Mu59q577Xirayr9vlW4tmoFqUrHKcWeQ==",
+          "requires": {
+            "buffer-from": "^0.1.1",
+            "combine-errors": "^3.0.3",
+            "js-base64": "^2.4.9",
+            "lodash.throttle": "^4.1.1",
+            "proper-lockfile": "^2.0.1",
+            "url-parse": "^1.4.3"
+          }
+        }
       }
     },
     "@uppy/url": {
@@ -36946,27 +36959,6 @@
         "safe-buffer": "^5.0.1"
       }
     },
-    "tus-js-client": {
-      "version": "1.8.0",
-      "resolved": "https://registry.npmjs.org/tus-js-client/-/tus-js-client-1.8.0.tgz",
-      "integrity": "sha512-qPX3TywqzxocTxUZtcS8X7Aik72SVMa0jKi4hWyfvRV+s9raVzzYGaP4MoJGaF0yOgm2+b6jXaVEHogxcJ8LGw==",
-      "requires": {
-        "buffer-from": "^0.1.1",
-        "combine-errors": "^3.0.3",
-        "extend": "^3.0.2",
-        "js-base64": "^2.4.9",
-        "lodash.throttle": "^4.1.1",
-        "proper-lockfile": "^2.0.1",
-        "url-parse": "^1.4.3"
-      },
-      "dependencies": {
-        "buffer-from": {
-          "version": "0.1.2",
-          "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-0.1.2.tgz",
-          "integrity": "sha512-RiWIenusJsmI2KcvqQABB83tLxCByE3upSP8QU3rJDMVFGPWLvPQJt/O1Su9moRWeH7d+Q2HYb68f6+v+tw2vg=="
-        }
-      }
-    },
     "tus-node-server": {
       "version": "0.3.2",
       "resolved": "https://registry.npmjs.org/tus-node-server/-/tus-node-server-0.3.2.tgz",

+ 0 - 1
package.json

@@ -105,7 +105,6 @@
     "@types/node": "12.12.27",
     "@types/react": "16.9.19",
     "@types/request": "2.48.4",
-    "@types/tus-js-client": "1.8.0",
     "@types/uuid": "3.4.7",
     "@types/ws": "6.0.4",
     "@wdio/cli": "5.18.6",

+ 1 - 1
packages/@uppy/companion/package.json

@@ -60,7 +60,7 @@
     "request": "2.88.0",
     "semver": "6.3.0",
     "serialize-error": "^2.1.0",
-    "tus-js-client": "1.8.0",
+    "tus-js-client": "2.1.1",
     "uuid": "3.3.3",
     "validator": "^12.1.0",
     "ws": "6.2.1"

+ 2 - 4
packages/@uppy/companion/src/server/Uploader.js

@@ -82,7 +82,7 @@ class Uploader {
         this._paused = true
         if (this.tus) {
           const shouldTerminate = !!this.tus.url
-          this.tus.abort(shouldTerminate)
+          this.tus.abort(shouldTerminate).catch(() => {})
         }
         this.cleanUp()
       })
@@ -414,15 +414,13 @@ class Uploader {
     const file = fs.createReadStream(this.path)
     const uploader = this
 
-    // @ts-ignore
     this.tus = new tus.Upload(file, {
       endpoint: this.options.endpoint,
       uploadUrl: this.options.uploadUrl,
-      // @ts-ignore
       uploadLengthDeferred: false,
-      resume: true,
       retryDelays: [0, 1000, 3000, 5000],
       uploadSize: this.bytesWritten,
+      addRequestId: true,
       metadata: Object.assign(
         {
           // file name and type as required by the tusd tus server

+ 6 - 5
packages/@uppy/transloadit/src/index.js

@@ -153,7 +153,9 @@ module.exports = class Transloadit extends Plugin {
     // Add Assembly-specific Tus endpoint.
     const tus = {
       ...file.tus,
-      endpoint: status.tus_url
+      endpoint: status.tus_url,
+      // Include X-Request-ID headers for better debugging.
+      addRequestId: true
     }
 
     // Set Companion location. We only add this, if 'file' has the attribute
@@ -748,9 +750,8 @@ module.exports = class Transloadit extends Plugin {
 
   _onTusError (err) {
     if (err && /^tus: /.test(err.message)) {
-      const url = err.originalRequest && err.originalRequest.responseURL
-        ? err.originalRequest.responseURL
-        : null
+      const xhr = err.originalRequest ? err.originalRequest.getUnderlyingObject() : null
+      const url = xhr && xhr.responseURL ? xhr.responseURL : null
       this.client.submitError(err, { url, type: 'TUS_ERROR' }).then((_) => {
         // if we can't report the error that sucks
       })
@@ -784,7 +785,7 @@ module.exports = class Transloadit extends Plugin {
         // were added to the Assembly, so we can properly complete it. All that state is handled by
         // Golden Retriever. So, Golden Retriever is required to do resumability with the Transloadit plugin,
         // and we disable Tus's default resume implementation to prevent bad behaviours.
-        resume: false,
+        storeFingerprintForResuming: false,
         // Disable Companion's retry optimisation; we need to change the endpoint on retry
         // so it can't just reuse the same tus.Upload instance server-side.
         useFastRemoteRetry: false,

+ 1 - 2
packages/@uppy/tus/package.json

@@ -22,10 +22,9 @@
     "url": "git+https://github.com/transloadit/uppy.git"
   },
   "dependencies": {
-    "@types/tus-js-client": "^1.8.0",
     "@uppy/companion-client": "file:../companion-client",
     "@uppy/utils": "file:../utils",
-    "tus-js-client": "^1.8.0"
+    "tus-js-client": "^2.1.1"
   },
   "peerDependencies": {
     "@uppy/core": "^1.0.0"

+ 3 - 3
packages/@uppy/tus/src/getFingerprint.js

@@ -23,9 +23,9 @@ function isReactNative () {
 // For React Native and Cordova, we let tus-js-client’s default
 // fingerprint handling take charge.
 module.exports = function getFingerprint (uppyFileObj) {
-  return function (file, options, callback) {
+  return function (file, options) {
     if (isCordova() || isReactNative()) {
-      return tus.Upload.defaultOptions.fingerprint(file, options, callback)
+      return tus.Upload.defaultOptions.fingerprint(file, options)
     }
 
     const uppyFingerprint = [
@@ -34,6 +34,6 @@ module.exports = function getFingerprint (uppyFileObj) {
       options.endpoint
     ].join('-')
 
-    return callback(null, uppyFingerprint)
+    return Promise.resolve(uppyFingerprint)
   }
 }

+ 66 - 26
packages/@uppy/tus/src/index.js

@@ -12,6 +12,7 @@ const hasProperty = require('@uppy/utils/lib/hasProperty')
 const getFingerprint = require('./getFingerprint')
 
 /** @typedef {import('..').TusOptions} TusOptions */
+/** @typedef {import('tus-js-client').UploadOptions} RawTusOptions */
 /** @typedef {import('@uppy/core').Uppy} Uppy */
 /** @typedef {import('@uppy/core').UppyFile} UppyFile */
 /** @typedef {import('@uppy/core').FailedUppyFile<{}>} FailedUppyFile */
@@ -20,22 +21,31 @@ const getFingerprint = require('./getFingerprint')
  * Extracted from https://github.com/tus/tus-js-client/blob/master/lib/upload.js#L13
  * excepted we removed 'fingerprint' key to avoid adding more dependencies
  *
- * @type {TusOptions}
+ * @type {RawTusOptions}
  */
 const tusDefaultOptions = {
   endpoint: '',
-  resume: true,
+
+  uploadUrl: null,
+  metadata: {},
+  uploadSize: null,
+
   onProgress: null,
   onChunkComplete: null,
   onSuccess: null,
   onError: null,
+
+  overridePatchMethod: false,
   headers: {},
+  addRequestId: false,
+
   chunkSize: Infinity,
-  withCredentials: false,
-  uploadUrl: null,
-  uploadSize: null,
-  overridePatchMethod: false,
-  retryDelays: null
+  retryDelays: [0, 1000, 3000, 5000],
+  parallelUploads: 1,
+  storeFingerprintForResuming: true,
+  removeFingerprintOnSuccess: false,
+  uploadLengthDeferred: false,
+  uploadDataDuringCreation: false
 }
 
 /**
@@ -56,8 +66,8 @@ module.exports = class Tus extends Plugin {
 
     // set default options
     const defaultOptions = {
-      resume: true,
       autoRetry: true,
+      resume: true,
       useFastRemoteRetry: true,
       limit: 0,
       retryDelays: [0, 1000, 3000, 5000]
@@ -162,25 +172,38 @@ module.exports = class Tus extends Plugin {
     return new Promise((resolve, reject) => {
       this.uppy.emit('upload-started', file)
 
-      const optsTus = Object.assign(
-        {},
-        tusDefaultOptions,
-        this.opts,
-        // Install file-specific upload overrides.
-        file.tus || {}
-      )
+      const opts = {
+        ...this.opts,
+        ...(file.tus || {})
+      }
+
+      /** @type {RawTusOptions} */
+      const uploadOptions = {
+        ...tusDefaultOptions,
+        // TODO only put tus-specific options in?
+        ...opts
+      }
+
+      delete uploadOptions.resume
+
+      // Make `resume: true` work like it did in tus-js-client v1.
+      // TODO: Remove in @uppy/tus v2
+      if (opts.resume) {
+        uploadOptions.storeFingerprintForResuming = true
+      }
 
       // We override tus fingerprint to uppy’s `file.id`, since the `file.id`
       // now also includes `relativePath` for files added from folders.
       // This means you can add 2 identical files, if one is in folder a,
       // the other in folder b.
-      optsTus.fingerprint = getFingerprint(file)
+      uploadOptions.fingerprint = getFingerprint(file)
 
-      optsTus.onError = (err) => {
+      uploadOptions.onError = (err) => {
         this.uppy.log(err)
 
-        if (isNetworkError(err.originalRequest)) {
-          err = new NetworkError(err, err.originalRequest)
+        const xhr = err.originalRequest ? err.originalRequest.getUnderlyingObject() : null
+        if (isNetworkError(xhr)) {
+          err = new NetworkError(err, xhr)
         }
 
         this.resetUploaderReferences(file.id)
@@ -191,7 +214,7 @@ module.exports = class Tus extends Plugin {
         reject(err)
       }
 
-      optsTus.onProgress = (bytesUploaded, bytesTotal) => {
+      uploadOptions.onProgress = (bytesUploaded, bytesTotal) => {
         this.onReceiveUploadUrl(file, upload.url)
         this.uppy.emit('upload-progress', file, {
           uploader: this,
@@ -200,7 +223,7 @@ module.exports = class Tus extends Plugin {
         })
       }
 
-      optsTus.onSuccess = () => {
+      uploadOptions.onSuccess = () => {
         const uploadResp = {
           uploadURL: upload.url
         }
@@ -223,9 +246,10 @@ module.exports = class Tus extends Plugin {
         }
       }
 
+      /** @type {{ [name: string]: string }} */
       const meta = {}
-      const metaFields = Array.isArray(optsTus.metaFields)
-        ? optsTus.metaFields
+      const metaFields = Array.isArray(opts.metaFields)
+        ? opts.metaFields
         // Send along all fields by default.
         : Object.keys(file.meta)
       metaFields.forEach((item) => {
@@ -236,15 +260,31 @@ module.exports = class Tus extends Plugin {
       copyProp(meta, 'type', 'filetype')
       copyProp(meta, 'name', 'filename')
 
-      optsTus.metadata = meta
+      uploadOptions.metadata = meta
 
-      const upload = new tus.Upload(file.data, optsTus)
+      const upload = new tus.Upload(file.data, uploadOptions)
       this.uploaders[file.id] = upload
       this.uploaderEvents[file.id] = new EventTracker(this.uppy)
 
+      // Make `resume: true` work like it did in tus-js-client v1.
+      // TODO: Remove in @uppy/tus v2.
+      if (opts.resume) {
+        upload.findPreviousUploads().then((previousUploads) => {
+          const previousUpload = previousUploads[0]
+          if (previousUploads) {
+            this.uppy.log(`[Tus] Resuming upload of ${file.id} started at ${previousUpload.creationTime}`)
+            upload.resumeFromPreviousUpload(previousUpload)
+          }
+        })
+      }
+
       let queuedRequest = this.requests.run(() => {
         if (!file.isPaused) {
-          upload.start()
+          // Ensure this gets scheduled to run _after_ `findPreviousUploads()` returns.
+          // TODO: Remove in @uppy/tus v2.
+          Promise.resolve().then(() => {
+            upload.start()
+          })
         }
         // Don't do anything here, the caller will take care of cancelling the upload itself
         // using resetUploaderReferences(). This is because resetUploaderReferences() has to be

+ 1 - 0
packages/@uppy/tus/types/index.d.ts

@@ -17,6 +17,7 @@ declare module Tus {
     metaFields?: string[] | null
     autoRetry?: boolean
     limit?: number
+    useFastRemoteRetry?: boolean
   }
 }