@uppy/tus
Advanced tools
Comparing version 3.5.0 to 3.5.1
# @uppy/tus | ||
## 3.5.1 | ||
Released: 2024-02-19 | ||
Included in: Uppy v3.22.0 | ||
- @uppy/aws-s3-multipart,@uppy/aws-s3,@uppy/companion-client,@uppy/tus,@uppy/xhr-upload: update `uppyfile` objects before emitting events (antoine du hamel / #4928) | ||
- @uppy/tus: migrate to ts (merlijn vos / #4899) | ||
- @uppy/companion,@uppy/tus: bump `tus-js-client` version range (merlijn vos / #4848) | ||
## 3.3.0 | ||
@@ -4,0 +13,0 @@ |
import * as tus from 'tus-js-client'; | ||
function isCordova() { | ||
return typeof window !== 'undefined' && (typeof window.PhoneGap !== 'undefined' || typeof window.Cordova !== 'undefined' || typeof window.cordova !== 'undefined'); | ||
return typeof window !== 'undefined' && ( | ||
// @ts-expect-error may exist | ||
typeof window.PhoneGap !== 'undefined' || | ||
// @ts-expect-error may exist | ||
typeof window.Cordova !== 'undefined' || | ||
// @ts-expect-error may exist | ||
typeof window.cordova !== 'undefined'); | ||
} | ||
@@ -17,3 +23,3 @@ function isReactNative() { | ||
// fingerprint handling take charge. | ||
export default function getFingerprint(uppyFileObj) { | ||
export default function getFingerprint(uppyFile) { | ||
return (file, options) => { | ||
@@ -23,5 +29,5 @@ if (isCordova() || isReactNative()) { | ||
} | ||
const uppyFingerprint = ['tus', uppyFileObj.id, options.endpoint].join('-'); | ||
const uppyFingerprint = ['tus', uppyFile.id, options.endpoint].join('-'); | ||
return Promise.resolve(uppyFingerprint); | ||
}; | ||
} |
147
lib/index.js
@@ -6,22 +6,20 @@ function _classPrivateFieldLooseBase(receiver, privateKey) { if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) { throw new TypeError("attempted to use private field on non-instance"); } return receiver; } | ||
import * as tus from 'tus-js-client'; | ||
import EventManager from '@uppy/utils/lib/EventManager'; | ||
import EventManager from '@uppy/core/lib/EventManager.js'; | ||
import NetworkError from '@uppy/utils/lib/NetworkError'; | ||
import isNetworkError from '@uppy/utils/lib/isNetworkError'; | ||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment | ||
// @ts-ignore untyped | ||
import { RateLimitedQueue } from '@uppy/utils/lib/RateLimitedQueue'; | ||
import hasProperty from '@uppy/utils/lib/hasProperty'; | ||
import { filterNonFailedFiles, filterFilesToEmitUploadStarted } from '@uppy/utils/lib/fileFilters'; | ||
import getFingerprint from './getFingerprint.js'; | ||
import getFingerprint from "./getFingerprint.js"; | ||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment | ||
// @ts-ignore We don't want TS to generate types for the package.json | ||
const packageJson = { | ||
"version": "3.5.0" | ||
"version": "3.5.1" | ||
}; | ||
/** @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 */ | ||
/** | ||
* 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 {RawTusOptions} | ||
*/ | ||
@@ -47,6 +45,7 @@ const tusDefaultOptions = { | ||
}; | ||
/** | ||
* Tus resumable file uploader | ||
*/ | ||
const defaultOptions = { | ||
limit: 20, | ||
retryDelays: tusDefaultOptions.retryDelays, | ||
withCredentials: false | ||
}; | ||
var _retryDelayIterator = /*#__PURE__*/_classPrivateFieldLooseKey("retryDelayIterator"); | ||
@@ -57,13 +56,12 @@ var _uploadLocalFile = /*#__PURE__*/_classPrivateFieldLooseKey("uploadLocalFile"); | ||
var _handleUpload = /*#__PURE__*/_classPrivateFieldLooseKey("handleUpload"); | ||
/** | ||
* Tus resumable file uploader | ||
*/ | ||
export default class Tus extends BasePlugin { | ||
/** | ||
* @param {Uppy} uppy | ||
* @param {TusOptions} opts | ||
*/ | ||
constructor(uppy, _opts) { | ||
var _this$opts$rateLimite, _this$opts$retryDelay; | ||
super(uppy, _opts); | ||
/** | ||
* @param {(UppyFile | FailedUppyFile)[]} files | ||
*/ | ||
super(uppy, { | ||
...defaultOptions, | ||
..._opts | ||
}); | ||
Object.defineProperty(this, _uploadFiles, { | ||
@@ -107,4 +105,2 @@ value: _uploadFiles2 | ||
* | ||
* @param {UppyFile} file for use with upload | ||
* @returns {Promise<void>} | ||
*/ | ||
@@ -118,5 +114,2 @@ Object.defineProperty(this, _uploadLocalFile, { | ||
}); | ||
/** | ||
* @param {string[]} fileIDs | ||
*/ | ||
Object.defineProperty(this, _handleUpload, { | ||
@@ -139,17 +132,2 @@ writable: true, | ||
this.id = this.opts.id || 'Tus'; | ||
this.title = 'Tus'; | ||
// set default options | ||
const defaultOptions = { | ||
limit: 20, | ||
retryDelays: tusDefaultOptions.retryDelays, | ||
withCredentials: false | ||
}; | ||
// merge default options with the ones set by user | ||
/** @type {import("..").TusOptions} */ | ||
this.opts = { | ||
...defaultOptions, | ||
..._opts | ||
}; | ||
if ((_opts == null ? void 0 : _opts.allowedMetaFields) === undefined && 'metaFields' in this.opts) { | ||
@@ -178,4 +156,5 @@ throw new Error('The `metaFields` option has been renamed to `allowedMetaFields`.'); | ||
Object.keys(files).forEach(fileID => { | ||
var _files$fileID; | ||
// Only clone the file object if it has a Tus `uploadUrl` attached. | ||
if (files[fileID].tus && files[fileID].tus.uploadUrl) { | ||
if ((_files$fileID = files[fileID]) != null && (_files$fileID = _files$fileID.tus) != null && _files$fileID.uploadUrl) { | ||
const tusState = { | ||
@@ -199,13 +178,8 @@ ...files[fileID].tus | ||
* any events related to the file, and the Companion WebSocket connection. | ||
* | ||
* @param {string} fileID | ||
*/ | ||
resetUploaderReferences(fileID, opts) { | ||
if (opts === void 0) { | ||
opts = {}; | ||
} | ||
if (this.uploaders[fileID]) { | ||
const uploader = this.uploaders[fileID]; | ||
uploader.abort(); | ||
if (opts.abort) { | ||
if (opts != null && opts.abort) { | ||
uploader.abort(true); | ||
@@ -223,5 +197,2 @@ } | ||
* restores state, we will continue uploading to the correct URL. | ||
* | ||
* @param {UppyFile} file | ||
* @param {string} uploadURL | ||
*/ | ||
@@ -278,7 +249,10 @@ onReceiveUploadUrl(file, uploadURL) { | ||
} | ||
/** @type {RawTusOptions} */ | ||
const { | ||
onShouldRetry, | ||
onBeforeRequest, | ||
...commonOpts | ||
} = opts; | ||
const uploadOptions = { | ||
...tusDefaultOptions, | ||
...opts | ||
...commonOpts | ||
}; | ||
@@ -291,14 +265,15 @@ | ||
uploadOptions.fingerprint = getFingerprint(file); | ||
uploadOptions.onBeforeRequest = req => { | ||
uploadOptions.onBeforeRequest = async req => { | ||
const xhr = req.getUnderlyingObject(); | ||
xhr.withCredentials = !!opts.withCredentials; | ||
let userProvidedPromise; | ||
if (typeof opts.onBeforeRequest === 'function') { | ||
userProvidedPromise = opts.onBeforeRequest(req, file); | ||
if (typeof onBeforeRequest === 'function') { | ||
userProvidedPromise = onBeforeRequest(req, file); | ||
} | ||
if (hasProperty(queuedRequest, 'shouldBeRequeued')) { | ||
if (!queuedRequest.shouldBeRequeued) return Promise.reject(); | ||
// TODO: switch to `Promise.withResolvers` on the next major if available. | ||
let done; | ||
// eslint-disable-next-line promise/param-names | ||
const p = new Promise(res => { | ||
// eslint-disable-line promise/param-names | ||
done = res; | ||
@@ -321,3 +296,4 @@ }); | ||
// `onBeforeRequest` option callback (in case it returns a promise). | ||
return Promise.all([p, userProvidedPromise]); | ||
await Promise.all([p, userProvidedPromise]); | ||
return undefined; | ||
} | ||
@@ -329,3 +305,3 @@ return userProvidedPromise; | ||
this.uppy.log(err); | ||
const xhr = err.originalRequest ? err.originalRequest.getUnderlyingObject() : null; | ||
const xhr = err.originalRequest != null ? err.originalRequest.getUnderlyingObject() : null; | ||
if (isNetworkError(xhr)) { | ||
@@ -336,3 +312,3 @@ // eslint-disable-next-line no-param-reassign | ||
this.resetUploaderReferences(file.id); | ||
(_queuedRequest = queuedRequest) == null ? void 0 : _queuedRequest.abort(); | ||
(_queuedRequest = queuedRequest) == null || _queuedRequest.abort(); | ||
this.uppy.emit('upload-error', file, err); | ||
@@ -349,3 +325,5 @@ if (typeof opts.onError === 'function') { | ||
} | ||
this.uppy.emit('upload-progress', file, { | ||
this.uppy.emit('upload-progress', this.uppy.getFile(file.id), { | ||
// TODO: remove `uploader` in next major | ||
// @ts-expect-error untyped | ||
uploader: this, | ||
@@ -357,10 +335,17 @@ bytesUploaded, | ||
uploadOptions.onSuccess = () => { | ||
var _upload$url; | ||
const uploadResp = { | ||
uploadURL: upload.url | ||
uploadURL: (_upload$url = upload.url) != null ? _upload$url : undefined, | ||
status: 200, | ||
body: {} | ||
}; | ||
this.resetUploaderReferences(file.id); | ||
queuedRequest.done(); | ||
this.uppy.emit('upload-success', file, uploadResp); | ||
this.uppy.emit('upload-success', this.uppy.getFile(file.id), uploadResp); | ||
if (upload.url) { | ||
this.uppy.log(`Download ${upload.file.name} from ${upload.url}`); | ||
// @ts-expect-error not typed in tus-js-client | ||
const { | ||
name | ||
} = upload.file; | ||
this.uppy.log(`Download ${name} from ${upload.url}`); | ||
} | ||
@@ -385,3 +370,3 @@ if (typeof opts.onSuccess === 'function') { | ||
} | ||
} else if (status > 400 && status < 500 && status !== 409 && status !== 423) { | ||
} else if (status != null && status > 400 && status < 500 && status !== 409 && status !== 423) { | ||
// HTTP 4xx, the server won't send anything, it's doesn't make sense to retry | ||
@@ -417,9 +402,4 @@ // HTTP 409 Conflict (happens if the Upload-Offset header does not match the one on the server) | ||
}; | ||
if (opts.onShouldRetry != null) { | ||
uploadOptions.onShouldRetry = function () { | ||
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { | ||
args[_key] = arguments[_key]; | ||
} | ||
return opts.onShouldRetry(...args, defaultOnShouldRetry); | ||
}; | ||
if (onShouldRetry != null) { | ||
uploadOptions.onShouldRetry = (error, retryAttempt) => onShouldRetry(error, retryAttempt, opts, defaultOnShouldRetry); | ||
} else { | ||
@@ -435,3 +415,5 @@ uploadOptions.onShouldRetry = defaultOnShouldRetry; | ||
/** @type {Record<string, string>} */ | ||
// We can't use `allowedMetaFields` to index generic M | ||
// and we also don't care about the type specifically here, | ||
// we just want to pass the meta fields along. | ||
const meta = {}; | ||
@@ -442,3 +424,7 @@ const allowedMetaFields = Array.isArray(opts.allowedMetaFields) ? opts.allowedMetaFields | ||
allowedMetaFields.forEach(item => { | ||
meta[item] = file.meta[item]; | ||
// tus type definition for metadata only accepts `Record<string, string>` | ||
// but in reality (at runtime) it accepts `Record<string, unknown>` | ||
// tus internally converts everything into a string, but let's do it here instead to be explicit. | ||
// because Uppy can have anything inside meta values, (for example relativePath: null is often sent by uppy) | ||
meta[item] = String(file.meta[item]); | ||
}); | ||
@@ -523,2 +509,3 @@ | ||
function _getCompanionClientArgs2(file) { | ||
var _file$remote; | ||
const opts = { | ||
@@ -532,3 +519,3 @@ ...this.opts | ||
return { | ||
...file.remote.body, | ||
...((_file$remote = file.remote) == null ? void 0 : _file$remote.body), | ||
endpoint: opts.endpoint, | ||
@@ -546,5 +533,3 @@ uploadUrl: opts.uploadUrl, | ||
this.uppy.emit('upload-start', filesToEmit); | ||
await Promise.allSettled(filesFiltered.map((file, i) => { | ||
const current = i + 1; | ||
const total = files.length; | ||
await Promise.allSettled(filesFiltered.map(file => { | ||
if (file.isRemote) { | ||
@@ -568,5 +553,5 @@ const getQueue = () => this.requests; | ||
} | ||
return _classPrivateFieldLooseBase(this, _uploadLocalFile)[_uploadLocalFile](file, current, total); | ||
return _classPrivateFieldLooseBase(this, _uploadLocalFile)[_uploadLocalFile](file); | ||
})); | ||
} | ||
Tus.VERSION = packageJson.version; |
{ | ||
"name": "@uppy/tus", | ||
"description": "Resumable uploads for Uppy using Tus.io", | ||
"version": "3.5.0", | ||
"version": "3.5.1", | ||
"license": "MIT", | ||
@@ -26,12 +26,12 @@ "main": "lib/index.js", | ||
"dependencies": { | ||
"@uppy/companion-client": "^3.7.0", | ||
"@uppy/utils": "^5.7.0", | ||
"tus-js-client": "^3.0.0" | ||
"@uppy/companion-client": "^3.7.1", | ||
"@uppy/utils": "^5.7.1", | ||
"tus-js-client": "^3.1.3" | ||
}, | ||
"devDependencies": { | ||
"vitest": "^0.34.5" | ||
"vitest": "^1.2.1" | ||
}, | ||
"peerDependencies": { | ||
"@uppy/core": "^3.8.0" | ||
"@uppy/core": "^3.9.0" | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
98339
1216
1
Updated@uppy/utils@^5.7.1
Updatedtus-js-client@^3.1.3