mirror of
https://github.com/transloadit/uppy.git
synced 2026-07-25 03:08:34 +00:00
meta: validate defaultOptions for stricter option types (#4901)
This commit is contained in:
parent
93c5e0a1c8
commit
66bd526ab3
6 changed files with 42 additions and 19 deletions
|
|
@ -1,5 +1,6 @@
|
|||
import type { Uppy, BasePlugin } from '@uppy/core'
|
||||
import type { Body, Meta, UppyFile } from '@uppy/utils/lib/UppyFile'
|
||||
import type { PluginOpts } from '@uppy/core/lib/BasePlugin.ts'
|
||||
import RequestClient, {
|
||||
authErrorStatusCode,
|
||||
type RequestOptions,
|
||||
|
|
@ -7,7 +8,7 @@ import RequestClient, {
|
|||
import * as tokenStorage from './tokenStorage.ts'
|
||||
|
||||
// TODO: remove deprecated options in next major release
|
||||
export type Opts = {
|
||||
export interface Opts extends PluginOpts {
|
||||
/** @deprecated */
|
||||
serverUrl?: string
|
||||
/** @deprecated */
|
||||
|
|
|
|||
|
|
@ -21,15 +21,22 @@ import type { State, Uppy } from './Uppy'
|
|||
export type PluginOpts = {
|
||||
locale?: Locale
|
||||
id?: string
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type OnlyOptionals<T> = Pick<
|
||||
T,
|
||||
{
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
[K in keyof T]-?: {} extends Pick<T, K> ? K : never
|
||||
}[keyof T]
|
||||
>
|
||||
|
||||
/**
|
||||
* DefinePluginOpts marks all of the passed AlwaysDefinedKeys as “required” or “always defined”.
|
||||
*/
|
||||
export type DefinePluginOpts<
|
||||
Opts extends PluginOpts,
|
||||
AlwaysDefinedKeys extends string,
|
||||
Opts,
|
||||
AlwaysDefinedKeys extends keyof OnlyOptionals<Opts>,
|
||||
> = Opts & Required<Pick<Opts, AlwaysDefinedKeys>>
|
||||
|
||||
export default class BasePlugin<
|
||||
|
|
|
|||
|
|
@ -8,12 +8,12 @@ import getCanvasDataThatFitsPerfectlyIntoContainer from './utils/getCanvasDataTh
|
|||
import getScaleFactorThatRemovesDarkCorners from './utils/getScaleFactorThatRemovesDarkCorners.ts'
|
||||
import limitCropboxMovementOnMove from './utils/limitCropboxMovementOnMove.ts'
|
||||
import limitCropboxMovementOnResize from './utils/limitCropboxMovementOnResize.ts'
|
||||
import type { ImageEditorOpts } from './ImageEditor.tsx'
|
||||
import type ImageEditor from './ImageEditor.tsx'
|
||||
|
||||
type Props<M extends Meta, B extends Body> = {
|
||||
currentImage: UppyFile<M, B>
|
||||
storeCropperInstance: (cropper: Cropper) => void
|
||||
opts: ImageEditorOpts
|
||||
opts: ImageEditor<M, B>['opts']
|
||||
i18n: I18n
|
||||
// eslint-disable-next-line react/no-unused-prop-types
|
||||
save: () => void // eslint confused
|
||||
|
|
|
|||
|
|
@ -36,8 +36,8 @@ declare module '@uppy/core' {
|
|||
}
|
||||
}
|
||||
|
||||
export interface Opts extends UIPluginOptions {
|
||||
target: string | HTMLElement
|
||||
interface Opts extends UIPluginOptions {
|
||||
target?: string | HTMLElement
|
||||
quality?: number
|
||||
cropperOptions?: Cropper.Options & {
|
||||
croppedCanvasOptions?: Cropper.GetCroppedCanvasOptions
|
||||
|
|
@ -54,13 +54,14 @@ export interface Opts extends UIPluginOptions {
|
|||
cropWidescreenVertical?: boolean
|
||||
}
|
||||
}
|
||||
export type { Opts as ImageEditorOptions }
|
||||
|
||||
type PluginState<M extends Meta, B extends Body> = {
|
||||
currentImage: UppyFile<M, B> | null
|
||||
}
|
||||
|
||||
const defaultCropperOptions = {
|
||||
viewMode: 0,
|
||||
viewMode: 0 as const,
|
||||
background: false,
|
||||
autoCropArea: 1,
|
||||
responsive: true,
|
||||
|
|
@ -68,7 +69,7 @@ const defaultCropperOptions = {
|
|||
minCropBoxHeight: 70,
|
||||
croppedCanvasOptions: {},
|
||||
initialAspectRatio: 0,
|
||||
} satisfies Opts['cropperOptions']
|
||||
} satisfies Partial<Opts['cropperOptions']>
|
||||
|
||||
const defaultActions = {
|
||||
revert: true,
|
||||
|
|
@ -80,7 +81,7 @@ const defaultActions = {
|
|||
cropSquare: true,
|
||||
cropWidescreen: true,
|
||||
cropWidescreenVertical: true,
|
||||
} satisfies Opts['actions']
|
||||
} satisfies Partial<Opts['actions']>
|
||||
|
||||
const defaultOptions = {
|
||||
target: 'body',
|
||||
|
|
@ -89,17 +90,26 @@ const defaultOptions = {
|
|||
quality: 0.8,
|
||||
actions: defaultActions,
|
||||
cropperOptions: defaultCropperOptions,
|
||||
} satisfies Opts
|
||||
} satisfies Partial<Opts>
|
||||
|
||||
export type ImageEditorOpts = DefinePluginOpts<
|
||||
Opts,
|
||||
keyof typeof defaultOptions
|
||||
>
|
||||
type InternalImageEditorOpts = Omit<
|
||||
DefinePluginOpts<Opts, keyof typeof defaultOptions>,
|
||||
'actions' | 'cropperOptions'
|
||||
> & {
|
||||
actions: DefinePluginOpts<
|
||||
NonNullable<Opts['actions']>,
|
||||
keyof typeof defaultActions
|
||||
>
|
||||
cropperOptions: DefinePluginOpts<
|
||||
NonNullable<Opts['cropperOptions']>,
|
||||
keyof typeof defaultCropperOptions
|
||||
>
|
||||
}
|
||||
|
||||
export default class ImageEditor<
|
||||
M extends Meta,
|
||||
B extends Body,
|
||||
> extends UIPlugin<ImageEditorOpts, M, B, PluginState<M, B>> {
|
||||
> extends UIPlugin<InternalImageEditorOpts, M, B, PluginState<M, B>> {
|
||||
static VERSION = packageJson.version
|
||||
|
||||
cropper: Cropper
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ describe('XHRUpload', () => {
|
|||
core.use(XHRUpload, {
|
||||
id: 'XHRUpload',
|
||||
endpoint: 'https://fake-endpoint.uppy.io',
|
||||
// @ts-expect-error that option does not exist
|
||||
some: 'option',
|
||||
getResponseData,
|
||||
})
|
||||
|
|
@ -65,6 +66,7 @@ describe('XHRUpload', () => {
|
|||
core.use(XHRUpload, {
|
||||
id: 'XHRUpload',
|
||||
endpoint: 'https://fake-endpoint.uppy.io',
|
||||
// @ts-expect-error that option doesn't exist
|
||||
some: 'option',
|
||||
validateStatus,
|
||||
getResponseError(responseText) {
|
||||
|
|
|
|||
|
|
@ -105,7 +105,6 @@ function setTypeInBlob<M extends Meta, B extends Body>(file: UppyFile<M, B>) {
|
|||
}
|
||||
|
||||
const defaultOptions = {
|
||||
endpoint: '',
|
||||
formData: true,
|
||||
fieldName: 'file',
|
||||
method: 'post',
|
||||
|
|
@ -132,7 +131,7 @@ const defaultOptions = {
|
|||
validateStatus(status) {
|
||||
return status >= 200 && status < 300
|
||||
},
|
||||
} satisfies XhrUploadOpts<any, any>
|
||||
} satisfies Partial<XhrUploadOpts<any, any>>
|
||||
|
||||
type Opts<M extends Meta, B extends Body> = DefinePluginOpts<
|
||||
XhrUploadOpts<M, B>,
|
||||
|
|
@ -169,6 +168,8 @@ export default class XHRUpload<
|
|||
|
||||
// Simultaneous upload limiting is shared across all uploads with this plugin.
|
||||
if (internalRateLimitedQueue in this.opts) {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore untyped internal
|
||||
this.requests = this.opts[internalRateLimitedQueue]
|
||||
} else {
|
||||
this.requests = new RateLimitedQueue(this.opts.limit)
|
||||
|
|
@ -608,6 +609,8 @@ export default class XHRUpload<
|
|||
|
||||
// No limit configured by the user, and no RateLimitedQueue passed in by a "parent" plugin
|
||||
// (basically just AwsS3) using the internal symbol
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore untyped internal
|
||||
if (this.opts.limit === 0 && !this.opts[internalRateLimitedQueue]) {
|
||||
this.uppy.log(
|
||||
'[XHRUpload] When uploading multiple files at once, consider setting the `limit` option (to `10` for example), to limit the number of concurrent uploads, which helps prevent memory and network issues: https://uppy.io/docs/xhr-upload/#limit-0',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue