import { type Store } from '@uppy/store-default'; import type { Body, CompanionClientProvider, CompanionClientSearchProvider, CompanionFile, FileProgressStarted, I18n, Locale, Meta, MinimalRequiredUppyFile, OptionalPluralizeLocale, UppyFile, UppyFileId } from '@uppy/utils'; import { Translator } from '@uppy/utils'; import type { h } from 'preact'; import type BasePlugin from './BasePlugin.js'; import { debugLogger } from './loggers.js'; import type { Restrictions, ValidateableFile } from './Restricter.js'; import { RestrictionError } from './Restricter.js'; type Processor = (fileIDs: string[], uploadID: string) => Promise | void; type LogLevel = 'info' | 'warning' | 'error' | 'success'; export type UnknownPlugin = Record> = BasePlugin; /** * ids are always `string`s, except the root folder's id can be `null` */ export type PartialTreeId = string | null; export type PartialTreeStatusFile = 'checked' | 'unchecked'; export type PartialTreeStatus = PartialTreeStatusFile | 'partial'; export type PartialTreeFile = { type: 'file'; id: string; /** * There exist two types of restrictions: * - individual restrictions (`allowedFileTypes`, `minFileSize`, `maxFileSize`), and * - aggregate restrictions (`maxNumberOfFiles`, `maxTotalFileSize`). * * `.restrictionError` reports whether this file passes individual restrictions. * */ restrictionError: string | null; status: PartialTreeStatusFile; parentId: PartialTreeId; data: CompanionFile; }; export type PartialTreeFolderNode = { type: 'folder'; id: string; /** * Consider `(.nextPagePath, .cached)` a composite key that can represent 4 states: * - `{ cached: true, nextPagePath: null }` - we fetched all pages in this folder * - `{ cached: true, nextPagePath: 'smth' }` - we fetched 1st page, and there are still pages left to fetch in this folder * - `{ cached: false, nextPagePath: null }` - we didn't fetch the 1st page in this folder * - `{ cached: false, nextPagePath: 'someString' }` - ❌ CAN'T HAPPEN ❌ */ cached: boolean; nextPagePath: PartialTreeId; status: PartialTreeStatus; parentId: PartialTreeId; data: Pick; }; export type PartialTreeFolderRoot = { type: 'root'; id: PartialTreeId; cached: boolean; nextPagePath: PartialTreeId; }; export type PartialTreeFolder = PartialTreeFolderNode | PartialTreeFolderRoot; /** * PartialTree has the following structure. * * FolderRoot * ┌─────┴─────┐ * FolderNode File * ┌─────┴────┐ * File File * * Root folder is called `PartialTreeFolderRoot`, * all other folders are called `PartialTreeFolderNode`, because they are "internal nodes". * * It's possible for `PartialTreeFolderNode` to be a leaf node if it doesn't contain any files. */ export type PartialTree = (PartialTreeFile | PartialTreeFolder)[]; export type UnknownProviderPluginState = { authenticated: boolean | undefined; didFirstRender: boolean; searchString: string; loading: boolean | string; partialTree: PartialTree; currentFolderId: PartialTreeId; username: string | null; searchResults?: string[] | undefined; }; export interface PluginTypeRegistry { } export interface AsyncStore { getItem: (key: string) => Promise; setItem: (key: string, value: string) => Promise; removeItem: (key: string) => Promise; } /** * This is a base for a provider that does not necessarily use the Companion-assisted OAuth2 flow */ export interface BaseProviderPlugin { title: string; icon: () => h.JSX.Element; storage: AsyncStore; } export type UnknownProviderPlugin = UnknownPlugin & BaseProviderPlugin & { rootFolderId: string | null; files: UppyFile[]; provider: CompanionClientProvider; view: any; }; export type UnknownSearchProviderPluginState = { isInputMode: boolean; } & Pick; export type UnknownSearchProviderPlugin = UnknownPlugin & BaseProviderPlugin & { provider: CompanionClientSearchProvider; }; export type UploadId = string; export interface UploadResult { successful?: UppyFile[]; failed?: UppyFile[]; uploadID?: UploadId; [key: string]: unknown; } interface CurrentUpload { fileIDs: UppyFileId[]; step: number; result: UploadResult; } interface Plugins extends Record | undefined> { } type UppyFilesMap = { [key: UppyFileId]: UppyFile; }; export interface State extends Record { meta: M; capabilities: { uploadProgress: boolean; individualCancellation: boolean; resumableUploads: boolean; isMobileDevice?: boolean; darkMode?: boolean; }; currentUploads: Record>; allowNewUpload: boolean; /** `recoveredState` is a special version of state in which the files don't have any data (because the data was never stored) */ recoveredState: (Omit, 'currentUploads'>, 'files'> & { files: Record, 'data'>>; }) | null; error: string | null; files: UppyFilesMap; info: Array<{ isHidden?: boolean; type: LogLevel; message: string; details?: string | Record | null; }>; plugins: Plugins; totalProgress: number; companion?: Record; } export interface UppyOptions { id?: string; autoProceed?: boolean; /** * @deprecated Use allowMultipleUploadBatches */ allowMultipleUploads?: boolean; allowMultipleUploadBatches?: boolean; logger?: typeof debugLogger; debug?: boolean; restrictions: Restrictions; meta?: M; onBeforeFileAdded?: (currentFile: UppyFile, files: { [key: string]: UppyFile; }) => UppyFile | boolean | undefined; onBeforeUpload?: (files: { [key: string]: UppyFile; }) => { [key: string]: UppyFile; } | boolean; locale?: Locale; store?: Store>; infoTimeout?: number; } export interface UppyOptionsWithOptionalRestrictions extends Omit, 'restrictions'> { restrictions?: Partial; } type MinimalRequiredOptions = Partial, 'locale' | 'meta' | 'restrictions'> & { locale: OptionalPluralizeLocale; meta: Partial; restrictions: Partial; }>; export type NonNullableUppyOptions = Required>; export interface _UppyEventMap { 'back-online': () => void; 'cancel-all': () => void; complete: (result: UploadResult) => void; error: (error: { name: string; message: string; details?: string; }, file?: UppyFile, response?: UppyFile['response']) => void; 'file-added': (file: UppyFile) => void; 'file-removed': (file: UppyFile) => void; 'files-added': (files: UppyFile[]) => void; 'info-hidden': () => void; 'info-visible': () => void; 'is-offline': () => void; 'is-online': () => void; 'pause-all': () => void; 'plugin-added': (plugin: UnknownPlugin) => void; 'plugin-remove': (plugin: UnknownPlugin) => void; 'postprocess-complete': (file: UppyFile | undefined, progress?: NonNullable) => void; 'postprocess-progress': (file: UppyFile | undefined, progress: NonNullable) => void; 'preprocess-complete': (file: UppyFile | undefined, progress?: NonNullable) => void; 'preprocess-progress': (file: UppyFile | undefined, progress: NonNullable) => void; progress: (progress: number) => void; restored: (pluginData: unknown) => void; 'restore-confirmed': () => void; 'restriction-failed': (file: UppyFile | undefined, error: Error) => void; 'resume-all': () => void; 'retry-all': (files: UppyFile[]) => void; 'state-update': (prevState: State, nextState: State, patch?: Partial>) => void; upload: (uploadID: string, files: UppyFile[]) => void; 'upload-error': (file: UppyFile | undefined, error: { name: string; message: string; details?: string; }, response?: Omit['response']>, 'uploadURL'> | undefined) => void; 'upload-pause': (file: UppyFile | undefined, isPaused: boolean) => void; 'upload-progress': (file: UppyFile | undefined, progress: FileProgressStarted) => void; 'upload-retry': (file: UppyFile) => void; 'upload-stalled': (error: { message: string; details?: string; }, files: UppyFile[]) => void; 'upload-success': (file: UppyFile | undefined, response: NonNullable['response']>) => void; } export interface UppyEventMap extends _UppyEventMap { 'upload-start': (files: UppyFile[]) => void; } /** `OmitFirstArg` is the type of the returned value of `someArray.slice(1)`. */ type OmitFirstArg = T extends [any, ...infer U] ? U : never; /** * Uppy Core module. * Manages plugins, state updates, acts as an event bus, * adds/removes files and metadata. */ export declare class Uppy> { #private; static VERSION: string; defaultLocale: OptionalPluralizeLocale; locale: Locale; opts: NonNullableUppyOptions; store: NonNullableUppyOptions['store']; i18n: I18n; i18nArray: Translator['translateArray']; scheduledAutoProceed: ReturnType | null; wasOffline: boolean; /** * Instantiate Uppy */ constructor(opts?: UppyOptionsWithOptionalRestrictions); emit>(event: T, ...args: Parameters[T]>): void; on>(event: K, callback: UppyEventMap[K]): this; once>(event: K, callback: UppyEventMap[K]): this; off>(event: K, callback: UppyEventMap[K]): this; /** * Iterate on all plugins and run `update` on them. * Called each time state changes. * */ updateAll(state: Partial>): void; /** * Updates state with a patch */ setState(patch?: Partial>): void; /** * Returns current state. */ getState(): State; patchFilesState(filesWithNewState: { [id: string]: Partial>; }): void; /** * Shorthand to set state for a specific file. */ setFileState(fileID: string, state: Partial>): void; i18nInit(): void; setOptions(newOpts: MinimalRequiredOptions): void; resetProgress(): void; clear(): void; addPreProcessor(fn: Processor): void; removePreProcessor(fn: Processor): boolean; addPostProcessor(fn: Processor): void; removePostProcessor(fn: Processor): boolean; addUploader(fn: Processor): void; removeUploader(fn: Processor): boolean; setMeta(data: Partial): void; setFileMeta(fileID: string, data: State['meta']): void; /** * Get a file object. */ getFile(fileID: string): UppyFile; /** * Get all files in an array. */ getFiles(): UppyFile[]; getFilesByIds(ids: string[]): UppyFile[]; getObjectOfFilesPerState(): { newFiles: UppyFile[]; startedFiles: UppyFile[]; uploadStartedFiles: UppyFile[]; pausedFiles: UppyFile[]; completeFiles: UppyFile[]; erroredFiles: UppyFile[]; inProgressFiles: UppyFile[]; inProgressNotPausedFiles: UppyFile[]; processingFiles: UppyFile[]; isUploadStarted: boolean; isAllComplete: boolean; isAllErrored: boolean; isAllPaused: boolean; isUploadInProgress: boolean; isSomeGhost: boolean; }; validateRestrictions(file: ValidateableFile, files?: ValidateableFile[]): RestrictionError | null; validateSingleFile(file: ValidateableFile): string | null; validateAggregateRestrictions(files: ValidateableFile[]): string | null; checkIfFileAlreadyExists(fileID: string): boolean; /** * Add a new file to `state.files`. This will run `onBeforeFileAdded`, * try to guess file type in a clever way, check file against restrictions, * and start an upload if `autoProceed === true`. */ addFile(file: File | MinimalRequiredUppyFile): UppyFile['id']; /** * Add multiple files to `state.files`. See the `addFile()` documentation. * * If an error occurs while adding a file, it is logged and the user is notified. * This is good for UI plugins, but not for programmatic use. * Programmatic users should usually still use `addFile()` on individual files. */ addFiles(fileDescriptors: MinimalRequiredUppyFile[]): void; removeFiles(fileIDs: string[]): void; removeFile(fileID: string): void; pauseResume(fileID: string): boolean | undefined; pauseAll(): void; resumeAll(): void; retryAll(): Promise | undefined>; cancelAll(): void; /** * Retry a specific file that has errored. */ retryUpload(fileID: string): Promise | undefined>; logout(): void; updateOnlineStatus(): void; getID(): string; /** * Registers a plugin with Core. */ use>(Plugin: T, ...args: OmitFirstArg>): this; /** * Find one Plugin by name. */ getPlugin>(id: K): PluginTypeRegistry[K] | undefined; getPlugin = UnknownPlugin>(id: string): T | undefined; /** * Iterate through all `use`d plugins. * */ iteratePlugins(method: (plugin: UnknownPlugin) => void): void; /** * Uninstall and remove a plugin. * * @param {object} instance The plugin instance to remove. */ removePlugin(instance: UnknownPlugin): void; /** * Uninstall all plugins and close down this Uppy instance. */ destroy(): void; hideInfo(): void; /** * Set info message in `state.info`, so that UI plugins like `Informer` * can display the message. */ info(message: string | { message: string; details?: string | Record; }, type?: LogLevel, duration?: number): void; /** * Passes messages to a function, provided in `opts.logger`. * If `opts.logger: Uppy.debugLogger` or `opts.debug: true`, logs to the browser console. */ log(message: unknown, type?: 'error' | 'warning'): void; registerRequestClient(id: string, client: unknown): void; /** @protected */ getRequestClientForFile(file: UppyFile): Client; /** * Restore an upload by its ID. */ restore(uploadID: string): Promise | undefined>; /** * Add data to an upload's result object. */ addResultData(uploadID: string, data: CurrentUpload['result']): void; /** * Start an upload for all the files that are not currently being uploaded. */ upload(): Promise> | undefined>; } export default Uppy; //# sourceMappingURL=Uppy.d.ts.map