diff --git a/packages/@uppy/core/src/Uppy.ts b/packages/@uppy/core/src/Uppy.ts index d27dda17c0..0814514b67 100644 --- a/packages/@uppy/core/src/Uppy.ts +++ b/packages/@uppy/core/src/Uppy.ts @@ -89,7 +89,7 @@ interface Plugins extends Record | undefined> {} export interface State extends Record { - meta: M + meta: Partial capabilities: { uploadProgress: boolean individualCancellation: boolean @@ -124,7 +124,7 @@ export interface UppyOptions { logger?: typeof debugLogger debug?: boolean restrictions: Restrictions - meta?: M + meta?: Partial onBeforeFileAdded?: ( currentFile: UppyFile, files: { [key: string]: UppyFile }, @@ -132,7 +132,7 @@ export interface UppyOptions { onBeforeUpload?: (files: { [key: string]: UppyFile }) => { [key: string]: UppyFile } | boolean - locale?: Locale + locale?: OptionalPluralizeLocale // TODO: add > when landing on `4.x` store?: DefaultStore infoTimeout?: number @@ -154,9 +154,12 @@ type MinimalRequiredOptions = Partial< } > -export type NonNullableUppyOptions = Required< - UppyOptions -> +// everything is required, except for `locale` +export type NonNullableUppyOptions = Omit< + Required>, + 'locale' +> & + Pick, 'locale'> type GenericEventCallback = () => void type FileAddedCallback = ( @@ -309,7 +312,7 @@ export class Uppy { #postProcessors: Set = new Set() - defaultLocale: Locale + defaultLocale: OptionalPluralizeLocale locale: Locale @@ -331,34 +334,29 @@ export class Uppy { * Instantiate Uppy */ constructor(opts?: UppyOptionsWithOptionalRestrictions) { - this.defaultLocale = locale as any as Locale - - const defaultOptions: UppyOptions, B> = { - id: 'uppy', - autoProceed: false, - allowMultipleUploadBatches: true, - debug: false, - restrictions: defaultRestrictionOptions, - meta: {}, - onBeforeFileAdded: (file, files) => !Object.hasOwn(files, file.id), - onBeforeUpload: (files) => files, - store: new DefaultStore(), - logger: justErrorsLogger, - infoTimeout: 5000, - } - - const merged = { ...defaultOptions, ...opts } as Omit< - NonNullableUppyOptions, - 'restrictions' - > + this.defaultLocale = locale + // Merge default options with the ones set by user, - // making sure to merge restrictions too this.opts = { - ...merged, + ...opts, + id: opts?.id ?? 'uppy', + autoProceed: opts?.autoProceed ?? false, + allowMultipleUploadBatches: opts?.allowMultipleUploadBatches ?? true, + allowMultipleUploads: opts?.allowMultipleUploads ?? true, + debug: opts?.debug ?? false, + // making sure to merge restrictions too: restrictions: { - ...(defaultOptions.restrictions as Restrictions), - ...(opts && opts.restrictions), + ...defaultRestrictionOptions, + ...opts?.restrictions, }, + meta: opts?.meta ?? {}, + onBeforeFileAdded: + opts?.onBeforeFileAdded ?? + ((file, files) => !Object.hasOwn(files, file.id)), + onBeforeUpload: opts?.onBeforeUpload ?? ((files) => files), + store: opts?.store ?? new DefaultStore(), + logger: opts?.logger ?? justErrorsLogger, + infoTimeout: opts?.infoTimeout ?? 5000, } // Support debug: true for backwards-compatability, unless logger is set in opts @@ -543,10 +541,10 @@ export class Uppy { setOptions(newOpts: MinimalRequiredOptions): void { this.opts = { ...this.opts, - ...(newOpts as UppyOptions), + ...newOpts, restrictions: { ...this.opts.restrictions, - ...(newOpts?.restrictions as Restrictions), + ...newOpts?.restrictions, }, } @@ -855,7 +853,7 @@ export class Uppy { size: fileDescriptorOrFile.size, data: fileDescriptorOrFile, } - : fileDescriptorOrFile) as UppyFile + : fileDescriptorOrFile) as UppyFile // todo remove this `as` (it hides a lot of logical issues) const fileType = getFileType(file) const fileName = getFileName(fileType, file) @@ -1016,10 +1014,10 @@ export class Uppy { * and start an upload if `autoProceed === true`. */ addFile(file: File | MinimalRequiredUppyFile): UppyFile['id'] { - this.#assertNewUploadAllowed(file as UppyFile) + this.#assertNewUploadAllowed(file as UppyFile) // todo remove this `as` (it hides a lot of logical issues) const { nextFilesState, validFilesToAdd, errors } = - this.#checkAndUpdateFileState([file as UppyFile]) + this.#checkAndUpdateFileState([file as UppyFile]) // todo remove this `as` (it hides a lot of logical issues) const restrictionErrors = errors.filter((error) => error.isRestriction) this.#informAndEmit(restrictionErrors) @@ -1052,6 +1050,7 @@ export class Uppy { this.#assertNewUploadAllowed() const { nextFilesState, validFilesToAdd, errors } = + // todo remove this `as` (it hides a lot of logical issues) this.#checkAndUpdateFileState(fileDescriptors as UppyFile[]) const restrictionErrors = errors.filter((error) => error.isRestriction) @@ -1391,23 +1390,25 @@ export class Uppy { if (sizedFiles.length === 0) { const progressMax = inProgress.length * 100 - const currentProgress = unsizedFiles.reduce((acc, file) => { - return acc + (file.progress.percentage as number) - }, 0) + const currentProgress = unsizedFiles.reduce( + (acc, file) => acc + (file.progress.percentage ?? 0), + 0, + ) const totalProgress = Math.round((currentProgress / progressMax) * 100) this.setState({ totalProgress }) return } - let totalSize = sizedFiles.reduce((acc, file) => { - return (acc + (file.progress.bytesTotal ?? 0)) as number - }, 0) + let totalSize = sizedFiles.reduce( + (acc, file) => acc + (file.progress.bytesTotal ?? 0), + 0, + ) const averageSize = totalSize / sizedFiles.length totalSize += averageSize * unsizedFiles.length let uploadedSize = 0 sizedFiles.forEach((file) => { - uploadedSize += file.progress.bytesUploaded as number + uploadedSize += Number(file.progress.bytesUploaded) }) unsizedFiles.forEach((file) => { uploadedSize += (averageSize * (file.progress.percentage || 0)) / 100 @@ -1512,7 +1513,7 @@ export class Uppy { percentage: 0, bytesUploaded: 0, bytesTotal: file.size, - } as FileProgressStarted, + } satisfies FileProgressStarted, }, ]), )