Skip to content

Commit

Permalink
Merge branch 'main' into form-ts
Browse files Browse the repository at this point in the history
* main:
  Introduce `ValidateableFile` & move `MinimalRequiredUppyFile` into utils (#4944)
  uppy: fix bundle builder (#4950)
  @uppy/core: improve `UIPluginOptions` types (#4946)
  @uppy/companion-client: fix body/url on upload-success (#4922)
  @uppy/utils: remove EventManager circular reference (#4949)
  • Loading branch information
Murderlon committed Feb 22, 2024
2 parents 34a7b8a + 36b55b2 commit ad3ebe2
Show file tree
Hide file tree
Showing 16 changed files with 414 additions and 56 deletions.
3 changes: 2 additions & 1 deletion bin/build-bundle.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ function buildBundle (srcFile, bundleFile, { minify = true, standalone = '', plu
outfile: bundleFile,
platform: 'browser',
minify,
keepNames: true,
keepNames: target !== 'es5',
plugins,
tsconfigRaw: '{}',
target,
format,
}).then(() => {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
"core-js": "~3.24.0",
"cssnano": "^5.0.6",
"dotenv": "^16.0.0",
"esbuild": "^0.17.1",
"esbuild": "^0.20.1",
"esbuild-plugin-babel": "^0.2.3",
"eslint": "^8.0.0",
"eslint-config-prettier": "^9.0.0",
Expand Down
9 changes: 6 additions & 3 deletions packages/@uppy/audio/src/Audio.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import { h } from 'preact'

import { UIPlugin, type UIPluginOptions } from '@uppy/core'
import type { Body, Meta } from '@uppy/utils/lib/UppyFile'
import type { Uppy, MinimalRequiredUppyFile } from '@uppy/core/lib/Uppy.ts'
import type {
Body,
Meta,
MinimalRequiredUppyFile,
} from '@uppy/utils/lib/UppyFile'
import type { Uppy } from '@uppy/core/lib/Uppy.ts'

import getFileTypeExtension from '@uppy/utils/lib/getFileTypeExtension'
import supportsMediaRecorder from './supportsMediaRecorder.ts'
Expand All @@ -14,7 +18,6 @@ import locale from './locale.ts'
import packageJson from '../package.json'

interface AudioOptions extends UIPluginOptions {
target?: HTMLElement | string
showAudioSourceDropdown?: boolean
}
interface AudioState {
Expand Down
7 changes: 5 additions & 2 deletions packages/@uppy/companion-client/src/RequestClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -479,13 +479,16 @@ export default class RequestClient<M extends Meta, B extends Body> {
break
}
case 'success': {
// payload.response exists for xhr-upload but not for tus/transloadit
const text = payload.response?.responseText

this.uppy.emit(
'upload-success',
this.uppy.getFile(file.id),
// @ts-expect-error event expects a lot more data.
// TODO: add missing data?
{
uploadURL: payload.url,
status: payload.response?.status ?? 200,
body: text ? JSON.parse(text) : undefined,
},
)
socketAbortController?.abort?.()
Expand Down
10 changes: 9 additions & 1 deletion packages/@uppy/companion/src/server/Uploader.js
Original file line number Diff line number Diff line change
Expand Up @@ -642,8 +642,16 @@ class Uploader {
throw new Error(errMsg)
}

let bodyURL = null
try {
bodyURL = JSON.parse(response.body)?.url
} catch {
// response.body can be undefined or an empty string
// in that case we ignore and continue.
}

return {
url: null,
url: bodyURL,
extraData: { response: getRespObj(response), bytesUploaded },
}
} catch (err) {
Expand Down
28 changes: 19 additions & 9 deletions packages/@uppy/core/src/Restricter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@ export type Restrictions = {
requiredMetaFields: string[]
}

/**
* The minimal required properties to be present from UppyFile in order to validate it.
*/
export type ValidateableFile<M extends Meta, B extends Body> = Pick<
UppyFile<M, B>,
'type' | 'extension' | 'size' | 'name'
// Both UppyFile and CompanionFile need to be passable as a ValidateableFile
// CompanionFile's do not have `isGhost`, so we mark it optional.
> & { isGhost?: boolean }

const defaultOptions = {
maxFileSize: null,
minFileSize: null,
Expand Down Expand Up @@ -69,8 +79,8 @@ class Restricter<M extends Meta, B extends Body> {

// Because these operations are slow, we cannot run them for every file (if we are adding multiple files)
validateAggregateRestrictions(
existingFiles: UppyFile<M, B>[],
addingFiles: UppyFile<M, B>[],
existingFiles: ValidateableFile<M, B>[],
addingFiles: ValidateableFile<M, B>[],
): void {
const { maxTotalFileSize, maxNumberOfFiles } = this.getOpts().restrictions

Expand Down Expand Up @@ -109,7 +119,7 @@ class Restricter<M extends Meta, B extends Body> {
}
}

validateSingleFile(file: UppyFile<M, B>): void {
validateSingleFile(file: ValidateableFile<M, B>): void {
const { maxFileSize, minFileSize, allowedFileTypes } =
this.getOpts().restrictions

Expand All @@ -134,7 +144,7 @@ class Restricter<M extends Meta, B extends Body> {
this.i18n('youCanOnlyUploadFileTypes', {
types: allowedFileTypesString,
}),
{ file },
{ file } as { file: UppyFile<M, B> },
)
}
}
Expand All @@ -146,7 +156,7 @@ class Restricter<M extends Meta, B extends Body> {
size: prettierBytes(maxFileSize),
file: file.name,
}),
{ file },
{ file } as { file: UppyFile<M, B> },
)
}

Expand All @@ -156,14 +166,14 @@ class Restricter<M extends Meta, B extends Body> {
this.i18n('inferiorSize', {
size: prettierBytes(minFileSize),
}),
{ file },
{ file } as { file: UppyFile<M, B> },
)
}
}

validate(
existingFiles: UppyFile<M, B>[],
addingFiles: UppyFile<M, B>[],
existingFiles: ValidateableFile<M, B>[],
addingFiles: ValidateableFile<M, B>[],
): void {
addingFiles.forEach((addingFile) => {
this.validateSingleFile(addingFile)
Expand All @@ -180,7 +190,7 @@ class Restricter<M extends Meta, B extends Body> {
}
}

getMissingRequiredMetaFields(file: UppyFile<M, B>): {
getMissingRequiredMetaFields(file: ValidateableFile<M, B> & { meta: M }): {
missingFields: string[]
error: RestrictionError<M, B>
} {
Expand Down
13 changes: 7 additions & 6 deletions packages/@uppy/core/src/UIPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,14 @@ function debounce<T extends (...args: any[]) => any>(
}
}

export interface UIPluginOptions extends PluginOpts {
target?: null | string | Element | typeof BasePlugin
replaceTargetContent?: boolean
direction?: 'ltr' | 'rtl'
}

/**
* UIPlugin is the extended version of BasePlugin to incorporate rendering with Preact.
* Use this for plugins that need a user interface.
*
* For plugins without an user interface, see BasePlugin.
*/
class UIPlugin<
// eslint-disable-next-line no-use-before-define
Opts extends UIPluginOptions,
M extends Meta,
B extends Body,
Expand Down Expand Up @@ -206,3 +201,9 @@ export type PluginTarget<M extends Meta, B extends Body> =
| typeof BasePlugin
| typeof UIPlugin
| BasePlugin<any, M, B>

export interface UIPluginOptions extends PluginOpts {
target?: PluginTarget<any, any>
replaceTargetContent?: boolean
direction?: 'ltr' | 'rtl'
}
33 changes: 15 additions & 18 deletions packages/@uppy/core/src/Uppy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,12 @@ import DefaultStore from '@uppy/store-default'
import getFileType from '@uppy/utils/lib/getFileType'
import getFileNameAndExtension from '@uppy/utils/lib/getFileNameAndExtension'
import { getSafeFileId } from '@uppy/utils/lib/generateFileID'
import type { UppyFile, Meta, Body } from '@uppy/utils/lib/UppyFile'
import type {
UppyFile,
Meta,
Body,
MinimalRequiredUppyFile,
} from '@uppy/utils/lib/UppyFile'
import type { CompanionFile } from '@uppy/utils/lib/CompanionFile'
import type {
CompanionClientProvider,
Expand Down Expand Up @@ -43,7 +48,7 @@ import locale from './locale.ts'

import type BasePlugin from './BasePlugin.ts'
import type UIPlugin from './UIPlugin.ts'
import type { Restrictions } from './Restricter.ts'
import type { Restrictions, ValidateableFile } from './Restricter.ts'

type Processor = (fileIDs: string[], uploadID: string) => Promise<void> | void

Expand Down Expand Up @@ -128,17 +133,6 @@ export type UnknownSearchProviderPlugin<
provider: CompanionClientSearchProvider
}

// The user facing type for UppyFile used in uppy.addFile() and uppy.setOptions()
export type MinimalRequiredUppyFile<M extends Meta, B extends Body> = Required<
Pick<UppyFile<M, B>, 'name' | 'data' | 'type' | 'source'>
> &
Partial<
Omit<UppyFile<M, B>, 'name' | 'data' | 'type' | 'source' | 'meta'>
// We want to omit the 'meta' from UppyFile because of internal metadata
// (see InternalMetadata in `UppyFile.ts`), as when adding a new file
// that is not required.
> & { meta?: M }

interface UploadResult<M extends Meta, B extends Body> {
successful?: UppyFile<M, B>[]
failed?: UppyFile<M, B>[]
Expand Down Expand Up @@ -844,8 +838,8 @@ export class Uppy<M extends Meta, B extends Body> {
}

validateRestrictions(
file: UppyFile<M, B>,
files = this.getFiles(),
file: ValidateableFile<M, B>,
files: ValidateableFile<M, B>[] = this.getFiles(),
): RestrictionError<M, B> | null {
try {
this.#restricter.validate(files, [file])
Expand Down Expand Up @@ -882,9 +876,12 @@ export class Uppy<M extends Meta, B extends Body> {
const { allowNewUpload } = this.getState()

if (allowNewUpload === false) {
const error = new RestrictionError(this.i18n('noMoreFilesAllowed'), {
file,
})
const error = new RestrictionError<M, B>(
this.i18n('noMoreFilesAllowed'),
{
file,
},
)
this.#informAndEmit([error])
throw error
}
Expand Down
1 change: 0 additions & 1 deletion packages/@uppy/image-editor/src/ImageEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ declare module '@uppy/core' {
}

interface Opts extends UIPluginOptions {
target?: string | HTMLElement
quality?: number
cropperOptions?: Cropper.Options & {
croppedCanvasOptions?: Cropper.GetCroppedCanvasOptions
Expand Down
1 change: 0 additions & 1 deletion packages/@uppy/status-bar/src/StatusBarOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import type { UIPluginOptions } from '@uppy/core/lib/UIPlugin'
import type StatusBarLocale from './locale.ts'

export interface StatusBarOptions extends UIPluginOptions {
target?: HTMLElement | string
showProgressDetails?: boolean
hideUploadButton?: boolean
hideAfterFinish?: boolean
Expand Down
83 changes: 83 additions & 0 deletions packages/@uppy/utils/src/EventManager.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/**
* Create a wrapper around an event emitter with a `remove` method to remove
* all events that were added using the wrapped emitter.
*/
export default class EventManager {
#uppy

#events = []

constructor (uppy) {
this.#uppy = uppy
}

on (event, fn) {
this.#events.push([event, fn])
return this.#uppy.on(event, fn)
}

remove () {
for (const [event, fn] of this.#events.splice(0)) {
this.#uppy.off(event, fn)
}
}

onFilePause (fileID, cb) {
this.on('upload-pause', (targetFileID, isPaused) => {
if (fileID === targetFileID) {
cb(isPaused)
}
})
}

onFileRemove (fileID, cb) {
this.on('file-removed', (file) => {
if (fileID === file.id) cb(file.id)
})
}

onPause (fileID, cb) {
this.on('upload-pause', (targetFileID, isPaused) => {
if (fileID === targetFileID) {
// const isPaused = this.#uppy.pauseResume(fileID)
cb(isPaused)
}
})
}

onRetry (fileID, cb) {
this.on('upload-retry', (targetFileID) => {
if (fileID === targetFileID) {
cb()
}
})
}

onRetryAll (fileID, cb) {
this.on('retry-all', () => {
if (!this.#uppy.getFile(fileID)) return
cb()
})
}

onPauseAll (fileID, cb) {
this.on('pause-all', () => {
if (!this.#uppy.getFile(fileID)) return
cb()
})
}

onCancelAll (fileID, eventHandler) {
this.on('cancel-all', (...args) => {
if (!this.#uppy.getFile(fileID)) return
eventHandler(...args)
})
}

onResumeAll (fileID, cb) {
this.on('resume-all', () => {
if (!this.#uppy.getFile(fileID)) return
cb()
})
}
}
3 changes: 0 additions & 3 deletions packages/@uppy/utils/src/EventManager.ts

This file was deleted.

16 changes: 14 additions & 2 deletions packages/@uppy/utils/src/UppyFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,16 @@ export interface UppyFile<M extends Meta, B extends Body> {
remote?: {
body?: Record<string, unknown>
companionUrl: string
host: string
host?: string
provider?: string
providerName?: string
requestClientId: string
url: string
}
serverToken?: string | null
size: number | null
source?: string
type?: string
type: string
uploadURL?: string
response?: {
body: B
Expand All @@ -40,3 +41,14 @@ export interface UppyFile<M extends Meta, B extends Body> {
uploadURL?: string
}
}

// The user facing type for UppyFile used in uppy.addFile() and uppy.setOptions()
export type MinimalRequiredUppyFile<M extends Meta, B extends Body> = Required<
Pick<UppyFile<M, B>, 'name' | 'data'>
> &
Partial<
Omit<UppyFile<M, B>, 'name' | 'data' | 'meta'>
// We want to omit the 'meta' from UppyFile because of internal metadata
// (see InternalMetadata in `UppyFile.ts`), as when adding a new file
// that is not required.
> & { meta?: M }
Loading

0 comments on commit ad3ebe2

Please sign in to comment.