diff --git a/.eslintrc.js b/.eslintrc.js index 62b99a4a3d..ca87a3fbc8 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -197,8 +197,8 @@ module.exports = { // Packages that have switched to ESM sources: 'packages/@uppy/audio/src/**/*.js', - 'packages/@uppy/aws-s3/src/**/*.js', 'packages/@uppy/aws-s3-multipart/src/**/*.js', + 'packages/@uppy/aws-s3/src/**/*.js', 'packages/@uppy/box/src/**/*.js', 'packages/@uppy/companion-client/src/**/*.js', 'packages/@uppy/compressor/src/**/*.js', @@ -222,16 +222,17 @@ module.exports = { 'packages/@uppy/provider-views/src/**/*.js', 'packages/@uppy/react/src/**/*.js', 'packages/@uppy/redux-dev-tools/src/**/*.js', + 'packages/@uppy/remote-sources/src/**/*.js', 'packages/@uppy/screen-capture/src/**/*.js', 'packages/@uppy/status-bar/src/**/*.js', 'packages/@uppy/store-default/src/**/*.js', 'packages/@uppy/store-redux/src/**/*.js', - 'packages/@uppy/svelte/src/**/*.js', 'packages/@uppy/svelte/rollup.config.js', + 'packages/@uppy/svelte/src/**/*.js', 'packages/@uppy/thumbnail-generator/src/**/*.js', + 'packages/@uppy/transloadit/src/**/*.js', 'packages/@uppy/tus/src/**/*.js', 'packages/@uppy/unsplash/src/**/*.js', - 'packages/@uppy/transloadit/src/**/*.js', 'packages/@uppy/url/src/**/*.js', 'packages/@uppy/utils/src/**/*.js', 'packages/@uppy/vue/src/**/*.js', diff --git a/.github/workflows/release-beta-candidate.yml b/.github/workflows/release-beta-candidate.yml index 1187a6ee9d..aafc5fbf11 100644 --- a/.github/workflows/release-beta-candidate.yml +++ b/.github/workflows/release-beta-candidate.yml @@ -14,13 +14,8 @@ jobs: - name: Checkout sources uses: actions/checkout@v3 with: - branch: release - - name: Rebase - run: | - git fetch origin ${{ env.BETA_BRANCH }} --depth=1 - git config --global user.email "actions@github.com" - git config --global user.name "GitHub Actions" - git rebase FETCH_HEAD + branch: release-beta + fetch-depth: 3 # the prepare commit, the merge commit, and the base ones. - name: Get yarn cache directory path id: yarn-cache-dir-path run: echo "::set-output name=dir::$(corepack yarn config get cacheFolder)" @@ -56,6 +51,8 @@ jobs: echo "This is a release candidate for the following packages:" >> commitMessage echo >> commitMessage jq -r 'map("- `"+.ident+"`: "+.oldVersion+" -> "+.newVersion) | join("\n") ' < releases.json >> commitMessage + git config --global user.email "actions@github.com" + git config --global user.name "GitHub Actions" git commit -n --amend --file commitMessage - name: Open Pull Request id: pr_opening diff --git a/CHANGELOG.md b/CHANGELOG.md index c597d1b62a..e053ba4812 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -50,6 +50,47 @@ Released: 2022-05-30 - @uppy/transloadit: remove IE 10 hack (Antoine du Hamel / #3777) +## 2.12.1 + +Released: 2022-06-09 + +| Package | Version | Package | Version | +| ----------------- | ------- | ----------------- | ------- | +| @uppy/transloadit | 2.3.1 | uppy | 2.12.1 | +| @uppy/robodog | 2.8.1 | | | + +- @uppy/transloadit: fix `COMPANION_PATTERN` export (Antoine du Hamel / #3820) +- meta: fix URL generation in the release script (Antoine du Hamel) + + +## 2.12.0 + +Released: 2022-06-07 + +| Package | Version | Package | Version | +| ---------------------- | ------- | ---------------------- | ------- | +| @uppy/aws-s3 | 2.2.1 | @uppy/tus | 2.4.1 | +| @uppy/aws-s3-multipart | 2.4.1 | @uppy/url | 2.2.0 | +| @uppy/companion-client | 2.2.1 | @uppy/xhr-upload | 2.1.2 | +| @uppy/core | 2.3.1 | @uppy/robodog | 2.8.0 | +| @uppy/react | 2.2.2 | uppy | 2.12.0 | +| @uppy/remote-sources | 0.1.0 | | | + +- @uppy/remote-sources: Add @uppy/remote-sources preset/plugin (Artur Paikin / #3676) +- @uppy/react: Reset uppy instance when React component is unmounted (Tomasz Pęksa / #3814) +- @uppy/aws-s3-multipart,@uppy/aws-s3,@uppy/tus: queue socket token requests for remote files (Merlijn Vos / #3797) +- @uppy/xhr-upload: replace `ev.target.status` with `xhr.status` (Wes Sankey / #3782) +- @uppy/core: fix `TypeError` when file was deleted (Antoine du Hamel / #3811) +- @uppy/robodog: fix linter warnings (Antoine du Hamel / #3808) +- meta: fix GHA workflow for prereleases (Antoine du Hamel) +- @uppy/aws-s3-multipart: allow `companionHeaders` to be modified with `setOptions` (Paulo Lemos Neto / #3770) +- @uppy/url: enable passing optional meta data to `addFile` (Brad Edelman / #3788) +- @uppy/url: fix `getFileNameFromUrl` (Brad Edelman / #3804) +- @uppy/tus: make onShouldRetry type optional (Merlijn Vos / #3800) +- doc: fix React examples (Antoine du Hamel / #3799) +- meta: add GHA workflow for prereleases (Antoine du Hamel) + + ## 2.11.0 Released: 2022-05-30 diff --git a/packages/@uppy/aws-s3-multipart/CHANGELOG.md b/packages/@uppy/aws-s3-multipart/CHANGELOG.md index f476ff94fe..6d2dc9408f 100644 --- a/packages/@uppy/aws-s3-multipart/CHANGELOG.md +++ b/packages/@uppy/aws-s3-multipart/CHANGELOG.md @@ -1,5 +1,13 @@ # @uppy/aws-s3-multipart +## 2.4.1 + +Released: 2022-06-07 +Included in: Uppy v2.12.0 + +- @uppy/aws-s3-multipart,@uppy/aws-s3,@uppy/tus: queue socket token requests for remote files (Merlijn Vos / #3797) +- @uppy/aws-s3-multipart: allow `companionHeaders` to be modified with `setOptions` (Paulo Lemos Neto / #3770) + ## 2.4.0 Released: 2022-05-30 diff --git a/packages/@uppy/aws-s3-multipart/src/index.js b/packages/@uppy/aws-s3-multipart/src/index.js index 6161d99c82..259dfe88b3 100644 --- a/packages/@uppy/aws-s3-multipart/src/index.js +++ b/packages/@uppy/aws-s3-multipart/src/index.js @@ -20,12 +20,16 @@ function assertServerError (res) { export default class AwsS3Multipart extends BasePlugin { static VERSION = packageJson.version + #queueRequestSocketToken + + #client + constructor (uppy, opts) { super(uppy, opts) this.type = 'uploader' this.id = this.opts.id || 'AwsS3Multipart' this.title = 'AWS S3 Multipart' - this.client = new RequestClient(uppy, opts) + this.#client = new RequestClient(uppy, opts) const defaultOptions = { timeout: 30 * 1000, @@ -36,6 +40,7 @@ export default class AwsS3Multipart extends BasePlugin { prepareUploadParts: this.prepareUploadParts.bind(this), abortMultipartUpload: this.abortMultipartUpload.bind(this), completeMultipartUpload: this.completeMultipartUpload.bind(this), + companionHeaders: {}, } this.opts = { ...defaultOptions, ...opts } @@ -47,8 +52,17 @@ export default class AwsS3Multipart extends BasePlugin { this.uploaders = Object.create(null) this.uploaderEvents = Object.create(null) this.uploaderSockets = Object.create(null) + + this.#queueRequestSocketToken = this.requests.wrapPromiseFunction(this.#requestSocketToken) } + [Symbol.for('uppy test: getClient')] () { return this.#client } + + // TODO: remove getter and setter for #client on the next major release + get client () { return this.#client } + + set client (client) { this.#client = client } + /** * Clean up all references for a file's upload: the MultipartUploader instance, * any events related to the file, and the Companion WebSocket connection. @@ -88,7 +102,7 @@ export default class AwsS3Multipart extends BasePlugin { } }) - return this.client.post('s3/multipart', { + return this.#client.post('s3/multipart', { filename: file.name, type: file.type, metadata, @@ -99,7 +113,7 @@ export default class AwsS3Multipart extends BasePlugin { this.assertHost('listParts') const filename = encodeURIComponent(key) - return this.client.get(`s3/multipart/${uploadId}?key=${filename}`) + return this.#client.get(`s3/multipart/${uploadId}?key=${filename}`) .then(assertServerError) } @@ -107,7 +121,7 @@ export default class AwsS3Multipart extends BasePlugin { this.assertHost('prepareUploadParts') const filename = encodeURIComponent(key) - return this.client.get(`s3/multipart/${uploadId}/batch?key=${filename}&partNumbers=${partNumbers.join(',')}`) + return this.#client.get(`s3/multipart/${uploadId}/batch?key=${filename}&partNumbers=${partNumbers.join(',')}`) .then(assertServerError) } @@ -116,7 +130,7 @@ export default class AwsS3Multipart extends BasePlugin { const filename = encodeURIComponent(key) const uploadIdEnc = encodeURIComponent(uploadId) - return this.client.post(`s3/multipart/${uploadIdEnc}/complete?key=${filename}`, { parts }) + return this.#client.post(`s3/multipart/${uploadIdEnc}/complete?key=${filename}`, { parts }) .then(assertServerError) } @@ -125,7 +139,7 @@ export default class AwsS3Multipart extends BasePlugin { const filename = encodeURIComponent(key) const uploadIdEnc = encodeURIComponent(uploadId) - return this.client.delete(`s3/multipart/${uploadIdEnc}?key=${filename}`) + return this.#client.delete(`s3/multipart/${uploadIdEnc}?key=${filename}`) .then(assertServerError) } @@ -279,7 +293,26 @@ export default class AwsS3Multipart extends BasePlugin { }) } - uploadRemote (file) { + #requestSocketToken = async (file) => { + const Client = file.remote.providerOptions.provider ? Provider : RequestClient + const client = new Client(this.uppy, file.remote.providerOptions) + const opts = { ...this.opts } + + if (file.tus) { + // Install file-specific upload overrides. + Object.assign(opts, file.tus) + } + + const res = await client.post(file.remote.url, { + ...file.remote.body, + protocol: 's3-multipart', + size: file.data.size, + metadata: file.meta, + }) + return res.token + } + + async uploadRemote (file) { this.resetUploaderReferences(file.id) // Don't double-emit upload-started for Golden Retriever-restored files that were already started @@ -287,33 +320,18 @@ export default class AwsS3Multipart extends BasePlugin { this.uppy.emit('upload-started', file) } - if (file.serverToken) { - return this.connectToServerSocket(file) - } - - return new Promise((resolve, reject) => { - const Client = file.remote.providerOptions.provider ? Provider : RequestClient - const client = new Client(this.uppy, file.remote.providerOptions) - client.post( - file.remote.url, - { - ...file.remote.body, - protocol: 's3-multipart', - size: file.data.size, - metadata: file.meta, - }, - ).then((res) => { - this.uppy.setFileState(file.id, { serverToken: res.token }) - // eslint-disable-next-line no-param-reassign - file = this.uppy.getFile(file.id) + try { + if (file.serverToken) { return this.connectToServerSocket(file) - }).then(() => { - resolve() - }).catch((err) => { - this.uppy.emit('upload-error', file, err) - reject(err) - }) - }) + } + const serverToken = await this.#queueRequestSocketToken(file) + + this.uppy.setFileState(file.id, { serverToken }) + return this.connectToServerSocket(this.uppy.getFile(file.id)) + } catch (err) { + this.uppy.emit('upload-error', file, err) + throw err + } } connectToServerSocket (file) { @@ -322,7 +340,7 @@ export default class AwsS3Multipart extends BasePlugin { const token = file.serverToken const host = getSocketHost(file.remote.companionUrl) - const socket = new Socket({ target: `${host}/api/${token}`, autoOpen: false }) + const socket = new Socket({ target: `${host}/api/${token}` }) this.uploaderSockets[file.id] = socket this.uploaderEvents[file.id] = new EventTracker(this.uppy) @@ -412,7 +430,6 @@ export default class AwsS3Multipart extends BasePlugin { }) queuedRequest = this.requests.run(() => { - socket.open() if (file.isPaused) { socket.send('pause', {}) } @@ -436,6 +453,11 @@ export default class AwsS3Multipart extends BasePlugin { return Promise.all(promises) } + #setCompanionHeaders = () => { + this.#client.setCompanionHeaders(this.opts.companionHeaders) + return Promise.resolve() + } + onFileRemove (fileID, cb) { this.uploaderEvents[fileID].on('file-removed', (file) => { if (fileID === file.id) cb(file.id) @@ -495,6 +517,7 @@ export default class AwsS3Multipart extends BasePlugin { resumableUploads: true, }, }) + this.uppy.addPreProcessor(this.#setCompanionHeaders) this.uppy.addUploader(this.upload) } @@ -506,6 +529,7 @@ export default class AwsS3Multipart extends BasePlugin { resumableUploads: false, }, }) + this.uppy.removePreProcessor(this.#setCompanionHeaders) this.uppy.removeUploader(this.upload) } } diff --git a/packages/@uppy/aws-s3-multipart/src/index.test.js b/packages/@uppy/aws-s3-multipart/src/index.test.js index 6a57f888dd..89aa67b7b4 100644 --- a/packages/@uppy/aws-s3-multipart/src/index.test.js +++ b/packages/@uppy/aws-s3-multipart/src/index.test.js @@ -227,4 +227,35 @@ describe('AwsS3Multipart', () => { expect(awsS3Multipart.opts.prepareUploadParts.mock.calls.length).toEqual(2) }) }) + + describe('dynamic companionHeader', () => { + let core + let awsS3Multipart + const oldToken = 'old token' + const newToken = 'new token' + + beforeEach(() => { + core = new Core() + core.use(AwsS3Multipart, { + companionHeaders: { + authorization: oldToken, + }, + }) + awsS3Multipart = core.getPlugin('AwsS3Multipart') + }) + + it('companionHeader is updated before uploading file', async () => { + awsS3Multipart.setOptions({ + companionHeaders: { + authorization: newToken, + }, + }) + + await core.upload() + + const client = awsS3Multipart[Symbol.for('uppy test: getClient')]() + + expect(client[Symbol.for('uppy test: getCompanionHeaders')]().authorization).toEqual(newToken) + }) + }) }) diff --git a/packages/@uppy/aws-s3/CHANGELOG.md b/packages/@uppy/aws-s3/CHANGELOG.md index 427def09d5..d7e4e6777e 100644 --- a/packages/@uppy/aws-s3/CHANGELOG.md +++ b/packages/@uppy/aws-s3/CHANGELOG.md @@ -1,5 +1,12 @@ # @uppy/aws-s3 +## 2.2.1 + +Released: 2022-06-07 +Included in: Uppy v2.12.0 + +- @uppy/aws-s3-multipart,@uppy/aws-s3,@uppy/tus: queue socket token requests for remote files (Merlijn Vos / #3797) + ## 2.2.0 Released: 2022-05-30 diff --git a/packages/@uppy/aws-s3/src/MiniXHRUpload.js b/packages/@uppy/aws-s3/src/MiniXHRUpload.js index c300a7c423..b2a5cded79 100644 --- a/packages/@uppy/aws-s3/src/MiniXHRUpload.js +++ b/packages/@uppy/aws-s3/src/MiniXHRUpload.js @@ -53,6 +53,8 @@ function createFormDataUpload (file, opts) { const createBareUpload = file => file.data export default class MiniXHRUpload { + #queueRequestSocketToken + constructor (uppy, opts) { this.uppy = uppy this.opts = { @@ -65,6 +67,8 @@ export default class MiniXHRUpload { this.requests = opts[internalRateLimitedQueue] this.uploaderEvents = Object.create(null) this.i18n = opts.i18n + + this.#queueRequestSocketToken = this.requests.wrapPromiseFunction(this.#requestSocketToken) } #getOptions (file) { @@ -243,19 +247,21 @@ export default class MiniXHRUpload { }) } - #uploadRemoteFile (file) { + #requestSocketToken = async (file) => { const opts = this.#getOptions(file) - // This is done in index.js in the S3 plugin. - // this.uppy.emit('upload-started', file) - + const Client = file.remote.providerOptions.provider ? Provider : RequestClient + const client = new Client(this.uppy, file.remote.providerOptions) const metaFields = Array.isArray(opts.metaFields) ? opts.metaFields - // Send along all fields by default. + // Send along all fields by default. : Object.keys(file.meta) - const Client = file.remote.providerOptions.provider ? Provider : RequestClient - const client = new Client(this.uppy, file.remote.providerOptions) - return client.post(file.remote.url, { + if (file.tus) { + // Install file-specific upload overrides. + Object.assign(opts, file.tus) + } + + const res = await client.post(file.remote.url, { ...file.remote.body, endpoint: opts.endpoint, size: file.data.size, @@ -264,14 +270,34 @@ export default class MiniXHRUpload { httpMethod: opts.method, useFormData: opts.formData, headers: opts.headers, - }).then(res => new Promise((resolve, reject) => { - const { token } = res + }) + return res.token + } + + async #uploadRemoteFile (file) { + try { + if (file.serverToken) { + return this.connectToServerSocket(file) + } + const serverToken = await this.#queueRequestSocketToken(file) + + this.uppy.setFileState(file.id, { serverToken }) + return this.connectToServerSocket(this.uppy.getFile(file.id)) + } catch (err) { + this.uppy.emit('upload-error', file, err) + throw err + } + } + + connectToServerSocket (file) { + return new Promise((resolve, reject) => { + const opts = this.#getOptions(file) + const token = file.serverToken const host = getSocketHost(file.remote.companionUrl) - const socket = new Socket({ target: `${host}/api/${token}`, autoOpen: false }) + const socket = new Socket({ target: `${host}/api/${token}` }) this.uploaderEvents[file.id] = new EventTracker(this.uppy) const queuedRequest = this.requests.run(() => { - socket.open() if (file.isPaused) { socket.send('pause', {}) } @@ -341,6 +367,6 @@ export default class MiniXHRUpload { }).catch((err) => { this.uppy.emit('upload-error', file, err) return Promise.reject(err) - })) + }) } } diff --git a/packages/@uppy/aws-s3/src/index.js b/packages/@uppy/aws-s3/src/index.js index 0f2c697121..75e342d6c7 100644 --- a/packages/@uppy/aws-s3/src/index.js +++ b/packages/@uppy/aws-s3/src/index.js @@ -117,6 +117,7 @@ export default class AwsS3 extends BasePlugin { limit: 0, metaFields: [], // have to opt in getUploadParameters: this.getUploadParameters.bind(this), + companionHeaders: {}, } this.opts = { ...defaultOptions, ...opts } @@ -128,6 +129,13 @@ export default class AwsS3 extends BasePlugin { this.#requests = new RateLimitedQueue(this.opts.limit) } + [Symbol.for('uppy test: getClient')] () { return this.#client } + + // TODO: remove getter and setter for #client on the next major release + get client () { return this.#client } + + set client (client) { this.#client = client } + getUploadParameters (file) { if (!this.opts.companionUrl) { throw new Error('Expected a `companionUrl` option containing a Companion address.') @@ -216,8 +224,14 @@ export default class AwsS3 extends BasePlugin { }) } + #setCompanionHeaders = () => { + this.#client.setCompanionHeaders(this.opts.companionHeaders) + return Promise.resolve() + } + install () { const { uppy } = this + uppy.addPreProcessor(this.#setCompanionHeaders) uppy.addUploader(this.#handleUpload) // Get the response data from a successful XMLHttpRequest instance. @@ -279,6 +293,7 @@ export default class AwsS3 extends BasePlugin { } uninstall () { + this.uppy.removePreProcessor(this.#setCompanionHeaders) this.uppy.removeUploader(this.#handleUpload) } } diff --git a/packages/@uppy/aws-s3/src/index.test.js b/packages/@uppy/aws-s3/src/index.test.js index 2f85949a23..ac6d8cfdff 100644 --- a/packages/@uppy/aws-s3/src/index.test.js +++ b/packages/@uppy/aws-s3/src/index.test.js @@ -35,4 +35,35 @@ describe('AwsS3', () => { expect(() => awsS3.opts.getUploadParameters(file)).not.toThrow() }) }) + + describe('dynamic companionHeader', () => { + let core + let awsS3 + const oldToken = 'old token' + const newToken = 'new token' + + beforeEach(() => { + core = new Core() + core.use(AwsS3, { + companionHeaders: { + authorization: oldToken, + }, + }) + awsS3 = core.getPlugin('AwsS3') + }) + + it('companionHeader is updated before uploading file', async () => { + awsS3.setOptions({ + companionHeaders: { + authorization: newToken, + }, + }) + + await core.upload() + + const client = awsS3[Symbol.for('uppy test: getClient')]() + + expect(client[Symbol.for('uppy test: getCompanionHeaders')]().authorization).toEqual(newToken) + }) + }) }) diff --git a/packages/@uppy/companion-client/src/RequestClient.js b/packages/@uppy/companion-client/src/RequestClient.js index 36430b22e8..637008bdd7 100644 --- a/packages/@uppy/companion-client/src/RequestClient.js +++ b/packages/@uppy/companion-client/src/RequestClient.js @@ -35,6 +35,8 @@ async function handleJSONResponse (res) { export default class RequestClient { static VERSION = packageJson.version + #companionHeaders + #getPostResponseFunc = skip => response => (skip ? response : this.onReceiveResponse(response)) constructor (uppy, opts) { @@ -43,8 +45,15 @@ export default class RequestClient { this.onReceiveResponse = this.onReceiveResponse.bind(this) this.allowedHeaders = ['accept', 'content-type', 'uppy-auth-token'] this.preflightDone = false + this.#companionHeaders = opts?.companionHeaders + } + + setCompanionHeaders (headers) { + this.#companionHeaders = headers } + [Symbol.for('uppy test: getCompanionHeaders')] () { return this.#companionHeaders } + get hostname () { const { companion } = this.uppy.getState() const host = this.opts.companionUrl @@ -58,10 +67,9 @@ export default class RequestClient { } headers () { - const userHeaders = this.opts.companionHeaders || {} return Promise.resolve({ ...RequestClient.defaultHeaders, - ...userHeaders, + ...this.#companionHeaders, }) } diff --git a/packages/@uppy/core/CHANGELOG.md b/packages/@uppy/core/CHANGELOG.md index 263a392d4e..59debd9d5e 100644 --- a/packages/@uppy/core/CHANGELOG.md +++ b/packages/@uppy/core/CHANGELOG.md @@ -1,5 +1,12 @@ # @uppy/core +## 2.3.1 + +Released: 2022-06-07 +Included in: Uppy v2.12.0 + +- @uppy/core: fix `TypeError` when file was deleted (Antoine du Hamel / #3811) + ## 2.3.0 Released: 2022-05-30 diff --git a/packages/@uppy/core/src/Uppy.js b/packages/@uppy/core/src/Uppy.js index 7c39b796db..af48cd779b 100644 --- a/packages/@uppy/core/src/Uppy.js +++ b/packages/@uppy/core/src/Uppy.js @@ -967,7 +967,7 @@ class Uppy { if (error.details) { newError.details += ` ${error.details}` } - newError.message = this.i18n('failedToUpload', { file: file.name }) + newError.message = this.i18n('failedToUpload', { file: file?.name }) this.#informAndEmit(newError) } else { this.#informAndEmit(error) diff --git a/packages/@uppy/react/CHANGELOG.md b/packages/@uppy/react/CHANGELOG.md index 2083360c8c..818f53556f 100644 --- a/packages/@uppy/react/CHANGELOG.md +++ b/packages/@uppy/react/CHANGELOG.md @@ -7,6 +7,13 @@ Included in: Uppy v3.0.0-beta - @uppy/react: refactor to ESM (Antoine du Hamel / #3780) +## 2.2.2 + +Released: 2022-06-07 +Included in: Uppy v2.12.0 + +- @uppy/react: Reset uppy instance when React component is unmounted (Tomasz Pęksa / #3814) + ## 2.2.1 Released: 2022-05-30 diff --git a/packages/@uppy/react/src/useUppy.js b/packages/@uppy/react/src/useUppy.js index 39e047360c..12e7868d34 100644 --- a/packages/@uppy/react/src/useUppy.js +++ b/packages/@uppy/react/src/useUppy.js @@ -18,8 +18,9 @@ export default function useUppy (factory) { useEffect(() => { return () => { uppy.current.close({ reason: 'unmount' }) + uppy.current = undefined } - }, []) + }, [uppy]) return uppy.current } diff --git a/packages/@uppy/remote-sources/CHANGELOG.md b/packages/@uppy/remote-sources/CHANGELOG.md new file mode 100644 index 0000000000..d53b56a41c --- /dev/null +++ b/packages/@uppy/remote-sources/CHANGELOG.md @@ -0,0 +1,8 @@ +# @uppy/remote-sources + +## 0.1.0 + +Released: 2022-06-07 +Included in: Uppy v2.12.0 + +- @uppy/remote-sources: Add @uppy/remote-sources preset/plugin (Artur Paikin / #3676) diff --git a/packages/@uppy/remote-sources/LICENSE b/packages/@uppy/remote-sources/LICENSE new file mode 100644 index 0000000000..d01ae72874 --- /dev/null +++ b/packages/@uppy/remote-sources/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2022 Transloadit + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/@uppy/remote-sources/README.md b/packages/@uppy/remote-sources/README.md new file mode 100644 index 0000000000..83c6950fc0 --- /dev/null +++ b/packages/@uppy/remote-sources/README.md @@ -0,0 +1,35 @@ +# @uppy/remote-sources + +Uppy logo: a superman puppy in a pink suit + + CI status for Uppy tests CI status for Companion tests CI status for browser tests + +## Example + +```js +import Uppy from '@uppy/core' +import RemoteSources from '@uppy/remote-sources' + +const uppy = new Uppy() +uppy.use(RemoteSources, { + companionUrl: 'https://your-companion-url', +}) +``` + +## Installation + +```bash +npm install @uppy/remote-sources +# or +yarn add @uppy/remote-sources +``` + +Alternatively, you can also use this plugin in a pre-built bundle from Transloadit’s CDN: Edgly. In that case `Uppy.RemoteSources` will attach itself to the global `window.Uppy` object. See the [main Uppy documentation](https://uppy.io/docs/#Installation) for instructions. + +## Documentation + +Documentation for this plugin can be found on the [Uppy website](https://uppy.io/docs/remote-sources). + +## License + +[The MIT License](./LICENSE). diff --git a/packages/@uppy/remote-sources/package.json b/packages/@uppy/remote-sources/package.json new file mode 100644 index 0000000000..54f4352686 --- /dev/null +++ b/packages/@uppy/remote-sources/package.json @@ -0,0 +1,51 @@ +{ + "name": "@uppy/remote-sources", + "description": "Uppy plugin that includes all remote sources that Uppy+Companion offer, like Instagram, Google Drive, Dropox, Box, Unsplash, Url etc", + "version": "0.1.0", + "license": "MIT", + "main": "lib/index.js", + "types": "types/index.d.ts", + "type": "module", + "keywords": [ + "file uploader", + "instagram", + "google-drive", + "facebook", + "dropbox", + "onedrive", + "zoom", + "unsplash", + "box", + "url" + ], + "homepage": "https://uppy.io", + "bugs": { + "url": "https://github.com/transloadit/uppy/issues" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/transloadit/uppy.git" + }, + "dependencies": { + "@uppy/box": "workspace:^", + "@uppy/dashboard": "workspace:^", + "@uppy/dropbox": "workspace:^", + "@uppy/facebook": "workspace:^", + "@uppy/google-drive": "workspace:^", + "@uppy/instagram": "workspace:^", + "@uppy/onedrive": "workspace:^", + "@uppy/unsplash": "workspace:^", + "@uppy/url": "workspace:^", + "@uppy/zoom": "workspace:^" + }, + "peerDependencies": { + "@uppy/core": "workspace:^" + }, + "publishConfig": { + "access": "public" + }, + "devDependencies": { + "@jest/globals": "^28.1.0", + "resize-observer-polyfill": "^1.5.1" + } +} diff --git a/packages/@uppy/remote-sources/src/index.js b/packages/@uppy/remote-sources/src/index.js new file mode 100644 index 0000000000..a332c89eba --- /dev/null +++ b/packages/@uppy/remote-sources/src/index.js @@ -0,0 +1,83 @@ +import { BasePlugin } from '@uppy/core' +import Dashboard from '@uppy/dashboard' +import Dropbox from '@uppy/dropbox' +import GoogleDrive from '@uppy/google-drive' +import Instagram from '@uppy/instagram' +import Facebook from '@uppy/facebook' +import OneDrive from '@uppy/onedrive' +import Box from '@uppy/box' +import Unsplash from '@uppy/unsplash' +import Url from '@uppy/url' +import Zoom from '@uppy/zoom' + +import packageJson from '../package.json' + +const availablePlugins = [ + Box, + Dropbox, + Facebook, + GoogleDrive, + Instagram, + OneDrive, + Unsplash, + Url, + Zoom, +] + +export default class RemoteSources extends BasePlugin { + static VERSION = packageJson.version + + #installedPlugins = new Set() + + constructor (uppy, opts) { + super(uppy, opts) + this.id = this.opts.id || 'RemoteSources' + this.type = 'acquirer' + + const defaultOptions = { + sources: [ + 'Box', + 'Dropbox', + 'Facebook', + 'GoogleDrive', + 'Instagram', + 'OneDrive', + 'Unsplash', + 'Url', + ], + target: Dashboard, + } + this.opts = { ...defaultOptions, ...opts } + + if (this.opts.companionUrl == null) { + throw new Error('Please specify companionUrl for RemoteSources to work, see https://uppy.io/docs/remote-sources#companionUrl') + } + } + + setOptions (newOpts) { + this.uninstall() + super.setOptions(newOpts) + this.install() + } + + install () { + this.opts.sources.forEach((pluginId) => { + const optsForRemoteSourcePlugin = { ...this.opts, sources: undefined } + const plugin = availablePlugins.find(p => p.name === pluginId) + if (plugin == null) { + const pluginNames = availablePlugins.map(p => p.name) + const formatter = new Intl.ListFormat('en', { style: 'long', type: 'disjunction' }) + throw new Error(`Invalid plugin: "${pluginId}" is not one of: ${formatter.format(pluginNames)}.`) + } + this.uppy.use(plugin, optsForRemoteSourcePlugin) + this.#installedPlugins.add(plugin) + }) + } + + uninstall () { + for (const plugin of this.#installedPlugins) { + this.uppy.removePlugin(plugin) + } + this.#installedPlugins.clear() + } +} diff --git a/packages/@uppy/remote-sources/src/index.test.js b/packages/@uppy/remote-sources/src/index.test.js new file mode 100644 index 0000000000..2e02ac4d90 --- /dev/null +++ b/packages/@uppy/remote-sources/src/index.test.js @@ -0,0 +1,42 @@ +import { describe, expect, it } from '@jest/globals' +import resizeObserverPolyfill from 'resize-observer-polyfill' +import Core from '@uppy/core' +import Dashboard from '@uppy/dashboard' +import RemoteSources from './index.js' + +describe('RemoteSources', () => { + beforeAll(() => { + globalThis.ResizeObserver = resizeObserverPolyfill.default || resizeObserverPolyfill + }) + + afterAll(() => { + delete globalThis.ResizeObserver + }) + + it('should install RemoteSources with default options', () => { + expect(() => { + const core = new Core() + core.use(Dashboard) + core.use(RemoteSources, { companionUrl: 'https://example.com' }) + }).not.toThrow() + }) + + it('should throw when a companionUrl is not specified', () => { + expect(() => { + const core = new Core() + core.use(Dashboard) + core.use(RemoteSources, { sources: ['Webcam'] }) + }).toThrow(new Error('Please specify companionUrl for RemoteSources to work, see https://uppy.io/docs/remote-sources#companionUrl')) + }) + + it('should throw when trying to use a plugin which is not included in RemoteSources', () => { + expect(() => { + const core = new Core() + core.use(Dashboard) + core.use(RemoteSources, { + companionUrl: 'https://example.com', + sources: ['Webcam'], + }) + }).toThrow('Invalid plugin: "Webcam" is not one of: Box, Dropbox, Facebook, GoogleDrive, Instagram, OneDrive, Unsplash, Url, or Zoom.') + }) +}) diff --git a/packages/@uppy/remote-sources/types/index.d.ts b/packages/@uppy/remote-sources/types/index.d.ts new file mode 100644 index 0000000000..3ac7afd332 --- /dev/null +++ b/packages/@uppy/remote-sources/types/index.d.ts @@ -0,0 +1,13 @@ +import type { PluginOptions, BasePlugin, PluginTarget } from '@uppy/core' +import type { RequestClientOptions } from '@uppy/companion-client' + +interface RemoteTargetOptions extends PluginOptions, RequestClientOptions { + target?: PluginTarget + sources?: Array + title?: string + companionUrl: string +} + +declare class RemoteTarget extends BasePlugin {} + +export default RemoteTarget diff --git a/packages/@uppy/remote-sources/types/index.test-d.ts b/packages/@uppy/remote-sources/types/index.test-d.ts new file mode 100644 index 0000000000..2a551ea846 --- /dev/null +++ b/packages/@uppy/remote-sources/types/index.test-d.ts @@ -0,0 +1,11 @@ +import Uppy from '@uppy/core' +import RemoteSources from '..' + +{ + const uppy = new Uppy() + uppy.use(RemoteSources, { + sources: ['Instagram', 'Url'], + companionUrl: '', + companionCookiesRule: 'same-origin', + }) +} diff --git a/packages/@uppy/robodog/CHANGELOG.md b/packages/@uppy/robodog/CHANGELOG.md index 91a8d7893f..20d1097957 100644 --- a/packages/@uppy/robodog/CHANGELOG.md +++ b/packages/@uppy/robodog/CHANGELOG.md @@ -1,5 +1,12 @@ # @uppy/robodog +## 2.8.0 + +Released: 2022-06-07 +Included in: Uppy v2.12.0 + +- @uppy/robodog: fix linter warnings (Antoine du Hamel / #3808) + ## 2.7.0 Released: 2022-05-30 diff --git a/packages/@uppy/robodog/src/TransloaditResultsPlugin.js b/packages/@uppy/robodog/src/TransloaditResultsPlugin.js index 6ad2795555..7bad3aca70 100644 --- a/packages/@uppy/robodog/src/TransloaditResultsPlugin.js +++ b/packages/@uppy/robodog/src/TransloaditResultsPlugin.js @@ -26,9 +26,9 @@ class TransloaditResultsPlugin extends BasePlugin { assemblies.forEach((assembly) => { Object.keys(assembly.results).forEach((stepName) => { const results = assembly.results[stepName] - results.forEach((result) => { + results.forEach((resultObject) => { assemblyResults.push({ - ...result, + ...resultObject, assemblyId: assembly.assembly_id, stepName, }) diff --git a/packages/@uppy/robodog/src/addProviders.js b/packages/@uppy/robodog/src/addProviders.js index 0f00dc22e3..adab8a4643 100644 --- a/packages/@uppy/robodog/src/addProviders.js +++ b/packages/@uppy/robodog/src/addProviders.js @@ -1,3 +1,4 @@ +/* eslint-disable global-require */ const Transloadit = require('@uppy/transloadit') const has = require('@uppy/utils/lib/hasProperty') @@ -39,6 +40,7 @@ function addRemoteProvider (uppy, name, opts) { companionAllowedHosts: Transloadit.COMPANION_PATTERN, } + // eslint-disable-next-line no-shadow remoteProviderOptionNames.forEach((name) => { if (has(opts, name)) providerOptions[name] = opts[name] }) @@ -68,6 +70,7 @@ function addLocalProvider (uppy, name, opts) { const Provider = localProviders[name] const providerOptions = {} + // eslint-disable-next-line no-shadow localProviderOptionNames.forEach((name) => { if (has(opts, name)) providerOptions[name] = opts[name] }) diff --git a/packages/@uppy/robodog/src/form.js b/packages/@uppy/robodog/src/form.js index 68cf15ef68..16a32c6c11 100644 --- a/packages/@uppy/robodog/src/form.js +++ b/packages/@uppy/robodog/src/form.js @@ -24,6 +24,7 @@ function mergeDefaultLocale (defaults, userProvided = {}) { function form (target, opts) { if (!opts) throw new TypeError('robodog.form: must provide an options object') + // eslint-disable-next-line no-param-reassign opts = { ...opts, locale: mergeDefaultLocale(defaultLocaleStrings, opts.locale), diff --git a/packages/@uppy/robodog/src/index.js b/packages/@uppy/robodog/src/index.js index eae67f0152..ebd27836fb 100644 --- a/packages/@uppy/robodog/src/index.js +++ b/packages/@uppy/robodog/src/index.js @@ -8,5 +8,7 @@ module.exports = { form, pick, upload, + // We need to keep the require here because we're using `babel-plugin-inline-package-json`. + // eslint-disable-next-line global-require VERSION: require('../package.json').version, } diff --git a/packages/@uppy/transloadit/CHANGELOG.md b/packages/@uppy/transloadit/CHANGELOG.md index 6b3fb128c5..e3f6e03317 100644 --- a/packages/@uppy/transloadit/CHANGELOG.md +++ b/packages/@uppy/transloadit/CHANGELOG.md @@ -7,6 +7,13 @@ Included in: Uppy v3.0.0-beta - @uppy/transloadit: remove IE 10 hack (Antoine du Hamel / #3777) +## 2.3.1 + +Released: 2022-06-09 +Included in: Uppy v2.12.1 + +- @uppy/transloadit: fix `COMPANION_PATTERN` export (Antoine du Hamel / #3820) + ## 2.3.0 Released: 2022-05-30 diff --git a/packages/@uppy/transloadit/src/index.js b/packages/@uppy/transloadit/src/index.js index 4f8ebcd9e1..f5398854b7 100644 --- a/packages/@uppy/transloadit/src/index.js +++ b/packages/@uppy/transloadit/src/index.js @@ -835,12 +835,14 @@ export default class Transloadit extends BasePlugin { } export { - COMPANION, ALLOWED_COMPANION_PATTERN, + COMPANION, + ALLOWED_COMPANION_PATTERN as COMPANION_PATTERN, } -// Backward compatibility: we want `COMPANION` and `ALLOWED_COMPANION_PATTERN` +// Backward compatibility: we want `COMPANION` and `COMPANION_PATTERN` // to keep being accessible as static properties of `Transloadit` to avoid a // breaking change. -Transloadit.COMPANION = COMPANION // TODO: remove this line on the next major Transloadit.ALLOWED_COMPANION_PATTERN = ALLOWED_COMPANION_PATTERN // TODO: remove this line on the next major +Transloadit.COMPANION = COMPANION // TODO: remove this line on the next major +Transloadit.COMPANION_PATTERN = ALLOWED_COMPANION_PATTERN // TODO: remove this line on the next major diff --git a/packages/@uppy/tus/CHANGELOG.md b/packages/@uppy/tus/CHANGELOG.md index 1663929eba..fccc63d9a9 100644 --- a/packages/@uppy/tus/CHANGELOG.md +++ b/packages/@uppy/tus/CHANGELOG.md @@ -1,5 +1,13 @@ # @uppy/tus +## 2.4.1 + +Released: 2022-06-07 +Included in: Uppy v2.12.0 + +- @uppy/aws-s3-multipart,@uppy/aws-s3,@uppy/tus: queue socket token requests for remote files (Merlijn Vos / #3797) +- @uppy/tus: make onShouldRetry type optional (Merlijn Vos / #3800) + ## 2.4.0 Released: 2022-05-30 diff --git a/packages/@uppy/tus/src/index.js b/packages/@uppy/tus/src/index.js index 00abd40167..57f9c3bdfc 100644 --- a/packages/@uppy/tus/src/index.js +++ b/packages/@uppy/tus/src/index.js @@ -57,6 +57,8 @@ export default class Tus extends BasePlugin { #retryDelayIterator + #queueRequestSocketToken + /** * @param {Uppy} uppy * @param {TusOptions} opts @@ -97,6 +99,7 @@ export default class Tus extends BasePlugin { this.handleResetProgress = this.handleResetProgress.bind(this) this.handleUpload = this.handleUpload.bind(this) + this.#queueRequestSocketToken = this.requests.wrapPromiseFunction(this.#requestSocketToken) } handleResetProgress () { @@ -427,43 +430,48 @@ export default class Tus extends BasePlugin { }) } - /** - * @param {UppyFile} file for use with upload - * @returns {Promise} - */ - async uploadRemote (file) { - this.resetUploaderReferences(file.id) - + #requestSocketToken = async (file) => { + const Client = file.remote.providerOptions.provider ? Provider : RequestClient + const client = new Client(this.uppy, file.remote.providerOptions) const opts = { ...this.opts } + if (file.tus) { // Install file-specific upload overrides. Object.assign(opts, file.tus) } - this.uppy.emit('upload-started', file) - this.uppy.log(file.remote.url) + const res = await client.post(file.remote.url, { + ...file.remote.body, + endpoint: opts.endpoint, + uploadUrl: opts.uploadUrl, + protocol: 'tus', + size: file.data.size, + headers: opts.headers, + metadata: file.meta, + }) + return res.token + } - if (file.serverToken) { - await this.connectToServerSocket(file) - return - } + /** + * @param {UppyFile} file for use with upload + * @returns {Promise} + */ + async uploadRemote (file) { + this.resetUploaderReferences(file.id) - const Client = file.remote.providerOptions.provider ? Provider : RequestClient - const client = new Client(this.uppy, file.remote.providerOptions) + // Don't double-emit upload-started for Golden Retriever-restored files that were already started + if (!file.progress.uploadStarted || !file.isRestored) { + this.uppy.emit('upload-started', file) + } try { - // !! cancellation is NOT supported at this stage yet - const res = await client.post(file.remote.url, { - ...file.remote.body, - endpoint: opts.endpoint, - uploadUrl: opts.uploadUrl, - protocol: 'tus', - size: file.data.size, - headers: opts.headers, - metadata: file.meta, - }) - this.uppy.setFileState(file.id, { serverToken: res.token }) - await this.connectToServerSocket(this.uppy.getFile(file.id)) + if (file.serverToken) { + return this.connectToServerSocket(file) + } + const serverToken = await this.#queueRequestSocketToken(file) + + this.uppy.setFileState(file.id, { serverToken }) + return this.connectToServerSocket(this.uppy.getFile(file.id)) } catch (err) { this.uppy.emit('upload-error', file, err) throw err @@ -482,7 +490,7 @@ export default class Tus extends BasePlugin { return new Promise((resolve, reject) => { const token = file.serverToken const host = getSocketHost(file.remote.companionUrl) - const socket = new Socket({ target: `${host}/api/${token}`, autoOpen: false }) + const socket = new Socket({ target: `${host}/api/${token}` }) this.uploaderSockets[file.id] = socket this.uploaderEvents[file.id] = new EventTracker(this.uppy) @@ -591,7 +599,6 @@ export default class Tus extends BasePlugin { }) queuedRequest = this.requests.run(() => { - socket.open() if (file.isPaused) { socket.send('pause', {}) } diff --git a/packages/@uppy/tus/types/index.d.ts b/packages/@uppy/tus/types/index.d.ts index 6753d750c4..19c954b9a8 100644 --- a/packages/@uppy/tus/types/index.d.ts +++ b/packages/@uppy/tus/types/index.d.ts @@ -20,7 +20,7 @@ export interface TusOptions extends PluginOptions, TusUploadOptions { limit?: number useFastRemoteRetry?: boolean withCredentials?: boolean - onShouldRetry: (err: Error | undefined, retryAttempt: number, options: TusOptions, next: Next) => boolean + onShouldRetry?: (err: Error | undefined, retryAttempt: number, options: TusOptions, next: Next) => boolean } declare class Tus extends BasePlugin {} diff --git a/packages/@uppy/url/CHANGELOG.md b/packages/@uppy/url/CHANGELOG.md index e8d2aeda2d..2532c69320 100644 --- a/packages/@uppy/url/CHANGELOG.md +++ b/packages/@uppy/url/CHANGELOG.md @@ -1,5 +1,13 @@ # @uppy/url +## 2.2.0 + +Released: 2022-06-07 +Included in: Uppy v2.12.0 + +- @uppy/url: enable passing optional meta data to `addFile` (Brad Edelman / #3788) +- @uppy/url: fix `getFileNameFromUrl` (Brad Edelman / #3804) + ## 2.1.1 Released: 2022-05-30 diff --git a/packages/@uppy/url/src/Url.jsx b/packages/@uppy/url/src/Url.jsx index c5551123f6..00a4c84044 100644 --- a/packages/@uppy/url/src/Url.jsx +++ b/packages/@uppy/url/src/Url.jsx @@ -48,7 +48,8 @@ function checkIfCorrectURL (url) { } function getFileNameFromUrl (url) { - return url.substring(url.lastIndexOf('/') + 1) + const { pathname } = new URL(url) + return pathname.substring(pathname.lastIndexOf('/') + 1) } /** * Url @@ -104,7 +105,7 @@ export default class Url extends UIPlugin { }) } - async addFile (protocollessUrl) { + async addFile (protocollessUrl, optionalMeta = undefined) { const url = this.addProtocolToURL(protocollessUrl) if (!this.checkIfCorrectURL(url)) { this.uppy.log(`[URL] Incorrect URL entered: ${url}`) @@ -116,6 +117,7 @@ export default class Url extends UIPlugin { const meta = await this.getMeta(url) const tagFile = { + meta: optionalMeta, source: this.id, name: this.getFileNameFromUrl(url), type: meta.type, diff --git a/packages/@uppy/url/types/index.d.ts b/packages/@uppy/url/types/index.d.ts index 5494abe291..c923bf0f8f 100644 --- a/packages/@uppy/url/types/index.d.ts +++ b/packages/@uppy/url/types/index.d.ts @@ -1,4 +1,4 @@ -import type { PluginOptions, UIPlugin, PluginTarget } from '@uppy/core' +import type { PluginOptions, UIPlugin, PluginTarget, IndexedObject } from '@uppy/core' import type { RequestClientOptions } from '@uppy/companion-client' import UrlLocale from './generatedLocale' @@ -9,7 +9,7 @@ export interface UrlOptions extends PluginOptions, RequestClientOptions { } declare class Url extends UIPlugin { - public addFile(url: string): undefined | string | never + public addFile(url: string, meta?: IndexedObject): undefined | string | never } export default Url diff --git a/packages/@uppy/xhr-upload/CHANGELOG.md b/packages/@uppy/xhr-upload/CHANGELOG.md index 0fe3127c60..db69dad3eb 100644 --- a/packages/@uppy/xhr-upload/CHANGELOG.md +++ b/packages/@uppy/xhr-upload/CHANGELOG.md @@ -1,5 +1,12 @@ # @uppy/xhr-upload +## 2.1.2 + +Released: 2022-06-07 +Included in: Uppy v2.12.0 + +- @uppy/xhr-upload: replace `ev.target.status` with `xhr.status` (Wes Sankey / #3782) + ## 2.1.1 Released: 2022-05-30 diff --git a/packages/@uppy/xhr-upload/src/index.js b/packages/@uppy/xhr-upload/src/index.js index 688b4ef98f..4e1e9d8611 100644 --- a/packages/@uppy/xhr-upload/src/index.js +++ b/packages/@uppy/xhr-upload/src/index.js @@ -251,7 +251,7 @@ export default class XHRUpload extends BasePlugin { } }) - xhr.addEventListener('load', (ev) => { + xhr.addEventListener('load', () => { this.uppy.log(`[XHRUpload] ${id} finished`) timer.done() queuedRequest.done() @@ -260,12 +260,12 @@ export default class XHRUpload extends BasePlugin { this.uploaderEvents[file.id] = null } - if (opts.validateStatus(ev.target.status, xhr.responseText, xhr)) { + if (opts.validateStatus(xhr.status, xhr.responseText, xhr)) { const body = opts.getResponseData(xhr.responseText, xhr) const uploadURL = body[opts.responseUrlFieldName] const uploadResp = { - status: ev.target.status, + status: xhr.status, body, uploadURL, } @@ -282,7 +282,7 @@ export default class XHRUpload extends BasePlugin { const error = buildResponseError(xhr, opts.getResponseError(xhr.responseText, xhr)) const response = { - status: ev.target.status, + status: xhr.status, body, } diff --git a/packages/uppy/index.mjs b/packages/uppy/index.mjs index c7a0875183..66303203af 100644 --- a/packages/uppy/index.mjs +++ b/packages/uppy/index.mjs @@ -29,6 +29,7 @@ export { default as Facebook } from '@uppy/facebook' export { default as GoogleDrive } from '@uppy/google-drive' export { default as Instagram } from '@uppy/instagram' export { default as OneDrive } from '@uppy/onedrive' +export { default as RemoteSources } from '@uppy/remote-sources' export { default as ScreenCapture } from '@uppy/screen-capture' export { default as Unsplash } from '@uppy/unsplash' export { default as Url } from '@uppy/url' diff --git a/private/dev/Dashboard.js b/private/dev/Dashboard.js index 3e882be118..e8014e1ac6 100644 --- a/private/dev/Dashboard.js +++ b/private/dev/Dashboard.js @@ -2,15 +2,7 @@ /* eslint-disable import/no-extraneous-dependencies */ import Uppy from '@uppy/core' import Dashboard from '@uppy/dashboard' -import Instagram from '@uppy/instagram' -import Facebook from '@uppy/facebook' -import OneDrive from '@uppy/onedrive' -import Dropbox from '@uppy/dropbox' -import Box from '@uppy/box' -import GoogleDrive from '@uppy/google-drive' -import Unsplash from '@uppy/unsplash' -import Zoom from '@uppy/zoom' -import Url from '@uppy/url' +import RemoteSources from '@uppy/remote-sources' import Webcam from '@uppy/webcam' import ScreenCapture from '@uppy/screen-capture' import GoldenRetriever from '@uppy/golden-retriever' @@ -83,15 +75,19 @@ export default () => { proudlyDisplayPoweredByUppy: true, note: '2 files, images and video only', }) - .use(GoogleDrive, { target: Dashboard, companionUrl: COMPANION_URL }) - .use(Instagram, { target: Dashboard, companionUrl: COMPANION_URL }) - .use(Dropbox, { target: Dashboard, companionUrl: COMPANION_URL }) - .use(Box, { target: Dashboard, companionUrl: COMPANION_URL }) - .use(Facebook, { target: Dashboard, companionUrl: COMPANION_URL }) - .use(OneDrive, { target: Dashboard, companionUrl: COMPANION_URL }) - .use(Zoom, { target: Dashboard, companionUrl: COMPANION_URL }) - .use(Url, { target: Dashboard, companionUrl: COMPANION_URL }) - .use(Unsplash, { target: Dashboard, companionUrl: COMPANION_URL }) + // .use(GoogleDrive, { target: Dashboard, companionUrl: COMPANION_URL }) + // .use(Instagram, { target: Dashboard, companionUrl: COMPANION_URL }) + // .use(Dropbox, { target: Dashboard, companionUrl: COMPANION_URL }) + // .use(Box, { target: Dashboard, companionUrl: COMPANION_URL }) + // .use(Facebook, { target: Dashboard, companionUrl: COMPANION_URL }) + // .use(OneDrive, { target: Dashboard, companionUrl: COMPANION_URL }) + // .use(Zoom, { target: Dashboard, companionUrl: COMPANION_URL }) + // .use(Url, { target: Dashboard, companionUrl: COMPANION_URL }) + // .use(Unsplash, { target: Dashboard, companionUrl: COMPANION_URL }) + .use(RemoteSources, { + companionUrl: COMPANION_URL, + sources: ['Box', 'Dropbox', 'Facebook', 'GoogleDrive', 'Instagram', 'OneDrive', 'Unsplash', 'Url'], + }) .use(Webcam, { target: Dashboard, showVideoSourceDropdown: true, diff --git a/private/release/choose-semverness.js b/private/release/choose-semverness.js index 965d20526a..ffce822874 100755 --- a/private/release/choose-semverness.js +++ b/private/release/choose-semverness.js @@ -4,6 +4,7 @@ import { createWriteStream, mkdirSync, readFileSync } from 'node:fs' import { spawnSync } from 'node:child_process' import prompts from 'prompts' +import { TARGET_BRANCH } from './config.js' const ROOT = new URL('../../', import.meta.url) const PACKAGES_FOLDER = new URL('./packages/', ROOT) @@ -87,7 +88,7 @@ export default async function pickSemverness ( `\nHere are the commits that landed on ${name} since previous release:\n${stdout}\n`, ) console.log( - `Check the web UI at https://github.com/transloadit/uppy/tree/main/${encodeURI( + `Check the web UI at https://github.com/transloadit/uppy/tree/${TARGET_BRANCH}/${encodeURI( location, )}.`, ) @@ -147,7 +148,7 @@ export default async function pickSemverness ( `Here are the commits that landed on @uppy/robodog since previous release:\n\n${stdout}\n`, ) console.log( - `Check the web UI at https://github.com/transloadit/uppy/tree/main/${encodeURI( + `Check the web UI at https://github.com/transloadit/uppy/tree/${TARGET_BRANCH}/${encodeURI( location, )}.`, ) diff --git a/website/src/docs/react-dragdrop.md b/website/src/docs/react-dragdrop.md index cc5cbaa183..69def48a5d 100644 --- a/website/src/docs/react-dragdrop.md +++ b/website/src/docs/react-dragdrop.md @@ -44,20 +44,25 @@ The `` component supports all [DragDrop](/docs/drag-drop/) options a import React from 'react' import { DragDrop } from '@uppy/react' - +export default function MyComponent (props) { + const { uppy } = props + return ( + + ) +} ``` diff --git a/website/src/docs/react-fileinput.md b/website/src/docs/react-fileinput.md index 732f270d05..33b5180425 100644 --- a/website/src/docs/react-fileinput.md +++ b/website/src/docs/react-fileinput.md @@ -44,10 +44,15 @@ The `` component supports all [FileInput](/docs/file-input/) option import React from 'react' import { FileInput } from '@uppy/react' - +export default function MyComponent (props) { + const { uppy } = props + return ( + + ) +} ``` diff --git a/website/src/docs/react-progressbar.md b/website/src/docs/react-progressbar.md index d138aabcfa..54da753196 100644 --- a/website/src/docs/react-progressbar.md +++ b/website/src/docs/react-progressbar.md @@ -44,11 +44,17 @@ The `` component supports all [`@uppy/progress-bar`][] options as import React from 'react' import { ProgressBar } from '@uppy/react' - +export default function MyComponent (props) { + const { uppy } = props + return ( + + ) +} ``` [`@uppy/progress-bar`]: /docs/progress-bar/ diff --git a/website/src/docs/react-statusbar.md b/website/src/docs/react-statusbar.md index a46c9eee9f..4260de6c50 100644 --- a/website/src/docs/react-statusbar.md +++ b/website/src/docs/react-statusbar.md @@ -44,12 +44,18 @@ The `` component supports all [`@uppy/status-bar`][] options as pro import React from 'react' import { StatusBar } from '@uppy/react' - +export default function MyComponent (props) { + const { uppy } = props + return ( + + ) +} ``` [`@uppy/status-bar`]: /docs/status-bar/ diff --git a/website/src/docs/remote-sources.md b/website/src/docs/remote-sources.md new file mode 100644 index 0000000000..c902e43ad0 --- /dev/null +++ b/website/src/docs/remote-sources.md @@ -0,0 +1,78 @@ +--- +type: docs +order: 10 +title: "Remote Sources" +module: "@uppy/remote-sources" +permalink: docs/remote-sources/ +category: "Miscellaneous" +tagline: "Uppy plugin that includes all remote sources that Uppy+Companion offer, like Instagram, Google Drive, Dropox, Box, Unsplash, Url etc" +--- + +`@uppy/remote-sources` is a preset plugin to add all the available remote sources, such Instagram, Google Drive, Dropbox, and others to Uppy Dashboard in one package. + +> Note: Remote Sources requires Dashboard and automatically installs all its plugins to it. + +```js +import Uppy from '@uppy/core' +import Dashbaord from '@uppy/dashboard' +import RemoteSources from '@uppy/compressor' + +const uppy = new Uppy() +uppy.use(Dashboard) +uppy.use(RemoteSources, { + companionUrl: 'https://your-companion-url', +}) +``` + +## Installation + +This plugin is published as the `@uppy/remote-sources` package. + +```shell +npm install @uppy/remote-sources +``` + +In the [CDN package](/docs/#With-a-script-tag), the plugin class is available on the `Uppy` global object: + +```js +const { RemoteSources } = Uppy +``` + +## Options + +### `id` + +A unique identifier for this plugin (`string`, default: `RemoteSources`). + +### `sources` + +List of remote sources that will be enabled (`array`, default: `['Box', 'Dropbox', 'Facebook', 'GoogleDrive','Instagram', 'OneDrive', 'Unsplash', 'Url']`). + +You don’t need to specify them manually or change them, but if you want to alter the order in which they appear in the Dashboard, or disable some sources, this option is for you. + +```js +uppy.use(RemoteSources, { + companionUrl: 'https://your-companion-url', + sources: ['Instagram', 'GoogleDrive', 'Unsplash', 'Url'], +}) +``` + +### `companionUrl` + +URL to a [Companion](/docs/companion) instance (`string`, default: `null`). + +### `companionHeaders` + +Custom headers that should be sent along to [Companion](/docs/companion) on every request (`object`, default: `{}`). + +### `companionAllowedHosts` + +The valid and authorized URL(s) from which OAuth responses should be accepted (`string | RegExp | Array`, Default: `companionUrl`) + +This value can be a `String`, a `Regex` pattern, or an `Array` of both. + +This is useful when you have your [Companion](/docs/companion) running on several hosts. Otherwise, the default value, which is `companionUrl`, should do fine. + +### `companionCookiesRule` + +This option correlates to the [RequestCredentials value](https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials), which tells the plugin whether to send cookies to [Companion](/docs/companion) (`string`, default: `same-origin`). diff --git a/yarn.lock b/yarn.lock index 5eef9773a2..d8d37ccab5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -648,6 +648,29 @@ __metadata: languageName: node linkType: hard +"@babel/core@npm:^7.11.6, @babel/core@npm:^7.14.3, @babel/core@npm:^7.17.9": + version: 7.18.2 + resolution: "@babel/core@npm:7.18.2" + dependencies: + "@ampproject/remapping": ^2.1.0 + "@babel/code-frame": ^7.16.7 + "@babel/generator": ^7.18.2 + "@babel/helper-compilation-targets": ^7.18.2 + "@babel/helper-module-transforms": ^7.18.0 + "@babel/helpers": ^7.18.2 + "@babel/parser": ^7.18.0 + "@babel/template": ^7.16.7 + "@babel/traverse": ^7.18.2 + "@babel/types": ^7.18.2 + convert-source-map: ^1.7.0 + debug: ^4.1.0 + gensync: ^1.0.0-beta.2 + json5: ^2.2.1 + semver: ^6.3.0 + checksum: 14a4142c12e004cd2477b7610408d5788ee5dd821ee9e4de204cbb72d9c399d858d9deabc3d49914d5d7c2927548160c19bdc7524b1a9f6acc1ec96a8d9848dd + languageName: node + linkType: hard + "@babel/core@npm:^7.12.10, @babel/core@npm:^7.17.5": version: 7.17.5 resolution: "@babel/core@npm:7.17.5" @@ -671,29 +694,6 @@ __metadata: languageName: node linkType: hard -"@babel/core@npm:^7.14.3, @babel/core@npm:^7.17.9": - version: 7.18.2 - resolution: "@babel/core@npm:7.18.2" - dependencies: - "@ampproject/remapping": ^2.1.0 - "@babel/code-frame": ^7.16.7 - "@babel/generator": ^7.18.2 - "@babel/helper-compilation-targets": ^7.18.2 - "@babel/helper-module-transforms": ^7.18.0 - "@babel/helpers": ^7.18.2 - "@babel/parser": ^7.18.0 - "@babel/template": ^7.16.7 - "@babel/traverse": ^7.18.2 - "@babel/types": ^7.18.2 - convert-source-map: ^1.7.0 - debug: ^4.1.0 - gensync: ^1.0.0-beta.2 - json5: ^2.2.1 - semver: ^6.3.0 - checksum: 14a4142c12e004cd2477b7610408d5788ee5dd821ee9e4de204cbb72d9c399d858d9deabc3d49914d5d7c2927548160c19bdc7524b1a9f6acc1ec96a8d9848dd - languageName: node - linkType: hard - "@babel/eslint-parser@npm:^7.11.3": version: 7.16.3 resolution: "@babel/eslint-parser@npm:7.16.3" @@ -4667,6 +4667,37 @@ __metadata: languageName: node linkType: hard +"@jest/environment@npm:^28.1.0": + version: 28.1.0 + resolution: "@jest/environment@npm:28.1.0" + dependencies: + "@jest/fake-timers": ^28.1.0 + "@jest/types": ^28.1.0 + "@types/node": "*" + jest-mock: ^28.1.0 + checksum: 376904d6626bb439f96a56ca9d400e1b6b4a5bafb751820fec649238e35cb7d0b9619223ade86c2906e97fae8da03a7b9561c55c1f5850afe9856db89185d754 + languageName: node + linkType: hard + +"@jest/expect-utils@npm:^28.1.0": + version: 28.1.0 + resolution: "@jest/expect-utils@npm:28.1.0" + dependencies: + jest-get-type: ^28.0.2 + checksum: 5b8b463682bd35ae71868020c87dc654ebed65ded4e74ea3c24bd9e1ab4637a7790c8b78c26cdcb832dd227b9981e8dd24eb3b742891637c24c2a3e38ba153e8 + languageName: node + linkType: hard + +"@jest/expect@npm:^28.1.0": + version: 28.1.0 + resolution: "@jest/expect@npm:28.1.0" + dependencies: + expect: ^28.1.0 + jest-snapshot: ^28.1.0 + checksum: e596bc2a2d02d66cb3e23982c6a48cfe24aa31932f594db7de6966db6c0b58f7aad3836a71debb8aeda6178116c35160e11ded42a355a94457f6402cbb2186e3 + languageName: node + linkType: hard + "@jest/fake-timers@npm:^24.9.0": version: 24.9.0 resolution: "@jest/fake-timers@npm:24.9.0" @@ -4692,6 +4723,20 @@ __metadata: languageName: node linkType: hard +"@jest/fake-timers@npm:^28.1.0": + version: 28.1.0 + resolution: "@jest/fake-timers@npm:28.1.0" + dependencies: + "@jest/types": ^28.1.0 + "@sinonjs/fake-timers": ^9.1.1 + "@types/node": "*" + jest-message-util: ^28.1.0 + jest-mock: ^28.1.0 + jest-util: ^28.1.0 + checksum: d24375bcd52873f1e602ff02ffe57c6866570b95ec0be167a4734d051047b2c6b3dab69b2a301a390a0ca2de2ad89fd2b23e991c09a1a3b70b1dd4763c8681c7 + languageName: node + linkType: hard + "@jest/globals@npm:^27.4.2": version: 27.4.2 resolution: "@jest/globals@npm:27.4.2" @@ -4703,6 +4748,17 @@ __metadata: languageName: node linkType: hard +"@jest/globals@npm:^28.1.0": + version: 28.1.0 + resolution: "@jest/globals@npm:28.1.0" + dependencies: + "@jest/environment": ^28.1.0 + "@jest/expect": ^28.1.0 + "@jest/types": ^28.1.0 + checksum: dce822edd1810430ce381235f714be705a9c774c00bf109d9d5df0dc4868371da62520832df99e83635ee1fc1fa4241cf617821b4e3b1a8bcd3fcd91aa8a75a7 + languageName: node + linkType: hard + "@jest/reporters@npm:^27.4.2": version: 27.4.2 resolution: "@jest/reporters@npm:27.4.2" @@ -4741,6 +4797,15 @@ __metadata: languageName: node linkType: hard +"@jest/schemas@npm:^28.0.2": + version: 28.0.2 + resolution: "@jest/schemas@npm:28.0.2" + dependencies: + "@sinclair/typebox": ^0.23.3 + checksum: 6a177e97b112c99f377697fe803a34f4489b92cd07949876250c69edc9029c7cbda771fcbb03caebd20ffbcfa89b9c22b4dc9d1e9a7fbc9873185459b48ba780 + languageName: node + linkType: hard + "@jest/source-map@npm:^24.9.0": version: 24.9.0 resolution: "@jest/source-map@npm:24.9.0" @@ -4844,6 +4909,29 @@ __metadata: languageName: node linkType: hard +"@jest/transform@npm:^28.1.0": + version: 28.1.0 + resolution: "@jest/transform@npm:28.1.0" + dependencies: + "@babel/core": ^7.11.6 + "@jest/types": ^28.1.0 + "@jridgewell/trace-mapping": ^0.3.7 + babel-plugin-istanbul: ^6.1.1 + chalk: ^4.0.0 + convert-source-map: ^1.4.0 + fast-json-stable-stringify: ^2.0.0 + graceful-fs: ^4.2.9 + jest-haste-map: ^28.1.0 + jest-regex-util: ^28.0.2 + jest-util: ^28.1.0 + micromatch: ^4.0.4 + pirates: ^4.0.4 + slash: ^3.0.0 + write-file-atomic: ^4.0.1 + checksum: f7417409c466fa1b4d8f9f7d365c8c1ed07e709e8712279180a87e9da8520ab06518de270b290148034d93f666d7826449b5e40cac34cc5f7225980e8991f2ba + languageName: node + linkType: hard + "@jest/types@npm:^24.9.0": version: 24.9.0 resolution: "@jest/types@npm:24.9.0" @@ -4906,6 +4994,20 @@ __metadata: languageName: node linkType: hard +"@jest/types@npm:^28.1.0": + version: 28.1.0 + resolution: "@jest/types@npm:28.1.0" + dependencies: + "@jest/schemas": ^28.0.2 + "@types/istanbul-lib-coverage": ^2.0.0 + "@types/istanbul-reports": ^3.0.0 + "@types/node": "*" + "@types/yargs": ^17.0.8 + chalk: ^4.0.0 + checksum: 22705aed92a76d45465a6c51147bc71c1fbd300b912ebad2769e3ff7fd51c1938017e29fcea52e00c00dab7130697359b2a2c2be6ee601e37c8b1042a2c4040e + languageName: node + linkType: hard + "@jridgewell/gen-mapping@npm:^0.3.0": version: 0.3.1 resolution: "@jridgewell/gen-mapping@npm:0.3.1" @@ -4955,7 +5057,7 @@ __metadata: languageName: node linkType: hard -"@jridgewell/trace-mapping@npm:^0.3.9": +"@jridgewell/trace-mapping@npm:^0.3.7, @jridgewell/trace-mapping@npm:^0.3.9": version: 0.3.13 resolution: "@jridgewell/trace-mapping@npm:0.3.13" dependencies: @@ -6534,6 +6636,13 @@ __metadata: languageName: node linkType: hard +"@sinclair/typebox@npm:^0.23.3": + version: 0.23.5 + resolution: "@sinclair/typebox@npm:0.23.5" + checksum: c96056d35d9cb862aeb635ff8873e2e7633e668dd544e162aee2690a82c970d0b3f90aa2b3501fe374dfa8e792388559a3e3a86712b23ebaef10061add534f47 + languageName: node + linkType: hard + "@sindresorhus/is@npm:^0.14.0": version: 0.14.0 resolution: "@sindresorhus/is@npm:0.14.0" @@ -6559,6 +6668,15 @@ __metadata: languageName: node linkType: hard +"@sinonjs/fake-timers@npm:^9.1.1": + version: 9.1.2 + resolution: "@sinonjs/fake-timers@npm:9.1.2" + dependencies: + "@sinonjs/commons": ^1.7.0 + checksum: 7d3aef54e17c1073101cb64d953157c19d62a40e261a30923fa1ee337b049c5f29cc47b1f0c477880f42b5659848ba9ab897607ac8ea4acd5c30ddcfac57fca6 + languageName: node + linkType: hard + "@sitespeed.io/tracium@npm:^0.3.3": version: 0.3.3 resolution: "@sitespeed.io/tracium@npm:0.3.3" @@ -8498,7 +8616,7 @@ __metadata: languageName: node linkType: hard -"@types/graceful-fs@npm:^4.1.2": +"@types/graceful-fs@npm:^4.1.2, @types/graceful-fs@npm:^4.1.3": version: 4.1.5 resolution: "@types/graceful-fs@npm:4.1.5" dependencies: @@ -9225,6 +9343,15 @@ __metadata: languageName: node linkType: hard +"@types/yargs@npm:^17.0.8": + version: 17.0.10 + resolution: "@types/yargs@npm:17.0.10" + dependencies: + "@types/yargs-parser": "*" + checksum: f0673cbfc08e17239dc58952a88350d6c4db04a027a28a06fbad27d87b670e909f9cd9e66f9c64cebdd5071d1096261e33454a55868395f125297e5c50992ca8 + languageName: node + linkType: hard + "@types/yauzl@npm:^2.9.1": version: 2.9.2 resolution: "@types/yauzl@npm:2.9.2" @@ -10320,6 +10447,27 @@ __metadata: languageName: unknown linkType: soft +"@uppy/remote-sources@workspace:packages/@uppy/remote-sources": + version: 0.0.0-use.local + resolution: "@uppy/remote-sources@workspace:packages/@uppy/remote-sources" + dependencies: + "@jest/globals": ^28.1.0 + "@uppy/box": "workspace:^" + "@uppy/dashboard": "workspace:^" + "@uppy/dropbox": "workspace:^" + "@uppy/facebook": "workspace:^" + "@uppy/google-drive": "workspace:^" + "@uppy/instagram": "workspace:^" + "@uppy/onedrive": "workspace:^" + "@uppy/unsplash": "workspace:^" + "@uppy/url": "workspace:^" + "@uppy/zoom": "workspace:^" + resize-observer-polyfill: ^1.5.1 + peerDependencies: + "@uppy/core": "workspace:^" + languageName: unknown + linkType: soft + "@uppy/robodog@workspace:*, @uppy/robodog@workspace:packages/@uppy/robodog": version: 0.0.0-use.local resolution: "@uppy/robodog@workspace:packages/@uppy/robodog" @@ -12825,7 +12973,7 @@ __metadata: languageName: node linkType: hard -"babel-plugin-istanbul@npm:6.1.1, babel-plugin-istanbul@npm:^6.0.0": +"babel-plugin-istanbul@npm:6.1.1, babel-plugin-istanbul@npm:^6.0.0, babel-plugin-istanbul@npm:^6.1.1": version: 6.1.1 resolution: "babel-plugin-istanbul@npm:6.1.1" dependencies: @@ -14415,9 +14563,9 @@ __metadata: linkType: hard "caniuse-lite@npm:^1.0.30001332": - version: 1.0.30001344 - resolution: "caniuse-lite@npm:1.0.30001344" - checksum: 9dba66f796dc98632dced4c5d487d0fad219e137a27c634eec68520f2e598a613e3371b9207e15a078689a629128eca898793e37fc98841821ab481bddad51b9 + version: 1.0.30001346 + resolution: "caniuse-lite@npm:1.0.30001346" + checksum: 951590454ffa4e2e7b772558dc593cd08604b44c83741e1188166298f54c34387f4bf34f5141a35de4a43028c012484240ad15c896e48bf4eac70dd7076a4449 languageName: node linkType: hard @@ -16989,6 +17137,13 @@ __metadata: languageName: node linkType: hard +"diff-sequences@npm:^28.0.2": + version: 28.0.2 + resolution: "diff-sequences@npm:28.0.2" + checksum: 482360a8ec93333ea61bc93a800a1bee37c943b94a48fa1597825076adcad24620b44a0d3aa8f3d190584a4156c4b3315028453ca33e1174001fae3cdaa7f8f8 + languageName: node + linkType: hard + "diff@npm:^4.0.1": version: 4.0.2 resolution: "diff@npm:4.0.2" @@ -17496,9 +17651,9 @@ __metadata: linkType: hard "electron-to-chromium@npm:^1.4.118": - version: 1.4.142 - resolution: "electron-to-chromium@npm:1.4.142" - checksum: 53c6105ef81923a4dba0a53fdd1a010a492ad051eb527969e981ce78aee5ebdc729e7b16733e6cfb7b934ad23b84172d0677abaa5d9cd0ae71cd4cf986e4ab2e + version: 1.4.147 + resolution: "electron-to-chromium@npm:1.4.147" + checksum: a714da8ac6842887e98886026b8eeaee0d2fd6d57f5707b0fc2a2916c1b9d026ca8deeef529fd3b069e96f719495a7467b01a508b881fd90d95aa204a7a92000 languageName: node linkType: hard @@ -19732,6 +19887,19 @@ __metadata: languageName: node linkType: hard +"expect@npm:^28.1.0": + version: 28.1.0 + resolution: "expect@npm:28.1.0" + dependencies: + "@jest/expect-utils": ^28.1.0 + jest-get-type: ^28.0.2 + jest-matcher-utils: ^28.1.0 + jest-message-util: ^28.1.0 + jest-util: ^28.1.0 + checksum: 53bfa2e094a7d5b270ce9a8dafc5432d51bb369287502acd373b66fe01072260bacd1f83bf741d5de49b008406781ab879a0247f5f6fc10d3f32fbe5a3ccfbdf + languageName: node + linkType: hard + "expo-application@npm:~3.2.0": version: 3.2.0 resolution: "expo-application@npm:3.2.0" @@ -24523,6 +24691,18 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis: languageName: node linkType: hard +"jest-diff@npm:^28.1.0": + version: 28.1.0 + resolution: "jest-diff@npm:28.1.0" + dependencies: + chalk: ^4.0.0 + diff-sequences: ^28.0.2 + jest-get-type: ^28.0.2 + pretty-format: ^28.1.0 + checksum: 4d90d9d18ba1d28f5520fa206831e9e8199facf28c6d2b4967c7e4cd1ee78e7e826187babdeb02073f79a1d2c186520d73f77fa29877c6547b0a79392d08a513 + languageName: node + linkType: hard + "jest-docblock@npm:^27.4.0": version: 27.4.0 resolution: "jest-docblock@npm:27.4.0" @@ -24588,6 +24768,13 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis: languageName: node linkType: hard +"jest-get-type@npm:^28.0.2": + version: 28.0.2 + resolution: "jest-get-type@npm:28.0.2" + checksum: 5281d7c89bc8156605f6d15784f45074f4548501195c26e9b188742768f72d40948252d13230ea905b5349038865a1a8eeff0e614cc530ff289dfc41fe843abd + languageName: node + linkType: hard + "jest-haste-map@npm:^24.9.0": version: 24.9.0 resolution: "jest-haste-map@npm:24.9.0" @@ -24660,6 +24847,29 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis: languageName: node linkType: hard +"jest-haste-map@npm:^28.1.0": + version: 28.1.0 + resolution: "jest-haste-map@npm:28.1.0" + dependencies: + "@jest/types": ^28.1.0 + "@types/graceful-fs": ^4.1.3 + "@types/node": "*" + anymatch: ^3.0.3 + fb-watchman: ^2.0.0 + fsevents: ^2.3.2 + graceful-fs: ^4.2.9 + jest-regex-util: ^28.0.2 + jest-util: ^28.1.0 + jest-worker: ^28.1.0 + micromatch: ^4.0.4 + walker: ^1.0.7 + dependenciesMeta: + fsevents: + optional: true + checksum: 128c2d1aa39610febfc9fe66bbc40bb847d89da3e1646ed1bbe63e90bd4c930d1798d20aef8d928fda8e5b0570f05f1cbb263030ebe776c01bb86dd5174434da + languageName: node + linkType: hard + "jest-jasmine2@npm:^27.4.2": version: 27.4.2 resolution: "jest-jasmine2@npm:27.4.2" @@ -24708,6 +24918,18 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis: languageName: node linkType: hard +"jest-matcher-utils@npm:^28.1.0": + version: 28.1.0 + resolution: "jest-matcher-utils@npm:28.1.0" + dependencies: + chalk: ^4.0.0 + jest-diff: ^28.1.0 + jest-get-type: ^28.0.2 + pretty-format: ^28.1.0 + checksum: 60e3e83fff67402972b101135d44443981d6519008e435b567f197220f330ec38356f905b6872348d082f0a2a4089612f63d2c72f55ee3c718de6b0ef03f4d6d + languageName: node + linkType: hard + "jest-message-util@npm:^24.9.0": version: 24.9.0 resolution: "jest-message-util@npm:24.9.0" @@ -24741,6 +24963,23 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis: languageName: node linkType: hard +"jest-message-util@npm:^28.1.0": + version: 28.1.0 + resolution: "jest-message-util@npm:28.1.0" + dependencies: + "@babel/code-frame": ^7.12.13 + "@jest/types": ^28.1.0 + "@types/stack-utils": ^2.0.0 + chalk: ^4.0.0 + graceful-fs: ^4.2.9 + micromatch: ^4.0.4 + pretty-format: ^28.1.0 + slash: ^3.0.0 + stack-utils: ^2.0.3 + checksum: a224f9dbb53b5ad857918938f94c6e5d9c64ccdd42e0780b3b485d66bd93c82cff7dd91fbe274273efb69533d79808f9c98622b23d70ec027e8619a20e283773 + languageName: node + linkType: hard + "jest-mock@npm:^24.9.0": version: 24.9.0 resolution: "jest-mock@npm:24.9.0" @@ -24770,6 +25009,16 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis: languageName: node linkType: hard +"jest-mock@npm:^28.1.0": + version: 28.1.0 + resolution: "jest-mock@npm:28.1.0" + dependencies: + "@jest/types": ^28.1.0 + "@types/node": "*" + checksum: 013428db82f418059314588e5d02a2a8f6697940ffeb1b1a23f61e9b94b1dca3ea0061d91f284e217bf0ce0e5251ff8f2f182a393cecd1ec6788d766cc18ded4 + languageName: node + linkType: hard + "jest-pnp-resolver@npm:^1.2.2": version: 1.2.2 resolution: "jest-pnp-resolver@npm:1.2.2" @@ -24796,6 +25045,13 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis: languageName: node linkType: hard +"jest-regex-util@npm:^28.0.2": + version: 28.0.2 + resolution: "jest-regex-util@npm:28.0.2" + checksum: 0ea8c5c82ec88bc85e273c0ec82e0c0f35f7a1e2d055070e50f0cc2a2177f848eec55f73e37ae0d045c3db5014c42b2f90ac62c1ab3fdb354d2abd66a9e08add + languageName: node + linkType: hard + "jest-resolve-dependencies@npm:^27.4.2": version: 27.4.2 resolution: "jest-resolve-dependencies@npm:27.4.2" @@ -24948,6 +25204,37 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis: languageName: node linkType: hard +"jest-snapshot@npm:^28.1.0": + version: 28.1.0 + resolution: "jest-snapshot@npm:28.1.0" + dependencies: + "@babel/core": ^7.11.6 + "@babel/generator": ^7.7.2 + "@babel/plugin-syntax-typescript": ^7.7.2 + "@babel/traverse": ^7.7.2 + "@babel/types": ^7.3.3 + "@jest/expect-utils": ^28.1.0 + "@jest/transform": ^28.1.0 + "@jest/types": ^28.1.0 + "@types/babel__traverse": ^7.0.6 + "@types/prettier": ^2.1.5 + babel-preset-current-node-syntax: ^1.0.0 + chalk: ^4.0.0 + expect: ^28.1.0 + graceful-fs: ^4.2.9 + jest-diff: ^28.1.0 + jest-get-type: ^28.0.2 + jest-haste-map: ^28.1.0 + jest-matcher-utils: ^28.1.0 + jest-message-util: ^28.1.0 + jest-util: ^28.1.0 + natural-compare: ^1.4.0 + pretty-format: ^28.1.0 + semver: ^7.3.5 + checksum: 73695484cf4e2af9d0dbb8bc1e851f6d6217cc740aa93b521012c253fbbd9dc1ce11b147ac3e18cac8358b4b64fe36a1b8a6d1a3083c9d275dd937281faad818 + languageName: node + linkType: hard + "jest-util@npm:^24.9.0": version: 24.9.0 resolution: "jest-util@npm:24.9.0" @@ -24996,6 +25283,20 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis: languageName: node linkType: hard +"jest-util@npm:^28.1.0": + version: 28.1.0 + resolution: "jest-util@npm:28.1.0" + dependencies: + "@jest/types": ^28.1.0 + "@types/node": "*" + chalk: ^4.0.0 + ci-info: ^3.2.0 + graceful-fs: ^4.2.9 + picomatch: ^2.2.3 + checksum: 14c2ee1c24c6efa2d7adfe81ece8b9bbda78fa871f40bed80db72726166e96f7fb22bf1d9fb1689fb433b9bcd748027eb1ee5f0851a12f1aa1c49ee0bd4d7508 + languageName: node + linkType: hard + "jest-validate@npm:^24.9.0": version: 24.9.0 resolution: "jest-validate@npm:24.9.0" @@ -25082,6 +25383,17 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis: languageName: node linkType: hard +"jest-worker@npm:^28.1.0": + version: 28.1.0 + resolution: "jest-worker@npm:28.1.0" + dependencies: + "@types/node": "*" + merge-stream: ^2.0.0 + supports-color: ^8.0.0 + checksum: 44b6cfb03752543e2462f143ca5c9642206f20813068ef0461e793bb8feda85f643ee906d96a0a57728e1a2fb5b89386fd34e44289568b1cee5815c115e7ee02 + languageName: node + linkType: hard + "jest@npm:^27.0.6": version: 27.4.3 resolution: "jest@npm:27.4.3" @@ -31073,7 +31385,7 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis: languageName: node linkType: hard -"pirates@npm:^4.0.5": +"pirates@npm:^4.0.4, pirates@npm:^4.0.5": version: 4.0.5 resolution: "pirates@npm:4.0.5" checksum: c9994e61b85260bec6c4fc0307016340d9b0c4f4b6550a957afaaff0c9b1ad58fbbea5cfcf083860a25cb27a375442e2b0edf52e2e1e40e69934e08dcc52d227 @@ -32523,6 +32835,18 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis: languageName: node linkType: hard +"pretty-format@npm:^28.1.0": + version: 28.1.0 + resolution: "pretty-format@npm:28.1.0" + dependencies: + "@jest/schemas": ^28.0.2 + ansi-regex: ^5.0.1 + ansi-styles: ^5.0.0 + react-is: ^18.0.0 + checksum: c1018099f8f800693449df96c05c243d94e01f7429b6617e1064a1a69b4d715637fc3c579061fbc31548b87d92af74a7933c6eb3856da6f30b29c0ff67004ce0 + languageName: node + linkType: hard + "pretty-format@npm:^3.8.0": version: 3.8.0 resolution: "pretty-format@npm:3.8.0" @@ -33255,6 +33579,13 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis: languageName: node linkType: hard +"react-is@npm:^18.0.0": + version: 18.1.0 + resolution: "react-is@npm:18.1.0" + checksum: d206a0fe6790851bff168727bfb896de02c5591695afb0c441163e8630136a3e13ee1a7ddd59fdccddcc93968b4721ae112c10f790b194b03b35a3dc13a355ef + languageName: node + linkType: hard + "react-native-safe-area-context@npm:3.2.0": version: 3.2.0 resolution: "react-native-safe-area-context@npm:3.2.0" @@ -35931,6 +36262,13 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis: languageName: node linkType: hard +"signal-exit@npm:^3.0.7": + version: 3.0.7 + resolution: "signal-exit@npm:3.0.7" + checksum: a2f098f247adc367dffc27845853e9959b9e88b01cb301658cfe4194352d8d2bb32e18467c786a7fe15f1d44b233ea35633d076d5e737870b7139949d1ab6318 + languageName: node + linkType: hard + "simple-concat@npm:^1.0.0": version: 1.0.1 resolution: "simple-concat@npm:1.0.1" @@ -41520,6 +41858,16 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis: languageName: node linkType: hard +"write-file-atomic@npm:^4.0.1": + version: 4.0.1 + resolution: "write-file-atomic@npm:4.0.1" + dependencies: + imurmurhash: ^0.1.4 + signal-exit: ^3.0.7 + checksum: 8f780232533ca6223c63c9b9c01c4386ca8c625ebe5017a9ed17d037aec19462ae17109e0aa155bff5966ee4ae7a27b67a99f55caf3f32ffd84155e9da3929fc + languageName: node + linkType: hard + "write@npm:1.0.3": version: 1.0.3 resolution: "write@npm:1.0.3"