Browse Source

Fix all breaking todo comments for 3.0 (#3907)

- `@uppy/aws/s3-multipart`: remove `client` getter and setter.
  - reason: internal usage only
  - migrate: use exposed options only
- `@uppy/core`: remove `AggregateError` polyfill
  - reason: [should be polyfilled by the user](https://github.com/transloadit/uppy/pull/3532#discussion_r818602636)
  - migrate: install `AggregateError` polyfill or use `core-js`
- `@uppy/core`: remove `reset()` method
  - reason: it's a duplicate of `cancelAll`, but with a less intention revealing name
  - migrate: use `cancelAll`
- `@uppy/core`: remove backwards compatible exports (static properties on `Uppy`)
  - reason: transition to ESM
  - migrate: import the `Uppy` class by default and/or use named exports for everything else.
- `@uppy/react`: don't expose `validProps`
  - reason: internal only
  - migrate: do not depend on this
- `@uppy/store-redux`: remove backwards compatible exports (static properties on `ReduxStore`)
  - reason: transition to ESM
  - migrate: use named imports
- `@uppy/thumbnail-generator`: remove `rotateImage`, `protect`, and `canvasToBlob` from prototype.
  - reason: internal only
  - migrate: don't depend on this
Merlijn Vos 2 năm trước cách đây
mục cha
commit
9a213b59da

+ 0 - 5
packages/@uppy/aws-s3-multipart/src/index.js

@@ -58,11 +58,6 @@ export default class AwsS3Multipart extends BasePlugin {
 
   [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.

+ 0 - 2
packages/@uppy/companion/src/server/controllers/url.js

@@ -93,7 +93,6 @@ const meta = async (req, res) => {
     return res.json(urlMeta)
   } catch (err) {
     logger.error(err, 'controller.url.meta.error', req.id)
-    // @todo send more meaningful error message and status code to client if possible
     return res.status(err.status || 500).json({ message: 'failed to fetch URL metadata' })
   }
 }
@@ -125,7 +124,6 @@ const get = async (req, res) => {
 
   function onUnhandledError (err) {
     logger.error(err, 'controller.url.error', req.id)
-    // @todo send more meaningful error message and status code to client if possible
     res.status(err.status || 500).json({ message: 'failed to fetch URL metadata' })
   }
 

+ 0 - 2
packages/@uppy/core/src/BasePlugin.js

@@ -75,8 +75,6 @@ export default class BasePlugin {
     throw new Error('Extend the render method to add your plugin to a DOM element')
   }
 
-  // TODO: remove in the next major version. It's not feasible to
-  // try to use plugins with other frameworks.
   // eslint-disable-next-line class-methods-use-this
   update () {}
 

+ 1 - 15
packages/@uppy/core/src/Restricter.js

@@ -1,5 +1,4 @@
 /* eslint-disable max-classes-per-file, class-methods-use-this */
-/* global AggregateError */
 import prettierBytes from '@transloadit/prettier-bytes'
 import match from 'mime-match'
 
@@ -17,17 +16,6 @@ class RestrictionError extends Error {
   isRestriction = true
 }
 
-if (typeof AggregateError === 'undefined') {
-  // eslint-disable-next-line no-global-assign
-  // TODO: remove this "polyfill" in the next major.
-  globalThis.AggregateError = class AggregateError extends Error {
-    constructor (errors, message) {
-      super(message)
-      this.errors = errors
-    }
-  }
-}
-
 class Restricter {
   constructor (getOpts, i18n) {
     this.i18n = i18n
@@ -108,12 +96,10 @@ class Restricter {
   getMissingRequiredMetaFields (file) {
     const error = new RestrictionError(this.i18n('missingRequiredMetaFieldOnFile', { fileName: file.name }))
     const { requiredMetaFields } = this.getOpts().restrictions
-    // TODO: migrate to Object.hasOwn in the next major.
-    const own = Object.prototype.hasOwnProperty
     const missingFields = []
 
     for (const field of requiredMetaFields) {
-      if (!own.call(file.meta, field) || file.meta[field] === '') {
+      if (!Object.hasOwn(file.meta, field) || file.meta[field] === '') {
         missingFields.push(field)
       }
     }

+ 0 - 5
packages/@uppy/core/src/Uppy.js

@@ -843,11 +843,6 @@ class Uppy {
     return this.#runUpload(uploadID)
   }
 
-  // todo remove in next major. what is the point of the reset method when we have cancelAll or vice versa?
-  reset (...args) {
-    this.cancelAll(...args)
-  }
-
   logout () {
     this.iteratePlugins(plugin => {
       if (plugin.provider && plugin.provider.logout) {

+ 6 - 5
packages/@uppy/core/src/Uppy.test.js

@@ -6,6 +6,7 @@ import fs from 'node:fs'
 import prettierBytes from '@transloadit/prettier-bytes'
 import Core from '../lib/index.js'
 import UIPlugin from '../lib/UIPlugin.js'
+import { debugLogger } from '../lib/loggers.js'
 import AcquirerPlugin1 from './mocks/acquirerPlugin1.js'
 import AcquirerPlugin2 from './mocks/acquirerPlugin2.js'
 import InvalidPlugin from './mocks/invalidPlugin.js'
@@ -204,7 +205,7 @@ describe('src/Core', () => {
     })
   })
 
-  it('should reset when the reset method is called', () => {
+  it('should cancel all when the `cancelAll` method is called', () => {
     // use DeepFrozenStore in some tests to make sure we are not mutating things
     const core = new Core({
       store: DeepFrozenStore(),
@@ -216,7 +217,7 @@ describe('src/Core', () => {
     core.on('state-update', coreStateUpdateEventMock)
     core.setState({ foo: 'bar', totalProgress: 30 })
 
-    core.reset()
+    core.cancelAll()
 
     expect(coreCancelEventMock).toHaveBeenCalledWith({ reason: 'user' }, undefined, undefined, undefined, undefined, undefined)
     expect(coreStateUpdateEventMock.mock.calls.length).toEqual(2)
@@ -1071,7 +1072,7 @@ describe('src/Core', () => {
       )
     })
 
-    it('allows new files again with allowMultipleUploadBatches: false after reset() was called', async () => {
+    it('allows new files again with allowMultipleUploadBatches: false after cancelAll() was called', async () => {
       const core = new Core({ allowMultipleUploadBatches: false })
 
       core.addFile({
@@ -1082,7 +1083,7 @@ describe('src/Core', () => {
       })
       await expect(core.upload()).resolves.toBeDefined()
 
-      core.reset()
+      core.cancelAll()
 
       core.addFile({
         source: 'jest',
@@ -2135,7 +2136,7 @@ describe('src/Core', () => {
       console.error = jest.fn()
 
       const core = new Core({
-        logger: Core.debugLogger,
+        logger: debugLogger,
       })
 
       core.log('test test')

+ 1 - 16
packages/@uppy/core/src/index.js

@@ -1,20 +1,5 @@
 export { default } from './Uppy.js'
+export { default as Uppy } from './Uppy.js'
 export { default as UIPlugin } from './UIPlugin.js'
 export { default as BasePlugin } from './BasePlugin.js'
 export { debugLogger } from './loggers.js'
-
-// TODO: remove all the following in the next major
-/* eslint-disable import/first */
-import Uppy from './Uppy.js'
-import UIPlugin from './UIPlugin.js'
-import BasePlugin from './BasePlugin.js'
-import { debugLogger } from './loggers.js'
-
-// Backward compatibility: we want those to keep being accessible as static
-// properties of `Uppy` to avoid a breaking change.
-Uppy.Uppy = Uppy
-Uppy.UIPlugin = UIPlugin
-Uppy.BasePlugin = BasePlugin
-Uppy.debugLogger = debugLogger
-
-export { Uppy }

+ 0 - 4
packages/@uppy/core/types/index.d.ts

@@ -217,8 +217,6 @@ export type ErrorCallback = (error: Error) => void;
 export type UploadErrorCallback<TMeta> = (file: UppyFile<TMeta> | undefined, error: Error, response?: ErrorResponse) => void;
 export type UploadRetryCallback = (fileID: string) => void;
 export type RetryAllCallback = (fileIDs: string[]) => void;
-
-// TODO: reverse the order in the next major version
 export type RestrictionFailedCallback<TMeta> = (file: UppyFile<TMeta> | undefined, error: Error) => void;
 
 export interface UppyEventMap<TMeta = Record<string, unknown>> {
@@ -349,8 +347,6 @@ export class Uppy {
     fileID: string
   ): Promise<UploadResult<TMeta>>
 
-  reset(): void
-
   getID(): string
 
   use<TOptions, TInstance extends UIPlugin | BasePlugin<TOptions>>(

+ 1 - 1
packages/@uppy/dashboard/src/Dashboard.jsx

@@ -73,7 +73,7 @@ export default class Dashboard extends UIPlugin {
       hidePauseResumeButton: false,
       hideProgressAfterFinish: false,
       doneButtonHandler: () => {
-        this.uppy.reset()
+        this.uppy.cancelAll()
         this.requestCloseModal()
       },
       note: null,

+ 2 - 4
packages/@uppy/react/src/Dashboard.js

@@ -19,7 +19,7 @@ class Dashboard extends Component {
     if (prevProps.uppy !== this.props.uppy) {
       this.uninstallPlugin(prevProps)
       this.installPlugin()
-    } else if (nonHtmlPropsHaveChanged(this, prevProps)) {
+    } else if (nonHtmlPropsHaveChanged(this.props, prevProps)) {
       const options = { ...this.props, target: this.container }
       delete options.uppy
       this.plugin.setOptions(options)
@@ -50,14 +50,12 @@ class Dashboard extends Component {
   }
 
   render () {
-    // TODO: stop exposing `validProps` as a public property and rename it to `htmlProps`
-    this.validProps = getHTMLProps(this.props)
     return h('div', {
       className: 'uppy-Container',
       ref: (container) => {
         this.container = container
       },
-      ...this.validProps,
+      ...getHTMLProps(this.props),
     })
   }
 }

+ 2 - 4
packages/@uppy/react/src/DashboardModal.js

@@ -20,7 +20,7 @@ class DashboardModal extends Component {
     if (prevProps.uppy !== uppy) {
       this.uninstallPlugin(prevProps)
       this.installPlugin()
-    } else if (nonHtmlPropsHaveChanged(this, prevProps)) {
+    } else if (nonHtmlPropsHaveChanged(this.props, prevProps)) {
       const options = { ...this.props, onRequestCloseModal: onRequestClose }
       delete options.uppy
       this.plugin.setOptions(options)
@@ -135,14 +135,12 @@ class DashboardModal extends Component {
   }
 
   render () {
-    // TODO: stop exposing `validProps` as a public property and rename it to `htmlProps`
-    this.validProps = getHTMLProps(this.props)
     return h('div', {
       className: 'uppy-Container',
       ref: (container) => {
         this.container = container
       },
-      ...this.validProps,
+      ...getHTMLProps(this.props),
     })
   }
 }

+ 2 - 4
packages/@uppy/react/src/DragDrop.js

@@ -20,7 +20,7 @@ class DragDrop extends Component {
     if (prevProps.uppy !== this.props.uppy) {
       this.uninstallPlugin(prevProps)
       this.installPlugin()
-    } else if (nonHtmlPropsHaveChanged(this, prevProps)) {
+    } else if (nonHtmlPropsHaveChanged(this.props, prevProps)) {
       const options = { ...this.props, target: this.container }
       delete options.uppy
       this.plugin.setOptions(options)
@@ -63,14 +63,12 @@ class DragDrop extends Component {
   }
 
   render () {
-    // TODO: stop exposing `validProps` as a public property and rename it to `htmlProps`
-    this.validProps = getHTMLProps(this.props)
     return h('div', {
       className: 'uppy-Container',
       ref: (container) => {
         this.container = container
       },
-      ...this.validProps,
+      ...getHTMLProps(this.props),
     })
   }
 }

+ 2 - 4
packages/@uppy/react/src/ProgressBar.js

@@ -19,7 +19,7 @@ class ProgressBar extends Component {
     if (prevProps.uppy !== this.props.uppy) {
       this.uninstallPlugin(prevProps)
       this.installPlugin()
-    } else if (nonHtmlPropsHaveChanged(this, prevProps)) {
+    } else if (nonHtmlPropsHaveChanged(this.props, prevProps)) {
       const options = { ...this.props, target: this.container }
       delete options.uppy
       this.plugin.setOptions(options)
@@ -52,14 +52,12 @@ class ProgressBar extends Component {
   }
 
   render () {
-    // TODO: stop exposing `validProps` as a public property and rename it to `htmlProps`
-    this.validProps = getHTMLProps(this.props)
     return h('div', {
       className: 'uppy-Container',
       ref: (container) => {
         this.container = container
       },
-      ...this.validProps,
+      ...getHTMLProps(this.props),
     })
   }
 }

+ 2 - 4
packages/@uppy/react/src/StatusBar.js

@@ -20,7 +20,7 @@ class StatusBar extends Component {
     if (prevProps.uppy !== this.props.uppy) {
       this.uninstallPlugin(prevProps)
       this.installPlugin()
-    } else if (nonHtmlPropsHaveChanged(this, prevProps)) {
+    } else if (nonHtmlPropsHaveChanged(this.props, prevProps)) {
       const options = { ...this.props, target: this.container }
       delete options.uppy
       this.plugin.setOptions(options)
@@ -67,14 +67,12 @@ class StatusBar extends Component {
   }
 
   render () {
-    // TODO: stop exposing `validProps` as a public property and rename it to `htmlProps`
-    this.validProps = getHTMLProps(this.props)
     return h('div', {
       className: 'uppy-Container',
       ref: (container) => {
         this.container = container
       },
-      ...this.validProps,
+      ...getHTMLProps(this.props),
     })
   }
 }

+ 2 - 7
packages/@uppy/react/src/nonHtmlPropsHaveChanged.js

@@ -1,10 +1,5 @@
 'use strict'
 
-// TODO: replace with `Object.hasOwn` when dropping support for older browsers.
-const hasOwn = (obj, key) => Object.prototype.hasOwnProperty.call(obj, key)
-
-export default function nonHtmlPropsHaveChanged (component, prevProps) {
-  return Object.keys(component.props)
-    // TODO: replace `validProps` with an exported `Symbol('htmlProps')`.
-    .some(key => !hasOwn(component.validProps, key) && component.props[key] !== prevProps[key])
+export default function nonHtmlPropsHaveChanged (props, prevProps) {
+  return Object.keys(props).some(key => !Object.hasOwn(props, key) && props[key] !== prevProps[key])
 }

+ 1 - 1
packages/@uppy/redux-dev-tools/src/index.js

@@ -40,7 +40,7 @@ export default class ReduxDevTools extends UIPlugin {
         // Implement monitors actions
         switch (message.payload.type) {
           case 'RESET':
-            this.uppy.reset()
+            this.uppy.cancelAll()
             return
           case 'IMPORT_STATE': {
             const { computedStates } = message.payload.nextLiftedState

+ 0 - 8
packages/@uppy/store-redux/src/index.js

@@ -90,11 +90,3 @@ export function middleware () {
 }
 
 export default ReduxStore
-
-// Backward compatibility: we want these to keep being available as static
-// properties of `ReduxStore` to avoid a breaking change.
-// TODO: remove these in the next semver-major.
-ReduxStore.ReduxStore = ReduxStore
-ReduxStore.STATE_UPDATE = STATE_UPDATE
-ReduxStore.reducer = reducer
-ReduxStore.middleware = middleware

+ 1 - 1
packages/@uppy/store-redux/src/index.test.js

@@ -10,7 +10,7 @@ describe('ReduxStore', () => {
 
   it('can be created with named or default import', () => {
     const r = createStore()
-    let store = new ReduxStore.ReduxStore({ store: r })
+    let store = new ReduxStore({ store: r })
     expect(typeof store).toBe('object')
     store = new ReduxStore({ store: r })
     expect(typeof store).toBe('object')

+ 4 - 8
packages/@uppy/thumbnail-generator/src/index.js

@@ -162,9 +162,9 @@ export default class ThumbnailGenerator extends UIPlugin {
     return Promise.all([onload, orientationPromise])
       .then(([image, orientation]) => {
         const dimensions = this.getProportionalDimensions(image, targetWidth, targetHeight, orientation.deg)
-        const rotatedImage = this.rotateImage(image, orientation)
+        const rotatedImage = rotateImage(image, orientation)
         const resizedImage = this.resizeImage(rotatedImage, dimensions.width, dimensions.height)
-        return this.canvasToBlob(resizedImage, this.thumbnailType, 80)
+        return canvasToBlob(resizedImage, this.thumbnailType, 80)
       })
       .then(blob => {
         return URL.createObjectURL(blob)
@@ -208,11 +208,12 @@ export default class ThumbnailGenerator extends UIPlugin {
    *
    * Returns a Canvas with the resized image on it.
    */
+  // eslint-disable-next-line class-methods-use-this
   resizeImage (image, targetWidth, targetHeight) {
     // Resizing in steps refactored to use a solution from
     // https://blog.uploadcare.com/image-resize-in-browsers-is-broken-e38eed08df01
 
-    let img = this.protect(image)
+    let img = protect(image)
 
     let steps = Math.ceil(Math.log2(img.width / targetWidth))
     if (steps < 1) {
@@ -398,8 +399,3 @@ export default class ThumbnailGenerator extends UIPlugin {
     }
   }
 }
-
-// TODO: remove these methods from the prototype in the next major.
-ThumbnailGenerator.prototype.canvasToBlob = canvasToBlob
-ThumbnailGenerator.prototype.protect = protect
-ThumbnailGenerator.prototype.rotateImage = rotateImage

+ 0 - 14
packages/@uppy/thumbnail-generator/src/index.test.js

@@ -348,20 +348,6 @@ describe('uploader/ThumbnailGeneratorPlugin', () => {
     })
   })
 
-  describe('canvasToBlob', () => {
-    it('should use canvas.toBlob if available', () => {
-      const core = new MockCore()
-      const plugin = new ThumbnailGeneratorPlugin(core)
-      const canvas = {
-        toBlob: jest.fn(),
-      }
-      plugin.canvasToBlob(canvas, 'type', 90)
-      expect(canvas.toBlob).toHaveBeenCalledTimes(1)
-      expect(canvas.toBlob.mock.calls[0][1]).toEqual('type')
-      expect(canvas.toBlob.mock.calls[0][2]).toEqual(90)
-    })
-  })
-
   describe('downScaleInSteps', () => {
     let originalDocumentCreateElement
     let originalURLCreateObjectURL

+ 0 - 4
packages/@uppy/transloadit/src/AssemblyOptions.js

@@ -122,7 +122,3 @@ class AssemblyOptions {
 
 export default AssemblyOptions
 export { validateParams }
-
-// Backward compatibility: we want `validateParams` to keep being a static
-// method of `AssemblyOptions` to avoid a breaking change.
-AssemblyOptions.validateParams = validateParams // TODO: remove this line on the next major

+ 2 - 2
private/dev/Dashboard.js

@@ -1,6 +1,6 @@
 // The @uppy/ dependencies are resolved from source
 /* eslint-disable import/no-extraneous-dependencies */
-import Uppy from '@uppy/core'
+import Uppy, { debugLogger } from '@uppy/core'
 import Dashboard from '@uppy/dashboard'
 import RemoteSources from '@uppy/remote-sources'
 import Webcam from '@uppy/webcam'
@@ -56,7 +56,7 @@ async function getAssemblyOptions () {
 
 export default () => {
   const uppyDashboard = new Uppy({
-    logger: Uppy.debugLogger,
+    logger: debugLogger,
     meta: {
       username: 'John',
       license: 'Creative Commons',

+ 5 - 5
website/src/docs/core.md

@@ -89,13 +89,13 @@ With this option set to `false`, users can upload some files, and you can listen
 
 An object of methods that are called with debug information from [`uppy.log`](/docs/uppy/#uppy-log).
 
-Set `logger: Uppy.debugLogger` to get debug info output to the browser console:
+Set `logger: debugLogger` to get debug info output to the browser console:
 
 ```js
 import Uppy from '@uppy/core'
 
 const uppy = new Uppy({
-  logger: Uppy.debugLogger,
+  logger: debugLogger,
 })
 ```
 
@@ -111,7 +111,7 @@ const nullLogger = {
 }
 ```
 
-`logger: Uppy.debugLogger` looks like this:
+`logger: debugLogger` looks like this:
 
 ```js
 const debugLogger = {
@@ -670,7 +670,7 @@ uppy.getPlugin('Dashboard').setOptions({
 })
 ```
 
-### `uppy.reset({ reason = 'user' })` (alias `uppy.cancelAll()`)
+### `uppy.cancelAll({ reason = 'user' })`
 
 Stop all uploads in progress and clear file selection, set progress to 0. More or less, it returns things to the way they were before any user input.
 
@@ -680,7 +680,7 @@ Stop all uploads in progress and clear file selection, set progress to 0. More o
 
 ### `uppy.close({ reason = 'user' })`
 
-Uninstall all plugins and close down this Uppy instance. Also runs `uppy.reset()` before uninstalling.
+Uninstall all plugins and close down this Uppy instance. Also runs `uppy.cancelAll()` before uninstalling.
 
 * `reason` - Same as the `reason` option for `cancelAll`
 

+ 2 - 2
website/src/docs/dashboard.md

@@ -81,7 +81,7 @@ uppy.use(Dashboard, {
   hideCancelButton: false,
   hideProgressAfterFinish: false,
   doneButtonHandler: () => {
-    this.uppy.reset()
+    this.uppy.cancelAll()
     this.requestCloseModal()
   },
   note: null,
@@ -198,7 +198,7 @@ This option is passed to the StatusBar, and will render a “Done” button in p
 
 ```js
 const doneButtonHandler = () => {
-  this.uppy.reset()
+  this.uppy.cancelAll()
   this.requestCloseModal()
 }
 ```

+ 1 - 1
website/src/docs/status-bar.md

@@ -113,7 +113,7 @@ If passed a function, Status Bar will render a “Done” button in place of pau
 
 ```js
 const doneButtonHandler = () => {
-  this.uppy.reset()
+  this.uppy.cancelAll()
   this.requestCloseModal()
 }
 ```