From 63478e6e52095bc3d434bf9ae9771d2e70ddace3 Mon Sep 17 00:00:00 2001 From: Murderlon Date: Mon, 25 Mar 2024 16:31:29 +0100 Subject: [PATCH 1/3] @uppy/remote-sources: migrate to TS --- packages/@uppy/remote-sources/.npmignore | 1 + packages/@uppy/remote-sources/src/index.js | 76 ------------- .../src/{index.test.js => index.test.ts} | 19 +++- packages/@uppy/remote-sources/src/index.ts | 105 ++++++++++++++++++ .../@uppy/remote-sources/tsconfig.build.json | 71 ++++++++++++ packages/@uppy/remote-sources/tsconfig.json | 67 +++++++++++ 6 files changed, 259 insertions(+), 80 deletions(-) create mode 100644 packages/@uppy/remote-sources/.npmignore delete mode 100644 packages/@uppy/remote-sources/src/index.js rename packages/@uppy/remote-sources/src/{index.test.js => index.test.ts} (61%) create mode 100644 packages/@uppy/remote-sources/src/index.ts create mode 100644 packages/@uppy/remote-sources/tsconfig.build.json create mode 100644 packages/@uppy/remote-sources/tsconfig.json diff --git a/packages/@uppy/remote-sources/.npmignore b/packages/@uppy/remote-sources/.npmignore new file mode 100644 index 0000000000..6c816673f0 --- /dev/null +++ b/packages/@uppy/remote-sources/.npmignore @@ -0,0 +1 @@ +tsconfig.* diff --git a/packages/@uppy/remote-sources/src/index.js b/packages/@uppy/remote-sources/src/index.js deleted file mode 100644 index 1a18dfea8d..0000000000 --- a/packages/@uppy/remote-sources/src/index.js +++ /dev/null @@ -1,76 +0,0 @@ -import { BasePlugin } from '@uppy/core' -import Dropbox from '@uppy/dropbox' -import GoogleDrive from '@uppy/google-drive' -import Instagram from '@uppy/instagram' -import Facebook from '@uppy/facebook' -import OneDrive from '@uppy/onedrive' -import Box from '@uppy/box' -import Unsplash from '@uppy/unsplash' -import Url from '@uppy/url' -import Zoom from '@uppy/zoom' - -import packageJson from '../package.json' - -const availablePlugins = { - // Using a null-prototype object to avoid prototype pollution. - __proto__: null, - Box, - Dropbox, - Facebook, - GoogleDrive, - Instagram, - OneDrive, - Unsplash, - Url, - Zoom, -} - -export default class RemoteSources extends BasePlugin { - static VERSION = packageJson.version - - #installedPlugins = new Set() - - constructor (uppy, opts) { - super(uppy, opts) - this.id = this.opts.id || 'RemoteSources' - this.type = 'preset' - - const defaultOptions = { - sources: Object.keys(availablePlugins), - } - this.opts = { ...defaultOptions, ...opts } - - if (this.opts.companionUrl == null) { - throw new Error('Please specify companionUrl for RemoteSources to work, see https://uppy.io/docs/remote-sources#companionUrl') - } - } - - setOptions (newOpts) { - this.uninstall() - super.setOptions(newOpts) - this.install() - } - - install () { - this.opts.sources.forEach((pluginId) => { - const optsForRemoteSourcePlugin = { ...this.opts, sources: undefined } - const plugin = availablePlugins[pluginId] - if (plugin == null) { - const pluginNames = Object.keys(availablePlugins) - const formatter = new Intl.ListFormat('en', { style: 'long', type: 'disjunction' }) - throw new Error(`Invalid plugin: "${pluginId}" is not one of: ${formatter.format(pluginNames)}.`) - } - this.uppy.use(plugin, optsForRemoteSourcePlugin) - // `plugin` is a class, but we want to track the instance object - // so we have to do `getPlugin` here. - this.#installedPlugins.add(this.uppy.getPlugin(pluginId)) - }) - } - - uninstall () { - for (const plugin of this.#installedPlugins) { - this.uppy.removePlugin(plugin) - } - this.#installedPlugins.clear() - } -} diff --git a/packages/@uppy/remote-sources/src/index.test.js b/packages/@uppy/remote-sources/src/index.test.ts similarity index 61% rename from packages/@uppy/remote-sources/src/index.test.js rename to packages/@uppy/remote-sources/src/index.test.ts index aecae499ed..b99ae2af89 100644 --- a/packages/@uppy/remote-sources/src/index.test.js +++ b/packages/@uppy/remote-sources/src/index.test.ts @@ -2,14 +2,17 @@ import { afterAll, beforeAll, describe, expect, it } from 'vitest' import resizeObserverPolyfill from 'resize-observer-polyfill' import Core from '@uppy/core' import Dashboard from '@uppy/dashboard' -import RemoteSources from './index.js' +import RemoteSources from './index.ts' describe('RemoteSources', () => { beforeAll(() => { - globalThis.ResizeObserver = resizeObserverPolyfill.default || resizeObserverPolyfill + globalThis.ResizeObserver = + // @ts-expect-error .default is fine + resizeObserverPolyfill.default || resizeObserverPolyfill }) afterAll(() => { + // @ts-expect-error delete does not have to be conditional delete globalThis.ResizeObserver }) @@ -25,8 +28,13 @@ describe('RemoteSources', () => { expect(() => { const core = new Core() core.use(Dashboard) + // @ts-expect-error companionUrl is missing core.use(RemoteSources, { sources: ['Webcam'] }) - }).toThrow(new Error('Please specify companionUrl for RemoteSources to work, see https://uppy.io/docs/remote-sources#companionUrl')) + }).toThrow( + new Error( + 'Please specify companionUrl for RemoteSources to work, see https://uppy.io/docs/remote-sources#companionUrl', + ), + ) }) it('should throw when trying to use a plugin which is not included in RemoteSources', () => { @@ -35,8 +43,11 @@ describe('RemoteSources', () => { core.use(Dashboard) core.use(RemoteSources, { companionUrl: 'https://example.com', + // @ts-expect-error test invalid sources: ['Webcam'], }) - }).toThrow('Invalid plugin: "Webcam" is not one of: Box, Dropbox, Facebook, GoogleDrive, Instagram, OneDrive, Unsplash, Url, or Zoom.') + }).toThrow( + 'Invalid plugin: "Webcam" is not one of: Box, Dropbox, Facebook, GoogleDrive, Instagram, OneDrive, Unsplash, Url, or Zoom.', + ) }) }) diff --git a/packages/@uppy/remote-sources/src/index.ts b/packages/@uppy/remote-sources/src/index.ts new file mode 100644 index 0000000000..22805bc26e --- /dev/null +++ b/packages/@uppy/remote-sources/src/index.ts @@ -0,0 +1,105 @@ +import { + BasePlugin, + Uppy, + type UIPluginOptions, + type UnknownProviderPlugin, +} from '@uppy/core' +import Dropbox from '@uppy/dropbox' +import GoogleDrive from '@uppy/google-drive' +import Instagram from '@uppy/instagram' +import Facebook from '@uppy/facebook' +import OneDrive from '@uppy/onedrive' +import Box from '@uppy/box' +import Unsplash from '@uppy/unsplash' +import Url from '@uppy/url' +import Zoom from '@uppy/zoom' + +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore We don't want TS to generate types for the package.json +import type { DefinePluginOpts } from '@uppy/core/lib/BasePlugin' +import packageJson from '../package.json' +import type { Body, Meta } from '../../utils/src/UppyFile' + +const availablePlugins = { + // Using a null-prototype object to avoid prototype pollution. + __proto__: null, + Box, + Dropbox, + Facebook, + GoogleDrive, + Instagram, + OneDrive, + Unsplash, + Url, + Zoom, +} + +export interface RemoteSourcesOptions extends UIPluginOptions { + sources?: Array> + companionUrl: string +} + +const defaultOptions = { + sources: Object.keys(availablePlugins) as Array< + keyof Omit + >, +} + +type Opts = DefinePluginOpts + +export default class RemoteSources< + M extends Meta, + B extends Body, +> extends BasePlugin { + static VERSION = packageJson.version + + #installedPlugins: Set> = new Set() + + constructor(uppy: Uppy, opts: RemoteSourcesOptions) { + super(uppy, { ...defaultOptions, ...opts }) + this.id = this.opts.id || 'RemoteSources' + this.type = 'preset' + + if (this.opts.companionUrl == null) { + throw new Error( + 'Please specify companionUrl for RemoteSources to work, see https://uppy.io/docs/remote-sources#companionUrl', + ) + } + } + + setOptions(newOpts: Partial): void { + this.uninstall() + super.setOptions(newOpts) + this.install() + } + + install(): void { + this.opts.sources.forEach((pluginId) => { + const optsForRemoteSourcePlugin = { ...this.opts, sources: undefined } + const plugin = availablePlugins[pluginId] + if (plugin == null) { + const pluginNames = Object.keys(availablePlugins) + const formatter = new Intl.ListFormat('en', { + style: 'long', + type: 'disjunction', + }) + throw new Error( + `Invalid plugin: "${pluginId}" is not one of: ${formatter.format(pluginNames)}.`, + ) + } + this.uppy.use(plugin, optsForRemoteSourcePlugin) + // `plugin` is a class, but we want to track the instance object + // so we have to do `getPlugin` here. + this.#installedPlugins.add( + this.uppy.getPlugin(pluginId) as UnknownProviderPlugin, + ) + }) + } + + uninstall(): void { + for (const plugin of this.#installedPlugins) { + this.uppy.removePlugin(plugin) + } + this.#installedPlugins.clear() + } +} diff --git a/packages/@uppy/remote-sources/tsconfig.build.json b/packages/@uppy/remote-sources/tsconfig.build.json new file mode 100644 index 0000000000..97b71eb43c --- /dev/null +++ b/packages/@uppy/remote-sources/tsconfig.build.json @@ -0,0 +1,71 @@ +{ + "extends": "../../../tsconfig.shared", + "compilerOptions": { + "noImplicitAny": false, + "outDir": "./lib", + "paths": { + "@uppy/box": ["../box/src/index.js"], + "@uppy/box/lib/*": ["../box/src/*"], + "@uppy/dashboard": ["../dashboard/src/index.js"], + "@uppy/dashboard/lib/*": ["../dashboard/src/*"], + "@uppy/dropbox": ["../dropbox/src/index.js"], + "@uppy/dropbox/lib/*": ["../dropbox/src/*"], + "@uppy/facebook": ["../facebook/src/index.js"], + "@uppy/facebook/lib/*": ["../facebook/src/*"], + "@uppy/google-drive": ["../google-drive/src/index.js"], + "@uppy/google-drive/lib/*": ["../google-drive/src/*"], + "@uppy/instagram": ["../instagram/src/index.js"], + "@uppy/instagram/lib/*": ["../instagram/src/*"], + "@uppy/onedrive": ["../onedrive/src/index.js"], + "@uppy/onedrive/lib/*": ["../onedrive/src/*"], + "@uppy/unsplash": ["../unsplash/src/index.js"], + "@uppy/unsplash/lib/*": ["../unsplash/src/*"], + "@uppy/url": ["../url/src/index.js"], + "@uppy/url/lib/*": ["../url/src/*"], + "@uppy/zoom": ["../zoom/src/index.js"], + "@uppy/zoom/lib/*": ["../zoom/src/*"], + "@uppy/core": ["../core/src/index.js"], + "@uppy/core/lib/*": ["../core/src/*"] + }, + "resolveJsonModule": false, + "rootDir": "./src", + "skipLibCheck": true + }, + "include": ["./src/**/*.*"], + "exclude": ["./src/**/*.test.ts"], + "references": [ + { + "path": "../box/tsconfig.build.json" + }, + { + "path": "../dashboard/tsconfig.build.json" + }, + { + "path": "../dropbox/tsconfig.build.json" + }, + { + "path": "../facebook/tsconfig.build.json" + }, + { + "path": "../google-drive/tsconfig.build.json" + }, + { + "path": "../instagram/tsconfig.build.json" + }, + { + "path": "../onedrive/tsconfig.build.json" + }, + { + "path": "../unsplash/tsconfig.build.json" + }, + { + "path": "../url/tsconfig.build.json" + }, + { + "path": "../zoom/tsconfig.build.json" + }, + { + "path": "../core/tsconfig.build.json" + } + ] +} diff --git a/packages/@uppy/remote-sources/tsconfig.json b/packages/@uppy/remote-sources/tsconfig.json new file mode 100644 index 0000000000..8a51722f0b --- /dev/null +++ b/packages/@uppy/remote-sources/tsconfig.json @@ -0,0 +1,67 @@ +{ + "extends": "../../../tsconfig.shared", + "compilerOptions": { + "emitDeclarationOnly": false, + "noEmit": true, + "paths": { + "@uppy/box": ["../box/src/index.js"], + "@uppy/box/lib/*": ["../box/src/*"], + "@uppy/dashboard": ["../dashboard/src/index.js"], + "@uppy/dashboard/lib/*": ["../dashboard/src/*"], + "@uppy/dropbox": ["../dropbox/src/index.js"], + "@uppy/dropbox/lib/*": ["../dropbox/src/*"], + "@uppy/facebook": ["../facebook/src/index.js"], + "@uppy/facebook/lib/*": ["../facebook/src/*"], + "@uppy/google-drive": ["../google-drive/src/index.js"], + "@uppy/google-drive/lib/*": ["../google-drive/src/*"], + "@uppy/instagram": ["../instagram/src/index.js"], + "@uppy/instagram/lib/*": ["../instagram/src/*"], + "@uppy/onedrive": ["../onedrive/src/index.js"], + "@uppy/onedrive/lib/*": ["../onedrive/src/*"], + "@uppy/unsplash": ["../unsplash/src/index.js"], + "@uppy/unsplash/lib/*": ["../unsplash/src/*"], + "@uppy/url": ["../url/src/index.js"], + "@uppy/url/lib/*": ["../url/src/*"], + "@uppy/zoom": ["../zoom/src/index.js"], + "@uppy/zoom/lib/*": ["../zoom/src/*"], + "@uppy/core": ["../core/src/index.js"], + "@uppy/core/lib/*": ["../core/src/*"], + }, + }, + "include": ["./package.json", "./src/**/*.*"], + "references": [ + { + "path": "../box/tsconfig.build.json", + }, + { + "path": "../dashboard/tsconfig.build.json", + }, + { + "path": "../dropbox/tsconfig.build.json", + }, + { + "path": "../facebook/tsconfig.build.json", + }, + { + "path": "../google-drive/tsconfig.build.json", + }, + { + "path": "../instagram/tsconfig.build.json", + }, + { + "path": "../onedrive/tsconfig.build.json", + }, + { + "path": "../unsplash/tsconfig.build.json", + }, + { + "path": "../url/tsconfig.build.json", + }, + { + "path": "../zoom/tsconfig.build.json", + }, + { + "path": "../core/tsconfig.build.json", + }, + ], +} From 8053a931e426d342deca5051ee1549af08c17bd2 Mon Sep 17 00:00:00 2001 From: Murderlon Date: Mon, 25 Mar 2024 16:38:43 +0100 Subject: [PATCH 2/3] fixup! @uppy/remote-sources: migrate to TS --- packages/@uppy/remote-sources/src/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/@uppy/remote-sources/src/index.ts b/packages/@uppy/remote-sources/src/index.ts index 22805bc26e..d5158648e0 100644 --- a/packages/@uppy/remote-sources/src/index.ts +++ b/packages/@uppy/remote-sources/src/index.ts @@ -14,11 +14,11 @@ import Unsplash from '@uppy/unsplash' import Url from '@uppy/url' import Zoom from '@uppy/zoom' +import type { DefinePluginOpts } from '@uppy/core/lib/BasePlugin' +import type { Body, Meta } from '../../utils/src/UppyFile' // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore We don't want TS to generate types for the package.json -import type { DefinePluginOpts } from '@uppy/core/lib/BasePlugin' import packageJson from '../package.json' -import type { Body, Meta } from '../../utils/src/UppyFile' const availablePlugins = { // Using a null-prototype object to avoid prototype pollution. From 45f8f6c74201d840b751b4712607eda243d5bf49 Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Tue, 26 Mar 2024 16:19:21 +0100 Subject: [PATCH 3/3] Update packages/@uppy/remote-sources/src/index.ts --- packages/@uppy/remote-sources/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@uppy/remote-sources/src/index.ts b/packages/@uppy/remote-sources/src/index.ts index d5158648e0..4b54c802c3 100644 --- a/packages/@uppy/remote-sources/src/index.ts +++ b/packages/@uppy/remote-sources/src/index.ts @@ -43,7 +43,7 @@ const defaultOptions = { sources: Object.keys(availablePlugins) as Array< keyof Omit >, -} +} satisfies Partial type Opts = DefinePluginOpts