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
This commit is contained in:
Merlijn Vos 2022-08-03 20:07:24 +02:00 committed by GitHub
parent 80f622fb62
commit 9a213b59da
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 37 additions and 128 deletions

View file

@ -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.

View file

@ -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' })
}

View file

@ -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 () {}

View file

@ -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)
}
}

View file

@ -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) {

View file

@ -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')

View file

@ -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 }

View file

@ -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>>(

View file

@ -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,

View file

@ -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),
})
}
}

View file

@ -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),
})
}
}

View file

@ -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),
})
}
}

View file

@ -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),
})
}
}

View file

@ -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),
})
}
}

View file

@ -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])
}

View file

@ -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

View file

@ -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

View file

@ -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')

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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',

View file

@ -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`

View file

@ -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()
}
```

View file

@ -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()
}
```