Skip to content

Commit

Permalink
@uppy/companion-client: type changes for provider-views (#4938)
Browse files Browse the repository at this point in the history
  • Loading branch information
aduh95 authored Feb 21, 2024
1 parent b7f2143 commit d7e577a
Show file tree
Hide file tree
Showing 8 changed files with 175 additions and 49 deletions.
42 changes: 19 additions & 23 deletions packages/@uppy/companion-client/src/Provider.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import type { Uppy, BasePlugin } from '@uppy/core'
import type { Body, Meta, UppyFile } from '@uppy/utils/lib/UppyFile'
import type { Uppy } from '@uppy/core'
import type { Body, Meta } from '@uppy/utils/lib/UppyFile'
import type { PluginOpts } from '@uppy/core/lib/BasePlugin.ts'
import RequestClient, {
authErrorStatusCode,
type RequestOptions,
} from './RequestClient.ts'
import type {
RequestOptions,
CompanionClientProvider,
} from '@uppy/utils/lib/CompanionClientProvider'
import type { UnknownProviderPlugin } from '@uppy/core/lib/Uppy.ts'
import RequestClient, { authErrorStatusCode } from './RequestClient.ts'
import * as tokenStorage from './tokenStorage.ts'

// TODO: remove deprecated options in next major release
Expand All @@ -22,13 +24,6 @@ export interface Opts extends PluginOpts {
provider: string
}

interface ProviderPlugin<M extends Meta, B extends Body>
extends BasePlugin<Opts, M, B> {
files: UppyFile<M, B>[]

storage: typeof tokenStorage
}

const getName = (id: string) => {
return id
.split('-')
Expand Down Expand Up @@ -64,10 +59,10 @@ function isOriginAllowed(
) // allowing for trailing '/'
}

export default class Provider<
M extends Meta,
B extends Body,
> extends RequestClient<M, B> {
export default class Provider<M extends Meta, B extends Body>
extends RequestClient<M, B>
implements CompanionClientProvider
{
#refreshingTokenPromise: Promise<void> | undefined

provider: string
Expand Down Expand Up @@ -141,7 +136,10 @@ export default class Provider<
}

#getPlugin() {
const plugin = this.uppy.getPlugin(this.pluginId) as ProviderPlugin<M, B>
const plugin = this.uppy.getPlugin(this.pluginId) as UnknownProviderPlugin<
M,
B
>
if (plugin == null) throw new Error('Plugin was nullish')
return plugin
}
Expand Down Expand Up @@ -375,23 +373,21 @@ export default class Provider<
}
}

list<ResBody extends Record<string, unknown>>(
list<ResBody>(
directory: string | undefined,
options: RequestOptions,
): Promise<ResBody> {
return this.get<ResBody>(`${this.id}/list/${directory || ''}`, options)
}

async logout<ResBody extends Record<string, unknown>>(
options: RequestOptions,
): Promise<ResBody> {
async logout<ResBody>(options?: RequestOptions): Promise<ResBody> {
const response = await this.get<ResBody>(`${this.id}/logout`, options)
await this.removeAuthToken()
return response
}

static initPlugin(
plugin: ProviderPlugin<any, any>, // any because static methods cannot use class generics
plugin: UnknownProviderPlugin<any, any>, // any because static methods cannot use class generics
opts: Opts,
defaultOpts: Record<string, unknown>,
): void {
Expand Down
8 changes: 1 addition & 7 deletions packages/@uppy/companion-client/src/RequestClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import getSocketHost from '@uppy/utils/lib/getSocketHost'

import type Uppy from '@uppy/core'
import type { UppyFile, Meta, Body } from '@uppy/utils/lib/UppyFile'
import type { RequestOptions } from '@uppy/utils/lib/CompanionClientProvider.ts'
import AuthError from './AuthError.ts'
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore We don't want TS to generate types for the package.json
Expand All @@ -28,13 +29,6 @@ export type Opts = {
companionKeysParams?: Record<string, string>
}

export type RequestOptions = {
method?: string
data?: Record<string, unknown>
skipPostResponse?: boolean
signal?: AbortSignal
qs?: Record<string, string>
}
type _RequestOptions =
| boolean // TODO: remove this on the next major
| RequestOptions
Expand Down
14 changes: 6 additions & 8 deletions packages/@uppy/companion-client/src/SearchProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import type { Body, Meta } from '@uppy/utils/lib/UppyFile.ts'
import type { Uppy } from '@uppy/core'
import type { CompanionClientSearchProvider } from '@uppy/utils/lib/CompanionClientProvider'
import RequestClient, { type Opts } from './RequestClient.ts'

const getName = (id: string): string => {
Expand All @@ -11,10 +12,10 @@ const getName = (id: string): string => {
.join(' ')
}

export default class SearchProvider<
M extends Meta,
B extends Body,
> extends RequestClient<M, B> {
export default class SearchProvider<M extends Meta, B extends Body>
extends RequestClient<M, B>
implements CompanionClientSearchProvider
{
provider: string

id: string
Expand All @@ -35,10 +36,7 @@ export default class SearchProvider<
return `${this.hostname}/search/${this.id}/get/${id}`
}

search<ResBody extends Record<string, unknown>>(
text: string,
queries?: string,
): Promise<ResBody> {
search<ResBody>(text: string, queries?: string): Promise<ResBody> {
return this.get<ResBody>(
`search/${this.id}/list?q=${encodeURIComponent(text)}${
queries ? `&${queries}` : ''
Expand Down
89 changes: 79 additions & 10 deletions packages/@uppy/core/src/Uppy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ 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 { CompanionFile } from '@uppy/utils/lib/CompanionFile'
import type {
CompanionClientProvider,
CompanionClientSearchProvider,
} from '@uppy/utils/lib/CompanionClientProvider'
import type {
FileProgressNotStarted,
FileProgressStarted,
Expand Down Expand Up @@ -46,19 +51,83 @@ type FileRemoveReason = 'user' | 'cancel-all'

type LogLevel = 'info' | 'warning' | 'error' | 'success'

export type UnknownPlugin<M extends Meta, B extends Body> = InstanceType<
typeof BasePlugin<any, M, B> | typeof UIPlugin<any, M, B>
>

type UnknownProviderPlugin<M extends Meta, B extends Body> = UnknownPlugin<
M,
B
> & {
provider: {
logout: () => void
export type UnknownPlugin<
M extends Meta,
B extends Body,
PluginState extends Record<string, unknown> = Record<string, unknown>,
> = BasePlugin<any, M, B, PluginState>

export type UnknownProviderPluginState = {
authenticated: boolean | undefined
breadcrumbs: {
requestPath: string
name: string
id?: string
}[]
didFirstRender: boolean
currentSelection: CompanionFile[]
filterInput: string
loading: boolean | string
folders: CompanionFile[]
files: CompanionFile[]
isSearchVisible: boolean
}
/*
* UnknownProviderPlugin can be any Companion plugin (such as Google Drive).
* As the plugins are passed around throughout Uppy we need a generic type for this.
* It may seems like duplication, but this type safe. Changing the type of `storage`
* will error in the `Provider` class of @uppy/companion-client and vice versa.
*
* Note that this is the *plugin* class, not a version of the `Provider` class.
* `Provider` does operate on Companion plugins with `uppy.getPlugin()`.
*/
export type UnknownProviderPlugin<
M extends Meta,
B extends Body,
> = UnknownPlugin<M, B, UnknownProviderPluginState> & {
onFirstRender: () => void
title: string
files: UppyFile<M, B>[]
icon: () => JSX.Element
provider: CompanionClientProvider
storage: {
getItem: (key: string) => Promise<string | null>
setItem: (key: string, value: string) => Promise<void>
removeItem: (key: string) => Promise<void>
}
}

/*
* UnknownSearchProviderPlugin can be any search Companion plugin (such as Unsplash).
* As the plugins are passed around throughout Uppy we need a generic type for this.
* It may seems like duplication, but this type safe. Changing the type of `title`
* will error in the `SearchProvider` class of @uppy/companion-client and vice versa.
*
* Note that this is the *plugin* class, not a version of the `SearchProvider` class.
* `SearchProvider` does operate on Companion plugins with `uppy.getPlugin()`.
*/
export type UnknownSearchProviderPluginState = {
isInputMode?: boolean
searchTerm?: string | null
} & Pick<
UnknownProviderPluginState,
| 'loading'
| 'files'
| 'folders'
| 'currentSelection'
| 'filterInput'
| 'didFirstRender'
>
export type UnknownSearchProviderPlugin<
M extends Meta,
B extends Body,
> = UnknownPlugin<M, B, UnknownSearchProviderPluginState> & {
onFirstRender: () => void
title: string
icon: () => JSX.Element
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'>
Expand Down
9 changes: 8 additions & 1 deletion packages/@uppy/core/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
export { default } from './Uppy.ts'
export { default as Uppy, type UppyEventMap, type State } from './Uppy.ts'
export {
default as Uppy,
type UppyEventMap,
type State,
type UnknownPlugin,
type UnknownProviderPlugin,
type UnknownSearchProviderPlugin,
} from './Uppy.ts'
export { default as UIPlugin } from './UIPlugin.ts'
export { default as BasePlugin } from './BasePlugin.ts'
export { debugLogger } from './loggers.ts'
Expand Down
2 changes: 2 additions & 0 deletions packages/@uppy/utils/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@
"./lib/fileFilters": "./lib/fileFilters.js",
"./lib/VirtualList": "./lib/VirtualList.js",
"./lib/UppyFile": "./lib/UppyFile.js",
"./lib/CompanionFile": "./lib/CompanionFile.js",
"./lib/CompanionClientProvider": "./lib/CompanionClientProvider.js",
"./lib/FileProgress": "./lib/FileProgress.js",
"./src/microtip.scss": "./src/microtip.scss",
"./lib/UserFacingApiError": "./lib/UserFacingApiError.js"
Expand Down
35 changes: 35 additions & 0 deletions packages/@uppy/utils/src/CompanionClientProvider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
export type RequestOptions = {
method?: string
data?: Record<string, unknown>
skipPostResponse?: boolean
signal?: AbortSignal
authFormData?: unknown
qs?: Record<string, string>
}

/**
* CompanionClientProvider is subset of the types of the `Provider`
* class from @uppy/companion-client.
*
* This is needed as the `Provider` class is passed around in Uppy and we
* need to have shared types for it. Although we are duplicating some types,
* this is still safe as `Provider implements CompanionClientProvider`
* so any changes here will error there and vice versa.
*
* TODO: remove this once companion-client and provider-views are merged into a single plugin.
*/
export interface CompanionClientProvider {
name: string
provider: string
login(options?: RequestOptions): Promise<void>
logout<ResBody>(options?: RequestOptions): Promise<ResBody>
list<ResBody>(
directory: string | undefined,
options: RequestOptions,
): Promise<ResBody>
}
export interface CompanionClientSearchProvider {
name: string
provider: string
search<ResBody>(text: string, queries?: string): Promise<ResBody>
}
25 changes: 25 additions & 0 deletions packages/@uppy/utils/src/CompanionFile.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* CompanionFile represents a file object returned by the Companion API.
*/
export type CompanionFile = {
id: string
name: string
/*
* Url to the thumbnail icon
*/
icon: string
type: string
mimeType: string
extension: string
size: number
isFolder: boolean
modifiedDate: string
thumbnail?: string
requestPath: string
relDirPath?: string
absDirPath?: string
author?: {
name?: string
url?: string
}
}

0 comments on commit d7e577a

Please sign in to comment.