Actually check types (#1918)

* types: stronger typings

* Remove remaining `declare module` things for uppy.use

* Format types standard-style-like

* Add `target` properties to plugin typings

* Add type for `replaceTargetContent` option

* xhr-upload: allow lowercase method

* opt in to stricter typechecks

* use the strictly typed version in all typings tests

* endtoend: use strict types in typescript test

* Add some comments to the typings file so IDEs will warn about untyped use()

* informer: remove obsolete option from typings

* react: generate prop types based on actual options types

* react: update types

* react: fix import in typings test

* companion-client: add `pluginId` property to ProviderOptions type

Co-Authored-By: Ifedapo .A. Olarewaju <ifedapoolarewaju@gmail.com>

* core: remove some `any` types

* *: add locale string types

* *: generate locale typings

* core: fix LocaleStrings<> type

* dashboard: add locale string type tests

* tus: inherit options typings from tus-js-client

* transloadit: add missing options types

* ci: do the required build steps before testing typings

* Support TokenStorage in types, add `title?: string` options

* form: update typings

* types: put TokenStorage type in dependents

* Document Uppy.StrictTypes

* if we pin at least we should use the latest

* Allow document.querySelector

I think it's a eslint-plugin-compat bug that it's marking querySelector
as not available in Android Chrome 78.

Co-authored-by: Ifedapo .A. Olarewaju <ifedapoolarewaju@gmail.com>
This commit is contained in:
Renée Kooi 2020-02-12 16:22:09 +01:00 committed by GitHub
parent 68639c2bb8
commit be66c47deb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
83 changed files with 6030 additions and 5377 deletions

View file

@ -33,7 +33,8 @@
"polyfills": [
"Promise",
"fetch",
"Object.assign"
"Object.assign",
"document.querySelector"
]
},
"overrides": [{

1
.gitignore vendored
View file

@ -16,6 +16,7 @@ examples/dev/bundle.js
test/endtoend/create-react-app/build/
test/endtoend/create-react-app/coverage/
uppy-*.tgz
generatedLocale.d.ts
website/db.json
website/*.log

View file

@ -67,7 +67,8 @@ install:
- npm ci
script:
- 'if [ -n "${LINT-}" ]; then npm run lint; fi'
- 'if [ -n "${LINT-}" ]; then npm run test:type; fi'
# Need to do a bunch of work to generate the locale typings 🙃
- 'if [ -n "${LINT-}" ]; then npm run build:lib && npm run build:companion && npm run build:locale-pack && npm run test:type; fi'
- 'if [ -n "${UNIT-}" ]; then npm run test:unit; fi'
- 'if [ -n "${COMPANION_NODE6-}" ]; then nvm install 6.0.0 && nvm use 6.0.0; fi'
- 'if [ -n "${COMPANION-}" ] || [ -n "${COMPANION_NODE6-}" ]; then npm run test:companion; fi'

View file

@ -154,6 +154,26 @@ function sortObjectAlphabetically (obj, sortFunc) {
}, {})
}
function createTypeScriptLocale (plugin, pluginName) {
const allowedStringTypes = Object.keys(plugin.defaultLocale.strings)
.map(key => ` | '${key}'`)
.join('\n')
const pluginClassName = pluginName === 'core' ? 'Core' : plugin.id
const localePath = path.join(__dirname, '..', 'packages', '@uppy', pluginName, 'types', 'generatedLocale.d.ts')
const localeTypes =
'import Uppy = require(\'@uppy/core\')\n' +
'\n' +
`type ${pluginClassName}Locale = Uppy.Locale` + '<\n' +
allowedStringTypes + '\n' +
'>\n' +
'\n' +
`export = ${pluginClassName}Locale\n`
fs.writeFileSync(localePath, localeTypes)
}
function build () {
const { plugins, sources } = buildPluginsList()
@ -161,6 +181,10 @@ function build () {
addLocaleToPack(plugins[pluginName], pluginName)
}
for (const pluginName in plugins) {
createTypeScriptLocale(plugins[pluginName], pluginName)
}
localePack = sortObjectAlphabetically(localePack)
for (const pluginName in sources) {

9064
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -69,69 +69,69 @@
"uppy.io": "file:website"
},
"devDependencies": {
"@babel/cli": "7.7.5",
"@babel/core": "7.7.5",
"@babel/plugin-proposal-class-properties": "7.7.4",
"@babel/plugin-transform-object-assign": "7.7.4",
"@babel/plugin-transform-proto-to-assign": "7.7.4",
"@babel/plugin-transform-react-jsx": "7.7.4",
"@babel/polyfill": "7.4.4",
"@babel/preset-env": "7.7.6",
"@babel/register": "7.7.4",
"@babel/cli": "7.8.4",
"@babel/core": "7.8.4",
"@babel/plugin-proposal-class-properties": "7.8.3",
"@babel/plugin-transform-object-assign": "7.8.3",
"@babel/plugin-transform-proto-to-assign": "7.8.3",
"@babel/plugin-transform-react-jsx": "7.8.3",
"@babel/polyfill": "7.8.3",
"@babel/preset-env": "7.8.4",
"@babel/register": "7.8.3",
"@jamen/lorem": "0.2.0",
"@lerna/run": "3.20.0",
"@octokit/rest": "16.25.0",
"@size-limit/preset-big-lib": "2.2.2",
"@types/aws-serverless-express": "3.0.1",
"@octokit/rest": "16.43.1",
"@size-limit/preset-big-lib": "2.2.4",
"@types/aws-serverless-express": "3.3.3",
"@types/compression": "0.0.36",
"@types/connect-redis": "0.0.7",
"@types/cookie-parser": "1.4.1",
"@types/cors": "2.8.3",
"@types/express-session": "1.15.6",
"@types/cookie-parser": "1.4.2",
"@types/cors": "2.8.6",
"@types/express-session": "1.15.16",
"@types/helmet": "0.0.37",
"@types/jsonwebtoken": "7.2.5",
"@types/lodash.merge": "4.6.3",
"@types/morgan": "1.7.35",
"@types/ms": "0.7.30",
"@types/node": "12.12.17",
"@types/react": "16.9.16",
"@types/request": "2.0.9",
"@types/jsonwebtoken": "7.2.8",
"@types/lodash.merge": "4.6.6",
"@types/morgan": "1.7.37",
"@types/ms": "0.7.31",
"@types/node": "12.12.27",
"@types/react": "16.9.19",
"@types/request": "2.48.4",
"@types/tus-js-client": "1.8.0",
"@types/uuid": "3.4.3",
"@types/uuid": "3.4.7",
"@types/ws": "3.2.1",
"@wdio/cli": "5.16.15",
"@wdio/local-runner": "5.16.15",
"@wdio/mocha-framework": "5.16.15",
"@wdio/cli": "5.18.6",
"@wdio/local-runner": "5.18.6",
"@wdio/mocha-framework": "5.18.6",
"@wdio/sauce-service": "5.16.10",
"adm-zip": "0.4.14",
"aliasify": "2.1.0",
"autoprefixer": "9.7.3",
"autoprefixer": "9.7.4",
"babel-eslint": "10.0.3",
"babel-jest": "24.9.0",
"babel-plugin-inline-package-json": "2.0.0",
"babelify": "10.0.0",
"brake": "1.0.1",
"browser-resolve": "1.11.3",
"browser-sync": "2.26.5",
"browserify": "16.2.3",
"browser-sync": "2.26.7",
"browserify": "16.5.0",
"chai": "4.2.0",
"chalk": "2.4.2",
"cssnano": "4.1.10",
"disc": "1.3.3",
"envify": "4.1.0",
"enzyme": "3.9.0",
"enzyme-adapter-react-16": "1.11.2",
"es6-promise": "4.2.5",
"eslint": "6.7.2",
"enzyme": "3.11.0",
"enzyme-adapter-react-16": "1.15.2",
"es6-promise": "4.2.8",
"eslint": "6.8.0",
"eslint-config-standard": "14.1.0",
"eslint-config-standard-jsx": "8.1.0",
"eslint-plugin-compat": "3.3.0",
"eslint-plugin-import": "2.19.1",
"eslint-plugin-jest": "22.17.0",
"eslint-plugin-jsdoc": "15.5.3",
"eslint-plugin-compat": "3.5.1",
"eslint-plugin-import": "2.20.1",
"eslint-plugin-jest": "22.21.0",
"eslint-plugin-jsdoc": "15.12.2",
"eslint-plugin-node": "10.0.0",
"eslint-plugin-promise": "4.2.1",
"eslint-plugin-react": "7.17.0",
"eslint-plugin-react": "7.18.3",
"eslint-plugin-standard": "4.0.1",
"events.once": "2.0.2",
"exorcist": "1.0.1",
@ -139,51 +139,52 @@
"fakefile": "0.0.9",
"flat": "4.1.0",
"github-contributors-list": "1.2.4",
"glob": "7.1.3",
"glob": "7.1.6",
"globby": "9.2.0",
"gzip-size": "5.0.0",
"gzip-size": "5.1.1",
"http-proxy": "1.18.0",
"isomorphic-fetch": "2.2.1",
"jest": "24.9.0",
"json3": "3.3.2",
"json3": "3.3.3",
"last-commit-message": "1.0.0",
"lerna": "3.17.0",
"lerna": "3.20.2",
"lint-staged": "9.5.0",
"mime-types": "2.1.24",
"minify-stream": "1.2.0",
"mime-types": "2.1.26",
"minify-stream": "1.2.1",
"mkdirp": "0.5.1",
"multi-glob": "1.0.2",
"namespace-emitter": "2.0.1",
"nock": "9.6.1",
"node-sass": "4.13.1",
"nodemon": "1.17.5",
"nodemon": "1.19.4",
"npm-auth-to-token": "1.0.0",
"npm-packlist": "1.4.7",
"npm-packlist": "1.4.8",
"npm-run-all": "4.1.5",
"onchange": "4.1.0",
"pacote": "9.5.11",
"postcss": "7.0.24",
"postcss-safe-important": "1.1.0",
"pacote": "9.5.12",
"postcss": "7.0.26",
"postcss-safe-important": "1.2.0",
"pre-commit": "1.2.2",
"pretty-bytes": "5.1.0",
"react": "16.8.6",
"react-dom": "16.8.6",
"redux": "4.0.1",
"replace-x": "1.5.0",
"rimraf": "2.6.3",
"pretty-bytes": "5.3.0",
"react": "16.12.0",
"react-dom": "16.12.0",
"redux": "4.0.5",
"replace-x": "1.7.2",
"rimraf": "2.7.1",
"stringify-object": "3.3.0",
"supertest": "3.0.0",
"tar": "4.4.8",
"supertest": "3.4.2",
"tar": "4.4.13",
"temp-write": "3.4.0",
"tinyify": "2.5.0",
"tinyify": "2.5.2",
"touch": "3.1.0",
"tsd": "0.10.0",
"tsify": "4.0.1",
"tus-node-server": "0.3.2",
"typescript": "3.7.3",
"verdaccio": "4.2.1",
"typescript": "3.7.5",
"verdaccio": "4.4.2",
"watchify": "3.11.1",
"webdriverio": "5.16.15",
"webpack": "4.41.1",
"webdriverio": "5.18.6",
"webpack": "4.41.6",
"whatwg-fetch": "3.0.0"
},
"scripts": {
@ -219,7 +220,7 @@
"test:endtoend:registry": "verdaccio --listen 4002 --config test/endtoend/verdaccio.yaml",
"test:endtoend": "npm run test:endtoend:prepare-ci && wdio test/endtoend/wdio.remote.conf.js",
"test:locale-packs": "node ./bin/locale-packs.js test",
"test:type": "tsc -p .",
"test:type": "lerna exec --scope '@uppy/*' --ignore '@uppy/{react-native,locales,companion,provider-views,robodog}' tsd",
"test:unit": "npm run build:lib && jest",
"test:watch": "jest --watch",
"test:size": "size-limit",

View file

@ -1,34 +0,0 @@
import Uppy = require('@uppy/core');
import AwsS3Multipart = require('../');
{
const uppy = Uppy();
uppy.use(AwsS3Multipart, {
createMultipartUpload(file) {
file // $ExpectType Uppy.UppyFile
},
listParts(file, opts) {
file // $ExpectType Uppy.UppyFile
opts.uploadId // $ExpectType string
opts.key // $ExpectType string
},
prepareUploadPart(file, part) {
file // $ExpectType Uppy.UppyFile
part.uploadId // $ExpectType string
part.key // $ExpectType string
part.body // $ExpectType Blob
part.number // $ExpectType number
},
abortMultipartUpload(file, opts) {
file // $ExpectType Uppy.UppyFile
opts.uploadId // $ExpectType string
opts.key // $ExpectType string
},
completeMultipartUpload(file, opts) {
file // $ExpectType Uppy.UppyFile
opts.uploadId // $ExpectType string
opts.key // $ExpectType string
opts.parts[0] // $ExpectType AwsS3Multipart.AwsS3Part
},
});
}

View file

@ -1,32 +1,42 @@
import Uppy = require('@uppy/core');
import Uppy = require('@uppy/core')
type MaybePromise<T> = T | Promise<T>
declare module AwsS3Multipart {
interface AwsS3Part {
PartNumber?: number;
Size?: number;
ETag?: string;
PartNumber?: number
Size?: number
ETag?: string
}
interface AwsS3MultipartOptions extends Uppy.PluginOptions {
companionUrl: string;
createMultipartUpload(file: Uppy.UppyFile): Promise<{ uploadId: string, key: string }>;
listParts(file: Uppy.UppyFile, opts: { uploadId: string, key: string }): Promise<AwsS3Part[]>;
prepareUploadPart(file: Uppy.UppyFile, partData: { uploadId: string, key: string, body: Blob, number: number }): Promise<{ url: string, headers?: {[k: string]: string}}>;
abortMultipartUpload(file: Uppy.UppyFile, opts: { uploadId: string, key: string }): Promise<void>;
completeMultipartUpload(file: Uppy.UppyFile, opts: { uploadId: string, key: string, parts: AwsS3Part[] }): Promise<{ location?: string }>;
timeout: number;
limit: number;
companionUrl?: string
createMultipartUpload?: (
file: Uppy.UppyFile
) => MaybePromise<{ uploadId: string; key: string }>
listParts?: (
file: Uppy.UppyFile,
opts: { uploadId: string; key: string }
) => MaybePromise<AwsS3Part[]>
prepareUploadPart?: (
file: Uppy.UppyFile,
partData: { uploadId: string; key: string; body: Blob; number: number }
) => MaybePromise<{ url: string, headers?: { [k: string]: string } }>
abortMultipartUpload?: (
file: Uppy.UppyFile,
opts: { uploadId: string; key: string }
) => MaybePromise<void>
completeMultipartUpload?: (
file: Uppy.UppyFile,
opts: { uploadId: string; key: string; parts: AwsS3Part[] }
) => MaybePromise<{ location?: string }>
timeout?: number
limit?: number
}
}
declare class AwsS3Multipart extends Uppy.Plugin {
constructor(uppy: Uppy.Uppy, opts: Partial<AwsS3Multipart.AwsS3MultipartOptions>);
}
declare class AwsS3Multipart extends Uppy.Plugin<
AwsS3Multipart.AwsS3MultipartOptions
> {}
export = AwsS3Multipart;
declare module '@uppy/core' {
export interface Uppy {
use(pluginClass: typeof AwsS3Multipart, opts: Partial<AwsS3Multipart.AwsS3MultipartOptions>): Uppy.Uppy;
}
}
export = AwsS3Multipart

View file

@ -0,0 +1,39 @@
import { expectType } from 'tsd'
import Uppy = require('@uppy/core')
import AwsS3Multipart = require('../')
{
const uppy = Uppy<Uppy.StrictTypes>()
uppy.use(AwsS3Multipart, {
createMultipartUpload (file) {
expectType<Uppy.UppyFile>(file)
return { uploadId: '', key: '' }
},
listParts (file, opts) {
expectType<Uppy.UppyFile>(file)
expectType<string>(opts.uploadId)
expectType<string>(opts.key)
return []
},
prepareUploadPart (file, part) {
expectType<Uppy.UppyFile>(file)
expectType<string>(part.uploadId)
expectType<string>(part.key)
expectType<Blob>(part.body)
expectType<number>(part.number)
return { url: '' }
},
abortMultipartUpload (file, opts) {
expectType<Uppy.UppyFile>(file)
expectType<string>(opts.uploadId)
expectType<string>(opts.key)
},
completeMultipartUpload (file, opts) {
expectType<Uppy.UppyFile>(file)
expectType<string>(opts.uploadId)
expectType<string>(opts.key)
expectType<AwsS3Multipart.AwsS3Part>(opts.parts[0])
return {}
}
})
}

View file

@ -1,11 +0,0 @@
import Uppy = require('@uppy/core');
import AwsS3 = require('../');
{
const uppy = Uppy();
uppy.use(AwsS3, {
getUploadParameters(file) {
file // $ExpectType Uppy.UppyFile
}
});
}

View file

@ -1,29 +1,25 @@
import Uppy = require('@uppy/core');
import Uppy = require('@uppy/core')
type MaybePromise<T> = T | Promise<T>
declare module AwsS3 {
interface AwsS3UploadParameters {
method?: string;
url: string;
fields?: { [type: string]: string };
headers?: { [type: string]: string };
method?: string
url: string
fields?: { [type: string]: string }
headers?: { [type: string]: string }
}
interface AwsS3Options extends Uppy.PluginOptions {
companionUrl: string;
getUploadParameters(file: Uppy.UppyFile): Promise<AwsS3UploadParameters>;
timeout: number;
limit: number;
companionUrl?: string
getUploadParameters?: (
file: Uppy.UppyFile
) => MaybePromise<AwsS3UploadParameters>
timeout?: number
limit?: number
}
}
declare class AwsS3 extends Uppy.Plugin {
constructor(uppy: Uppy.Uppy, opts: Partial<AwsS3.AwsS3Options>);
}
declare class AwsS3 extends Uppy.Plugin<AwsS3.AwsS3Options> {}
export = AwsS3;
declare module '@uppy/core' {
export interface Uppy {
use(pluginClass: typeof AwsS3, opts: Partial<AwsS3.AwsS3Options>): Uppy.Uppy;
}
}
export = AwsS3

View file

@ -0,0 +1,13 @@
import { expectType } from 'tsd'
import Uppy = require('@uppy/core')
import AwsS3 = require('../')
{
const uppy = Uppy<Uppy.StrictTypes>()
uppy.use(AwsS3, {
getUploadParameters (file) {
expectType<Uppy.UppyFile>(file)
return { url: '' }
}
})
}

View file

@ -1,48 +1,70 @@
/**
* Async storage interface, similar to `localStorage`. This can be used to
* implement custom storages for authentication tokens.
*/
export interface TokenStorage {
setItem: (key: string, value: string) => Promise<void>
getItem: (key: string) => Promise<string>
removeItem: (key: string) => Promise<void>
}
export interface RequestClientOptions {
companionUrl: string;
companionHeaders?: object;
companionUrl: string
companionHeaders?: object
/**
* Deprecated, use `companionHeaders` instead.
*/
serverHeaders?: object;
serverHeaders?: object
}
export class RequestClient {
constructor (uppy: any, opts: RequestClientOptions);
get (path: string): Promise<any>;
post (path: string, data: object): Promise<any>;
delete (path: string, data: object): Promise<any>;
constructor (uppy: any, opts: RequestClientOptions)
get (path: string): Promise<any>
post (path: string, data: object): Promise<any>
delete (path: string, data: object): Promise<any>
}
export interface ProviderOptions extends RequestClientOptions {
provider: string;
authProvider?: string;
name?: string;
/**
* Options for Providers that can be passed in by Uppy users through
* Plugin constructors.
*/
export interface PublicProviderOptions extends RequestClientOptions {
companionAllowedHosts?: string | RegExp | Array<string | RegExp>
}
/**
* Options for Providers, including internal options that Plugins can set.
*/
export interface ProviderOptions extends PublicProviderOptions {
provider: string
authProvider?: string
name?: string
pluginId: string
}
export class Provider extends RequestClient {
constructor (uppy: any, opts: ProviderOptions);
checkAuth (): Promise<boolean>;
authUrl (): string;
fileUrl (id: string): string;
list (directory: string): Promise<any>;
logout (redirect?: string): Promise<any>;
static initPlugin(plugin: any, opts: object, defaultOpts?: object): void;
constructor (uppy: any, opts: ProviderOptions)
checkAuth (): Promise<boolean>
authUrl (): string
fileUrl (id: string): string
list (directory: string): Promise<any>
logout (redirect?: string): Promise<any>
static initPlugin (plugin: any, opts: object, defaultOpts?: object): void
}
export interface SocketOptions {
target: string;
autoOpen?: boolean;
target: string
autoOpen?: boolean
}
export class Socket {
isOpen: boolean;
isOpen: boolean
constructor (opts: SocketOptions);
open (): void;
close (): void;
send (action: string, payload: any): void;
on (action: string, handler: (param: any) => void): void;
once (action: string, handler: (param: any) => void): void;
emit (action: string, payload: (param: any) => void): void;
constructor (opts: SocketOptions)
open (): void
close (): void
send (action: string, payload: any): void
on (action: string, handler: (param: any) => void): void
once (action: string, handler: (param: any) => void): void
emit (action: string, payload: (param: any) => void): void
}

View file

@ -0,0 +1,2 @@
import { RequestClient, Provider, Socket } from '../'
// TODO tests

View file

@ -1,71 +0,0 @@
import Uppy = require('../')
import DefaultStore = require('@uppy/store-default')
{
const uppy = Uppy()
uppy.addFile({
data: new Blob([new ArrayBuffer(1024)], { type: 'application/octet-stream' })
})
uppy.upload().then((result) => {
result.successful[0] // $ExpectType UppyFile
result.failed[0] // $ExpectType UppyFile
})
}
{
const store = DefaultStore()
const uppy = Uppy({ store })
}
{
const uppy = Uppy()
// this doesn't exist but type checking works anyway :)
const f = uppy.getFile('virtual')
if (f && f.progress && f.progress.uploadStarted === null) {
f.progress.uploadStarted = Date.now()
}
if (f && f.response && f.response.status === 200) {
f.response.body // $ExpectType any
}
// f.response!.status === '200' // $ExpectError
}
{
type Meta = {};
type ResponseBody = {
averageColor: string
}
const uppy = Uppy()
const f = uppy.getFile<Meta, ResponseBody>('virtual')!
f.response!.body // $ExpectType ResponseBody
}
{
const uppy = Uppy()
uppy.addFile({
name: 'empty.json',
data: new Blob(['null'], { type: 'application/json' }),
meta: { path: 'path/to/file' }
})
}
{
const uppy = Uppy()
// can emit events with internal event types
uppy.emit('upload')
uppy.emit('complete', () => {})
uppy.emit('error', () => {})
// can emit events with custom event types
uppy.emit('dashboard:modal-closed', () => {})
// can register listners for internal events
uppy.on('upload', () => {})
uppy.on('complete', () => {})
uppy.on('error', () => {})
// can register listners on custom events
uppy.on('dashboard:modal-closed', () => {})
}

View file

@ -1,104 +1,139 @@
import UppyUtils = require('@uppy/utils');
import UppyUtils = require('@uppy/utils')
declare module Uppy {
// Utility types
type OmitKey<T, Key> = Pick<T, Exclude<keyof T, Key>>;
type OmitKey<T, Key> = Pick<T, Exclude<keyof T, Key>>
// These are defined in @uppy/utils instead of core so it can be used there without creating import cycles
export type UppyFile<TMeta extends IndexedObject<any> = {}, TBody extends IndexedObject<any> = {}> = UppyUtils.UppyFile<TMeta, TBody>;
export type Store = UppyUtils.Store;
export type InternalMetadata = UppyUtils.InternalMetadata;
export type UppyFile<
TMeta extends IndexedObject<any> = {},
TBody extends IndexedObject<any> = {}
> = UppyUtils.UppyFile<TMeta, TBody>
export type Store = UppyUtils.Store
export type InternalMetadata = UppyUtils.InternalMetadata
interface IndexedObject<T> {
[key: string]: T;
[key: number]: T;
[key: string]: T
[key: number]: T
}
interface UploadedUppyFile<TMeta, TBody> extends UppyFile<TMeta, TBody> {
uploadURL: string;
uploadURL: string
}
interface FailedUppyFile<TMeta, TBody> extends UppyFile<TMeta, TBody> {
error: string;
error: string
}
// Replace the `meta` property type with one that allows omitting internal metadata; addFile() will add that
type UppyFileWithoutMeta<TMeta, TBody> = OmitKey<UppyFile<TMeta, TBody>, 'meta'>;
interface AddFileOptions<TMeta = IndexedObject<any>, TBody = IndexedObject<any>> extends Partial<UppyFileWithoutMeta<TMeta, TBody>> {
type UppyFileWithoutMeta<TMeta, TBody> = OmitKey<
UppyFile<TMeta, TBody>,
'meta'
>
interface AddFileOptions<
TMeta = IndexedObject<any>,
TBody = IndexedObject<any>
> extends Partial<UppyFileWithoutMeta<TMeta, TBody>> {
// `.data` is the only required property here.
data: Blob | File;
meta?: Partial<InternalMetadata> & TMeta;
data: Blob | File
meta?: Partial<InternalMetadata> & TMeta
}
interface PluginOptions {
id?: string;
id?: string
}
interface DefaultPluginOptions extends PluginOptions {
[prop: string]: any
}
class Plugin {
id: string;
uppy: Uppy;
type: string;
constructor(uppy: Uppy, opts?: PluginOptions);
getPluginState(): object;
setPluginState(update: any): object;
update(state?: object): void;
mount(target: any, plugin: any): void;
render(state: object): void;
addTarget(plugin: any): void;
unmount(): void;
install(): void;
uninstall(): void;
type PluginTarget = string | Element | typeof Plugin
class Plugin<TOptions extends PluginOptions = DefaultPluginOptions> {
id: string
uppy: Uppy
type: string
constructor(uppy: Uppy, opts?: TOptions)
getPluginState(): object
setPluginState(update: IndexedObject<any>): object
update(state?: object): void
mount(target: PluginTarget, plugin: typeof Plugin): void
render(state: object): void
addTarget<TPlugin extends Plugin>(plugin: TPlugin): void
unmount(): void
install(): void
uninstall(): void
}
interface LocaleStrings {
[key: string]: string | LocaleStrings;
type LocaleStrings<TNames extends string> = {
[K in TNames]?: string | { [n: number]: string }
}
interface Locale {
strings: LocaleStrings;
pluralize?: (n: number) => number;
interface Locale<TNames extends string = string> {
strings: LocaleStrings<TNames>
pluralize?: (n: number) => number
}
interface Restrictions {
maxFileSize: number | null;
maxNumberOfFiles: number | null;
minNumberOfFiles: number | null;
allowedFileTypes: string[] | null;
maxFileSize?: number | null
maxNumberOfFiles?: number | null
minNumberOfFiles?: number | null
allowedFileTypes?: string[] | null
}
interface UppyOptions {
id: string;
autoProceed: boolean;
allowMultipleUploads: boolean;
debug: boolean;
restrictions: Partial<Restrictions>;
target: string | Plugin;
meta: any;
onBeforeFileAdded: (currentFile: UppyFile, files: {[key: string]: UppyFile}) => UppyFile | boolean | undefined;
onBeforeUpload: (files: {[key: string]: UppyFile}) => {[key: string]: UppyFile} | boolean;
locale: Locale;
store: Store;
interface UppyOptions<TMeta extends IndexedObject<any> = {}> {
id?: string
autoProceed?: boolean
allowMultipleUploads?: boolean
debug?: boolean
restrictions?: Restrictions
meta?: TMeta
onBeforeFileAdded?: (
currentFile: UppyFile<TMeta>,
files: { [key: string]: UppyFile<TMeta> }
) => UppyFile<TMeta> | boolean | undefined
onBeforeUpload?: (files: {
[key: string]: UppyFile<TMeta>
}) => { [key: string]: UppyFile<TMeta> } | boolean
locale?: Locale
store?: Store
}
interface UploadResult<TMeta extends IndexedObject<any> = {}, TBody extends IndexedObject<any> = {}> {
successful: UploadedUppyFile<TMeta, TBody>[];
failed: FailedUppyFile<TMeta, TBody>[];
interface UploadResult<
TMeta extends IndexedObject<any> = {},
TBody extends IndexedObject<any> = {}
> {
successful: UploadedUppyFile<TMeta, TBody>[]
failed: FailedUppyFile<TMeta, TBody>[]
}
interface State<TMeta extends IndexedObject<any> = {}, TBody extends IndexedObject<any> = {}> extends IndexedObject<any> {
capabilities?: {resumableUploads?: boolean};
currentUploads: {};
error?: string;
files: {[key: string]: UploadedUppyFile<TMeta, TBody> | FailedUppyFile<TMeta, TBody>};
interface State<
TMeta extends IndexedObject<any> = {},
TBody extends IndexedObject<any> = {}
> extends IndexedObject<any> {
capabilities?: { resumableUploads?: boolean }
currentUploads: {}
error?: string
files: {
[key: string]:
| UploadedUppyFile<TMeta, TBody>
| FailedUppyFile<TMeta, TBody>
}
info?: {
isHidden: boolean;
type: string;
message: string;
details: string;
};
plugins?: IndexedObject<any>;
totalProgress: number;
isHidden: boolean
type: string
message: string
details: string
}
plugins?: IndexedObject<any>
totalProgress: number
}
type LogLevel = 'info' | 'warning' | 'error';
type LogLevel = 'info' | 'warning' | 'error'
/** Enable the old, untyped `uppy.use()` signature. */
type LooseTypes = 'loose'
/** Disable the old, untyped `uppy.use()` signature. */
type StrictTypes = 'strict'
type TypeChecking = LooseTypes | StrictTypes
// This hack accepts _any_ string for `Event`, but also tricks VSCode and friends into providing autocompletions
// for the names listed. https://github.com/microsoft/TypeScript/issues/29729#issuecomment-505826972
@ -106,57 +141,112 @@ declare module Uppy {
type Event = LiteralUnion<'file-added' | 'file-removed' | 'upload' | 'upload-progress' | 'upload-success' | 'complete' | 'error' | 'upload-error' |
'upload-retry' | 'info-visible' | 'info-hidden' | 'cancel-all' | 'restriction-failed' | 'reset-progress'>;
class Uppy {
constructor(opts?: Partial<UppyOptions>);
on<TMeta extends IndexedObject<any> = {}>(event: 'upload-success', callback: (file: UppyFile<TMeta>, body: any, uploadURL: string) => void): Uppy;
on<TMeta extends IndexedObject<any> = {}>(event: 'complete', callback: (result: UploadResult<TMeta>) => void): Uppy;
on(event: Event, callback: (...args: any[]) => void): Uppy;
off(event: Event, callback: any): Uppy;
type UploadHandler = (fileIDs: string[]) => Promise<void>
class Uppy<TUseStrictTypes extends TypeChecking = TypeChecking> {
constructor(opts?: UppyOptions)
on<TMeta extends IndexedObject<any> = {}>(
event: 'upload-success',
callback: (file: UppyFile<TMeta>, body: any, uploadURL: string) => void
): this
on<TMeta extends IndexedObject<any> = {}>(
event: 'complete',
callback: (result: UploadResult<TMeta>) => void
): this
on(event: Event, callback: (...args: any[]) => void): this
off(event: Event, callback: (...args: any[]) => void): this
/**
* For use by plugins only!
*/
emit(event: Event, ...args: any[]): void;
updateAll(state: object): void;
setState(patch: object): void;
getState<TMeta extends IndexedObject<any> = {}>(): State<TMeta>;
readonly state: State;
setFileState(fileID: string, state: object): void;
resetProgress(): void;
addPreProcessor(fn: any): void;
removePreProcessor(fn: any): void;
addPostProcessor(fn: any): void;
removePostProcessor(fn: any): void;
addUploader(fn: any): void;
removeUploader(fn: any): void;
setMeta<TMeta extends IndexedObject<any> = {}>(data: TMeta): void;
setFileMeta<TMeta extends IndexedObject<any> = {}>(fileID: string, data: TMeta): void;
getFile<TMeta extends IndexedObject<any> = {}, TBody extends IndexedObject<any> = {}>(fileID: string): UppyFile<TMeta, TBody>;
getFiles<TMeta extends IndexedObject<any> = {}, TBody extends IndexedObject<any> = {}>(): Array<UppyFile<TMeta, TBody>>;
addFile<TMeta extends IndexedObject<any> = {}>(file: AddFileOptions<TMeta>): void;
removeFile(fileID: string): void;
pauseResume(fileID: string): boolean;
pauseAll(): void;
resumeAll(): void;
retryAll(): void;
cancelAll(): void;
retryUpload(fileID: string): any;
reset(): void;
getID(): string;
use<T extends typeof Plugin>(pluginClass: T, opts: object): Uppy;
getPlugin(name: string): Plugin;
iteratePlugins(callback: (plugin: Plugin) => void): void;
removePlugin(instance: Plugin): void;
close(): void;
info(message: string | {message: string; details: string}, type?: LogLevel, duration?: number): void;
hideInfo(): void;
log(msg: string, type?: LogLevel): void;
run(): Uppy;
restore<TMeta extends IndexedObject<any> = {}>(uploadID: string): Promise<UploadResult>;
addResultData(uploadID: string, data: object): void;
upload<TMeta extends IndexedObject<any> = {}>(): Promise<UploadResult>;
emit(event: Event, ...args: any[]): void
updateAll(state: object): void
setState(patch: object): void
getState<TMeta extends IndexedObject<any> = {}>(): State<TMeta>
readonly state: State
setFileState(fileID: string, state: object): void
resetProgress(): void
addPreProcessor(fn: UploadHandler): void
removePreProcessor(fn: UploadHandler): void
addPostProcessor(fn: UploadHandler): void
removePostProcessor(fn: UploadHandler): void
addUploader(fn: UploadHandler): void
removeUploader(fn: UploadHandler): void
setMeta<TMeta extends IndexedObject<any> = {}>(data: TMeta): void
setFileMeta<TMeta extends IndexedObject<any> = {}>(
fileID: string,
data: TMeta
): void
getFile<
TMeta extends IndexedObject<any> = {},
TBody extends IndexedObject<any> = {}
>(fileID: string): UppyFile<TMeta, TBody>
getFiles<
TMeta extends IndexedObject<any> = {},
TBody extends IndexedObject<any> = {}
>(): Array<UppyFile<TMeta, TBody>>
addFile<TMeta extends IndexedObject<any> = {}>(
file: AddFileOptions<TMeta>
): void
removeFile(fileID: string): void
pauseResume(fileID: string): boolean
pauseAll(): void
resumeAll(): void
retryAll<TMeta extends IndexedObject<any> = {}>(): Promise<UploadResult<TMeta>>
cancelAll(): void
retryUpload<TMeta extends IndexedObject<any> = {}>(fileID: string): Promise<UploadResult<TMeta>>
reset(): void
getID(): string
/**
* Add a plugin to this Uppy instance.
*/
use<TOptions, TInstance extends Plugin<TOptions>>(
pluginClass: new (uppy: this, opts: TOptions) => TInstance,
opts?: TOptions
): this
/**
* Fallback `.use()` overload with unchecked plugin options.
*
* This does not validate that the options you pass in are correct.
* We recommend disabling this overload by using the `Uppy<Uppy.StrictTypes>` type, instead of the plain `Uppy` type, to enforce strict typechecking.
* This overload will be removed in Uppy 2.0.
*/
use(pluginClass: TUseStrictTypes extends StrictTypes ? never : new (uppy: this, opts: any) => Plugin<any>, opts?: object): this
getPlugin(name: string): Plugin
iteratePlugins(callback: (plugin: Plugin) => void): void
removePlugin(instance: Plugin): void
close(): void
info(
message: string | { message: string; details: string },
type?: LogLevel,
duration?: number
): void
hideInfo(): void
log(msg: string, type?: LogLevel): void
/**
* Obsolete: do not use. This method does nothing and will be removed in a future release.
*/
run(): this
restore<TMeta extends IndexedObject<any> = {}>(
uploadID: string
): Promise<UploadResult<TMeta>>
addResultData(uploadID: string, data: object): void
upload<TMeta extends IndexedObject<any> = {}>(): Promise<UploadResult<TMeta>>
}
}
declare function Uppy(opts?: Partial<Uppy.UppyOptions>): Uppy.Uppy;
/**
* Create an uppy instance.
*
* By default, Uppy's `.use(Plugin, options)` method uses loose type checking.
* In Uppy 2.0, the `.use()` method will get a stricter type signature. You can enable strict type checking of plugin classes and their options today by using:
* ```ts
* const uppy = Uppy<Uppy.StrictTypes>()
* ```
* Make sure to also declare any variables and class properties with the `StrictTypes` parameter:
* ```ts
* private uppy: Uppy<Uppy.StrictTypes>;
* ```
*/
declare function Uppy<TUseStrictTypes extends Uppy.TypeChecking = Uppy.TypeChecking>(opts?: Uppy.UppyOptions): Uppy.Uppy<TUseStrictTypes>
export = Uppy;
export = Uppy

View file

@ -0,0 +1,91 @@
import { expectError, expectType } from 'tsd'
import Uppy = require('../')
import DefaultStore = require('@uppy/store-default')
{
const uppy = Uppy<Uppy.StrictTypes>()
uppy.addFile({
data: new Blob([new ArrayBuffer(1024)], {
type: 'application/octet-stream'
})
})
uppy.upload().then(result => {
expectType<Uppy.UploadedUppyFile<{}, {}>>(result.successful[0])
expectType<Uppy.FailedUppyFile<{}, {}>>(result.failed[0])
})
}
{
const store = DefaultStore()
const uppy = Uppy<Uppy.StrictTypes>({ store })
}
{
const uppy = Uppy<Uppy.StrictTypes>()
// this doesn't exist but type checking works anyway :)
const f = uppy.getFile('virtual')
if (f && f.progress && f.progress.uploadStarted === null) {
f.progress.uploadStarted = Date.now()
}
if (f && f.response && f.response.status === 200) {
expectType(f.response.body)
}
expectType<number>(f.response!.status)
}
{
type Meta = {}
type ResponseBody = {
averageColor: string
}
const uppy = Uppy<Uppy.StrictTypes>()
const f = uppy.getFile<Meta, ResponseBody>('virtual')!
expectType<ResponseBody>(f.response!.body)
}
{
const uppy = Uppy<Uppy.StrictTypes>()
uppy.addFile({
name: 'empty.json',
data: new Blob(['null'], { type: 'application/json' }),
meta: { path: 'path/to/file' }
})
}
{
interface SomeOptions extends Uppy.PluginOptions {
types: 'are checked'
}
class SomePlugin extends Uppy.Plugin<SomeOptions> {}
const untypedUppy = Uppy()
untypedUppy.use(SomePlugin, { types: 'are unchecked' })
const typedUppy = Uppy<Uppy.StrictTypes>()
expectError(typedUppy.use(SomePlugin, { types: 'are unchecked' }))
typedUppy.use(SomePlugin, { types: 'are checked' })
// strictly-typed instance can be cast to a loosely-typed instance
const widenUppy: Uppy.Uppy = Uppy<Uppy.StrictTypes>()
// and disables the type checking
widenUppy.use(SomePlugin, { random: 'nonsense' })
}
{
const uppy = Uppy()
// can emit events with internal event types
uppy.emit('upload')
uppy.emit('complete', () => {})
uppy.emit('error', () => {})
// can emit events with custom event types
uppy.emit('dashboard:modal-closed', () => {})
// can register listners for internal events
uppy.on('upload', () => {})
uppy.on('complete', () => {})
uppy.on('error', () => {})
// can register listners on custom events
uppy.on('dashboard:modal-closed', () => {})
}

View file

@ -1,32 +0,0 @@
import Uppy = require('@uppy/core')
import Dashboard = require('../')
{
const uppy = Uppy()
uppy.use(Dashboard, {
target: 'body'
})
const plugin = uppy.getPlugin('Dashboard') as Dashboard
plugin.openModal()
plugin.isModalOpen() // $ExpectType boolean
plugin.closeModal()
}
{
const uppy = Uppy()
uppy.use(Dashboard, <Partial<Dashboard.DashboardOptions>>{
width: '100%',
height: 700,
metaFields: [
{ id: 'caption', name: 'Caption' },
{ id: 'license', name: 'License', placeholder: 'Creative Commons, Apache 2.0, ...' },
]
})
}
{
const uppy = Uppy()
// $ExpectError
uppy.use(Dashboard, { height: {} })
}

View file

@ -1,113 +1,56 @@
import Uppy = require('@uppy/core');
import Uppy = require('@uppy/core')
import StatusBar = require('@uppy/status-bar')
import DashboardLocale = require('./generatedLocale')
interface MetaField {
id: string;
name: string;
placeholder?: string;
id: string
name: string
placeholder?: string
}
declare module Dashboard {
interface DashboardLocale {
strings: {
closeModal: string,
importFrom: string,
addingMoreFiles: string,
addMoreFiles: string,
dashboardWindowTitle: string,
dashboardTitle: string,
copyLinkToClipboardSuccess: string,
copyLinkToClipboardFallback: string,
copyLink: string,
link: string,
fileSource: string,
done: string,
back: string,
addMore: string,
removeFile: string,
editFile: string,
editing: string,
edit: string,
finishEditingFile: string,
saveChanges: string,
cancel: string,
myDevice: string,
dropPasteImport: string,
dropPaste: string,
dropHint: string,
browse: string,
uploadComplete: string,
uploadPaused: string,
resumeUpload: string,
pauseUpload: string,
retryUpload: string,
cancelUpload: string,
xFilesSelected: {
0: string,
1: string,
2: string
},
uploadingXFiles: {
0: string,
1: string,
2: string
},
processingXFiles: {
0: string,
1: string,
2: string
},
poweredBy: string
}
}
interface DashboardOptions extends Uppy.PluginOptions {
animateOpenClose: boolean;
browserBackButtonClose: boolean
closeAfterFinish: boolean;
closeModalOnClickOutside: boolean;
disableInformer: boolean;
disablePageScrollWhenModalOpen: boolean;
disableStatusBar: boolean;
disableThumbnailGenerator: boolean;
height: string | number;
hideCancelButton: boolean;
hidePauseResumeButton: boolean;
hideProgressAfterFinish: boolean;
hideRetryButton: boolean;
hideUploadButton: boolean;
inline: boolean;
locale: DashboardLocale;
metaFields: MetaField[];
note: string | null;
onRequestCloseModal: () => void;
plugins: string[];
proudlyDisplayPoweredByUppy: boolean;
showLinkToFileUploadResult: boolean;
showProgressDetails: boolean;
showSelectedFiles: boolean;
target: string;
thumbnailWidth: number;
trigger: string;
width: string | number;
animateOpenClose?: boolean
browserBackButtonClose?: boolean
closeAfterFinish?: boolean
closeModalOnClickOutside?: boolean
disableInformer?: boolean
disablePageScrollWhenModalOpen?: boolean
disableStatusBar?: boolean
disableThumbnailGenerator?: boolean
height?: string | number
hideCancelButton?: boolean
hidePauseResumeButton?: boolean
hideProgressAfterFinish?: boolean
hideRetryButton?: boolean
hideUploadButton?: boolean
inline?: boolean
locale?: DashboardLocale & StatusBar.StatusBarLocale
metaFields?: MetaField[]
note?: string | null
onRequestCloseModal?: () => void
plugins?: string[]
proudlyDisplayPoweredByUppy?: boolean
showLinkToFileUploadResult?: boolean
showProgressDetails?: boolean
showSelectedFiles?: boolean
replaceTargetContent?: boolean
target?: Uppy.PluginTarget
thumbnailWidth?: number
trigger?: string
width?: string | number
}
}
declare class Dashboard extends Uppy.Plugin {
constructor(uppy: Uppy.Uppy, opts: Partial<Dashboard.DashboardOptions>);
addTarget(plugin: Uppy.Plugin): HTMLElement;
hideAllPanels(): void;
openModal(): void;
closeModal(): void;
isModalOpen(): boolean;
render(state: object): void;
install(): void;
uninstall(): void;
declare class Dashboard extends Uppy.Plugin<Dashboard.DashboardOptions> {
addTarget (plugin: Uppy.Plugin): HTMLElement
hideAllPanels (): void
openModal (): void
closeModal (): void
isModalOpen (): boolean
render (state: object): void
install (): void
uninstall (): void
}
export = Dashboard;
declare module '@uppy/core' {
export interface Uppy {
use(pluginClass: typeof Dashboard, opts: Partial<Dashboard.DashboardOptions>): Uppy.Uppy;
}
}
export = Dashboard

View file

@ -0,0 +1,64 @@
import { expectType, expectError } from 'tsd'
import Uppy = require('@uppy/core')
import Dashboard = require('../')
{
const uppy = Uppy<Uppy.StrictTypes>()
uppy.use(Dashboard, {
target: 'body'
})
const plugin = uppy.getPlugin('Dashboard') as Dashboard
plugin.openModal()
expectType<boolean>(plugin.isModalOpen())
plugin.closeModal()
}
{
const uppy = Uppy<Uppy.StrictTypes>()
uppy.use(Dashboard, {
width: '100%',
height: 700,
metaFields: [
{ id: 'caption', name: 'Caption' },
{
id: 'license',
name: 'License',
placeholder: 'Creative Commons, Apache 2.0, ...'
}
]
})
}
{
const uppy = Uppy<Uppy.StrictTypes>()
uppy.use(Dashboard, {
locale: {
strings: {
// Dashboard string
addMoreFiles: 'yaddayadda',
// StatusBar string
uploading: '^^^^'
}
}
})
expectError(uppy.use(Dashboard, {
locale: {
strings: {
somethingThatDoesNotExist: 'wrong'
}
}
}))
const wrongType = 1234
expectError(uppy.use(Dashboard, {
locale: {
strings: {
addMoreFiles: wrongType
}
}
}))
}
{
const uppy = Uppy<Uppy.StrictTypes>()
expectError(uppy.use(Dashboard, { height: {} }))
}

View file

@ -1,23 +1,19 @@
import Uppy = require('@uppy/core');
import Uppy = require('@uppy/core')
import DragDropLocale = require('./generatedLocale')
declare module DragDrop {
interface DragDropOptions extends Uppy.PluginOptions {
inputName: string;
allowMultipleFiles: boolean;
width: string;
height: string;
note: string;
replaceTargetContent?: boolean
target?: Uppy.PluginTarget
inputName?: string
allowMultipleFiles?: boolean
width?: string
height?: string
note?: string
locale?: DragDropLocale
}
}
declare class DragDrop extends Uppy.Plugin {
constructor(uppy: Uppy.Uppy, opts: Partial<DragDrop.DragDropOptions>);
}
declare class DragDrop extends Uppy.Plugin<DragDrop.DragDropOptions> {}
export = DragDrop;
declare module '@uppy/core' {
export interface Uppy {
use(pluginClass: typeof DragDrop, opts: Partial<DragDrop.DragDropOptions>): Uppy.Uppy;
}
}
export = DragDrop

View file

@ -0,0 +1,2 @@
import DragDrop = require('../')
// TODO implement

View file

@ -1,21 +1,17 @@
import Uppy = require('@uppy/core');
import CompanionClient = require('@uppy/companion-client');
import Uppy = require('@uppy/core')
import CompanionClient = require('@uppy/companion-client')
declare module Dropbox {
interface DropboxOptions extends Uppy.PluginOptions, CompanionClient.ProviderOptions {
companionUrl: string;
companionAllowedHosts: string | RegExp | Array<string | RegExp>;
interface DropboxOptions
extends Uppy.PluginOptions,
CompanionClient.PublicProviderOptions {
replaceTargetContent?: boolean
target?: Uppy.PluginTarget
title?: string
storage?: CompanionClient.TokenStorage
}
}
declare class Dropbox extends Uppy.Plugin {
constructor(uppy: Uppy.Uppy, opts: Partial<Dropbox.DropboxOptions>);
}
declare class Dropbox extends Uppy.Plugin<Dropbox.DropboxOptions> {}
export = Dropbox;
declare module '@uppy/core' {
export interface Uppy {
use(pluginClass: typeof Dropbox, opts: Partial<Dropbox.DropboxOptions>): Uppy.Uppy;
}
}
export = Dropbox

View file

@ -0,0 +1,2 @@
import Dropbox = require('../')
// TODO implement

View file

@ -1,21 +1,17 @@
import Uppy = require('@uppy/core');
import CompanionClient = require('@uppy/companion-client');
import Uppy = require('@uppy/core')
import CompanionClient = require('@uppy/companion-client')
declare module Facebook {
interface FacebookOptions extends Uppy.PluginOptions, CompanionClient.ProviderOptions {
companionUrl: string;
companionAllowedHosts: string | RegExp | Array<string | RegExp>;
interface FacebookOptions
extends Uppy.PluginOptions,
CompanionClient.PublicProviderOptions {
replaceTargetContent?: boolean
target?: Uppy.PluginTarget
title?: string
storage?: CompanionClient.TokenStorage
}
}
declare class Facebook extends Uppy.Plugin {
constructor(uppy: Uppy.Uppy, opts: Partial<Facebook.FacebookOptions>);
}
declare class Facebook extends Uppy.Plugin<Facebook.FacebookOptions> {}
export = Facebook;
declare module '@uppy/core' {
export interface Uppy {
use(pluginClass: typeof Facebook, opts: Partial<Facebook.FacebookOptions>): Uppy.Uppy;
}
}
export = Facebook

View file

@ -0,0 +1,2 @@
import Facebook = require('../')
// TODO implement

View file

@ -1,20 +1,16 @@
import Uppy = require('@uppy/core');
import Uppy = require('@uppy/core')
import FileInputLocale = require('./generatedLocale')
declare module FileInput {
interface FileInputOptions extends Uppy.PluginOptions {
pretty: boolean;
inputName: string;
export interface FileInputOptions extends Uppy.PluginOptions {
replaceTargetContent?: boolean
target?: Uppy.PluginTarget
pretty?: boolean
inputName?: string
locale?: FileInputLocale
}
}
declare class FileInput extends Uppy.Plugin {
constructor(uppy: Uppy.Uppy, opts: Partial<FileInput.FileInputOptions>);
}
declare class FileInput extends Uppy.Plugin<FileInput.FileInputOptions> {}
export = FileInput;
declare module '@uppy/core' {
export interface Uppy {
use(pluginClass: typeof FileInput, opts: Partial<FileInput.FileInputOptions>): Uppy.Uppy;
}
}
export = FileInput

View file

@ -0,0 +1 @@
import FileInput = require('../')

View file

@ -29,7 +29,7 @@ module.exports = class Form extends Plugin {
}
// merge default options with the ones set by user
this.opts = Object.assign({}, defaultOptions, opts)
this.opts = { ...defaultOptions, ...opts }
this.handleFormSubmit = this.handleFormSubmit.bind(this)
this.handleUploadStart = this.handleUploadStart.bind(this)

View file

@ -1,23 +1,18 @@
import Uppy = require('@uppy/core');
import Uppy = require('@uppy/core')
declare module Form {
interface FormOptions extends Uppy.PluginOptions {
getMetaFromForm: boolean;
addResultToForm: boolean;
submitOnSuccess: boolean;
triggerUploadOnSubmit: boolean;
resultName: string;
replaceTargetContent?: boolean
target?: Uppy.PluginTarget
resultName?: string
getMetaFromForm?: boolean
addResultToForm?: boolean
multipleResults?: boolean
submitOnSuccess?: boolean
triggerUploadOnSubmit?: boolean
}
}
declare class Form extends Uppy.Plugin {
constructor(uppy: Uppy.Uppy, opts: Partial<Form.FormOptions>);
}
declare class Form extends Uppy.Plugin<Form.FormOptions> {}
export = Form;
declare module '@uppy/core' {
export interface Uppy {
use(pluginClass: typeof Form, opts: Partial<Form.FormOptions>): Uppy.Uppy;
}
}
export = Form

View file

@ -0,0 +1 @@
import Form = require('../')

View file

@ -1,21 +1,15 @@
import Uppy = require('@uppy/core');
import Uppy = require('@uppy/core')
declare module GoldenRetriever {
interface GoldenRetrieverOptions extends Uppy.PluginOptions {
expires: number;
serviceWorker: boolean;
indexedDB: any;
expires?: number
serviceWorker?: boolean
indexedDB?: any
}
}
declare class GoldenRetriever extends Uppy.Plugin {
constructor(uppy: Uppy.Uppy, opts: Partial<GoldenRetriever.GoldenRetrieverOptions>);
}
declare class GoldenRetriever extends Uppy.Plugin<
GoldenRetriever.GoldenRetrieverOptions
> {}
export = GoldenRetriever;
declare module '@uppy/core' {
export interface Uppy {
use(pluginClass: typeof GoldenRetriever, opts: Partial<GoldenRetriever.GoldenRetrieverOptions>): Uppy.Uppy;
}
}
export = GoldenRetriever

View file

@ -0,0 +1 @@
import GoldenRetriever = require('../')

View file

@ -1,21 +1,17 @@
import Uppy = require('@uppy/core');
import CompanionClient = require('@uppy/companion-client');
import Uppy = require('@uppy/core')
import CompanionClient = require('@uppy/companion-client')
declare module GoogleDrive {
interface GoogleDriveOptions extends Uppy.PluginOptions, CompanionClient.ProviderOptions {
companionUrl: string;
companionAllowedHosts: string | RegExp | Array<string | RegExp>;
interface GoogleDriveOptions
extends Uppy.PluginOptions,
CompanionClient.PublicProviderOptions {
replaceTargetContent?: boolean
target?: Uppy.PluginTarget
title?: string
storage?: CompanionClient.TokenStorage
}
}
declare class GoogleDrive extends Uppy.Plugin {
constructor(uppy: Uppy.Uppy, opts: Partial<GoogleDrive.GoogleDriveOptions>);
}
declare class GoogleDrive extends Uppy.Plugin<GoogleDrive.GoogleDriveOptions> {}
export = GoogleDrive;
declare module '@uppy/core' {
export interface Uppy {
use(pluginClass: typeof GoogleDrive, opts: Partial<GoogleDrive.GoogleDriveOptions>): Uppy.Uppy;
}
}
export = GoogleDrive

View file

@ -0,0 +1,9 @@
import Uppy = require('@uppy/core')
import GoogleDrive = require('../')
class SomePlugin extends Uppy.Plugin<{}> {}
const uppy = Uppy<Uppy.StrictTypes>()
uppy.use(GoogleDrive, { companionUrl: '' })
uppy.use(GoogleDrive, { target: SomePlugin, companionUrl: '' })
uppy.use(GoogleDrive, { target: document.querySelector('#gdrive')!, companionUrl: '' })

View file

@ -1,26 +1,12 @@
import Uppy = require('@uppy/core');
import Uppy = require('@uppy/core')
declare module Informer {
interface Color {
bg: string | number;
text: string | number;
}
interface InformerOptions extends Uppy.PluginOptions {
typeColors: {
[type: string]: Color
};
replaceTargetContent?: boolean
target?: Uppy.PluginTarget
}
}
declare class Informer extends Uppy.Plugin {
constructor(uppy: Uppy.Uppy, opts: Partial<Informer.InformerOptions>);
}
declare class Informer extends Uppy.Plugin<Informer.InformerOptions> {}
export = Informer;
declare module '@uppy/core' {
export interface Uppy {
use(pluginClass: typeof Informer, opts: Partial<Informer.InformerOptions>): Uppy.Uppy;
}
}
export = Informer

View file

@ -0,0 +1 @@
import Informer = require('../')

View file

@ -1,21 +1,17 @@
import Uppy = require('@uppy/core');
import CompanionClient = require('@uppy/companion-client');
import Uppy = require('@uppy/core')
import CompanionClient = require('@uppy/companion-client')
declare module Instagram {
interface InstagramOptions extends Uppy.PluginOptions, CompanionClient.ProviderOptions {
companionUrl: string;
companionAllowedHosts: string | RegExp | Array<string | RegExp>;
interface InstagramOptions
extends Uppy.PluginOptions,
CompanionClient.PublicProviderOptions {
replaceTargetContent?: boolean
target?: Uppy.PluginTarget
title?: string
storage?: CompanionClient.TokenStorage
}
}
declare class Instagram extends Uppy.Plugin {
constructor(uppy: Uppy.Uppy, opts: Partial<Instagram.InstagramOptions>);
}
declare class Instagram extends Uppy.Plugin<Instagram.InstagramOptions> {}
export = Instagram;
declare module '@uppy/core' {
export interface Uppy {
use(pluginClass: typeof Instagram, opts: Partial<Instagram.InstagramOptions>): Uppy.Uppy;
}
}
export = Instagram

View file

@ -0,0 +1,2 @@
import Instagram = require('../')
// TODO implement

View file

@ -1,21 +1,17 @@
import Uppy = require('@uppy/core');
import CompanionClient = require('@uppy/companion-client');
import Uppy = require('@uppy/core')
import CompanionClient = require('@uppy/companion-client')
declare module OneDrive {
interface OneDriveOptions extends Uppy.PluginOptions, CompanionClient.ProviderOptions {
companionUrl: string;
companionAllowedHosts: string | RegExp | Array<string | RegExp>;
interface OneDriveOptions
extends Uppy.PluginOptions,
CompanionClient.PublicProviderOptions {
replaceTargetContent?: boolean
target?: Uppy.PluginTarget
title?: string
storage?: CompanionClient.TokenStorage
}
}
declare class OneDrive extends Uppy.Plugin {
constructor(uppy: Uppy.Uppy, opts: Partial<OneDrive.OneDriveOptions>);
}
declare class OneDrive extends Uppy.Plugin<OneDrive.OneDriveOptions> {}
export = OneDrive;
declare module '@uppy/core' {
export interface Uppy {
use(pluginClass: typeof OneDrive, opts: Partial<OneDrive.OneDriveOptions>): Uppy.Uppy;
}
}
export = OneDrive

View file

@ -0,0 +1,2 @@
import OneDrive = require('../')
// TODO implement

View file

@ -1,20 +1,14 @@
import Uppy = require('@uppy/core');
import Uppy = require('@uppy/core')
declare module ProgressBar {
interface ProgressBarOptions extends Uppy.PluginOptions {
hideAfterFinish: boolean;
fixed: boolean;
replaceTargetContent?: boolean
target?: Uppy.PluginTarget
hideAfterFinish?: boolean
fixed?: boolean
}
}
declare class ProgressBar extends Uppy.Plugin {
constructor(uppy: Uppy.Uppy, opts: Partial<ProgressBar.ProgressBarOptions>);
}
declare class ProgressBar extends Uppy.Plugin<ProgressBar.ProgressBarOptions> {}
export = ProgressBar;
declare module '@uppy/core' {
export interface Uppy {
use(pluginClass: typeof ProgressBar, opts: Partial<ProgressBar.ProgressBarOptions>): Uppy.Uppy;
}
}
export = ProgressBar

View file

@ -0,0 +1,2 @@
import ProgressBar = require('../')
// TODO implement

View file

@ -1,4 +1,13 @@
import UppyCore = require('@uppy/core');
export interface Uppy extends UppyCore.Uppy {}
export interface Locale extends UppyCore.Locale {}
export type Uppy = UppyCore.Uppy
export type Locale = UppyCore.Locale
// Helper to exclude a key
export type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>
// If I use the helper it doesn't work, I think because 'target' is not a `keyof T` while
// the generic T is unknown, so will just use the expansion here
type OmitTarget<T> = Pick<T, Exclude<keyof T, 'target' | 'replaceTargetContent'>>
type WithBaseUppyProps<T> = T & { uppy: Uppy }
export type ToUppyProps<T> = WithBaseUppyProps<OmitTarget<T>>

View file

@ -1,39 +1,20 @@
import { Uppy, Locale } from './CommonTypes';
import { Omit, ToUppyProps } from './CommonTypes'
import Dashboard = require('@uppy/dashboard')
interface MetaField {
id: string;
name: string;
placeholder?: string;
}
// This type is mapped into `DashboardProps` below so IntelliSense doesn't display this big mess of nested types
type DashboardPropsInner = Omit<
ToUppyProps<Dashboard.DashboardOptions>,
// Remove the modal-only props
'animateOpenClose' | 'browserBackButtonClose' | 'inline' | 'onRequestCloseModal' | 'trigger'
>
export interface DashboardProps {
uppy: Uppy;
inline?: boolean;
plugins?: Array<string>;
trigger?: string;
width?: number;
height?: number;
showLinkToFileUploadResult?: boolean;
showProgressDetails?: boolean;
hideUploadButton?: boolean;
hideRetryButton?: boolean;
hidePauseResumeButton?: boolean;
hideCancelButton?: boolean;
hideProgressAfterFinish?: boolean;
showSelectedFiles?: boolean;
note?: string;
metaFields?: Array<MetaField>;
proudlyDisplayPoweredByUppy?: boolean;
disableStatusBar?: boolean;
disableInformer?: boolean;
disableThumbnailGenerator?: boolean;
thumbnailWidth?: number;
locale?: Locale;
export type DashboardProps = {
[K in keyof DashboardPropsInner]: DashboardPropsInner[K]
}
/**
* React Component that renders a Dashboard for an Uppy instance. This component
* renders the Dashboard inline; so you can put it anywhere you want.
* renders the Dashboard inline so you can put it anywhere you want.
*/
declare const Dashboard: React.ComponentType<DashboardProps>;
export default Dashboard;
declare const DashboardComponent: React.ComponentType<DashboardProps>
export default DashboardComponent

View file

@ -1,18 +1,13 @@
import { DashboardProps } from './Dashboard';
import { DashboardProps } from './Dashboard'
export interface DashboardModalProps extends DashboardProps {
target?: string | HTMLElement;
open?: boolean;
onRequestClose?: VoidFunction;
closeAfterFinish?: boolean;
animateOpenClose?: boolean;
closeModalOnClickOutside?: boolean;
disablePageScrollWhenModalOpen?: boolean;
open?: boolean
onRequestClose?: VoidFunction
}
/**
* React Component that renders a Dashboard for an Uppy instance in a Modal
* dialog. Visibility of the Modal is toggled using the `open` prop.
*/
declare const DashboardModal: React.ComponentType<DashboardModalProps>;
export default DashboardModal;
declare const DashboardModal: React.ComponentType<DashboardModalProps>
export default DashboardModal

View file

@ -1,13 +1,11 @@
import { Uppy, Locale } from './CommonTypes';
import { ToUppyProps } from './CommonTypes'
import DragDrop = require('@uppy/drag-drop')
export interface DragDropProps {
uppy: Uppy;
locale?: Locale;
}
export type DragDropProps = ToUppyProps<DragDrop.DragDropOptions>
/**
* React component that renders an area in which files can be dropped to be
* uploaded.
*/
declare const DragDrop: React.ComponentType<DragDropProps>;
export default DragDrop;
declare const DragDropComponent: React.ComponentType<DragDropProps>;
export default DragDropComponent;

View file

@ -1,13 +1,10 @@
import { Uppy } from './CommonTypes';
import { ToUppyProps } from './CommonTypes'
import ProgressBar = require('@uppy/progress-bar')
export interface ProgressBarProps {
uppy: Uppy;
fixed?: boolean;
hideAfterFinish?: boolean;
}
export type ProgressBarProps = ToUppyProps<ProgressBar.ProgressBarOptions>
/**
* React component that renders a progress bar at the top of the page.
*/
declare const ProgressBar: React.ComponentType<ProgressBarProps>;
export default ProgressBar;
declare const ProgressBarComponent: React.ComponentType<ProgressBarProps>
export default ProgressBarComponent

View file

@ -1,14 +1,11 @@
import { Uppy } from './CommonTypes';
import { ToUppyProps } from './CommonTypes'
import StatusBar = require('@uppy/status-bar')
export interface StatusBarProps {
uppy: Uppy;
showProgressDetails?: boolean;
hideAfterFinish?: boolean;
}
export type StatusBarProps = ToUppyProps<StatusBar.StatusBarOptions>
/**
* React component that renders a status bar containing upload progress and speed,
* processing progress and pause/resume/cancel controls.
*/
declare const StatusBar: React.ComponentType<StatusBarProps>;
export default StatusBar;
declare const StatusBarComponent: React.ComponentType<StatusBarProps>
export default StatusBarComponent

View file

@ -1,7 +1,7 @@
import * as React from 'react';
import * as React from 'react'
export { default as Dashboard } from '../src/Dashboard';
export { default as DashboardModal } from '../src/DashboardModal';
export { default as DragDrop } from '../src/DragDrop';
export { default as ProgressBar } from '../src/ProgressBar';
export { default as StatusBar } from '../src/StatusBar';
export { default as Dashboard } from '../src/Dashboard'
export { default as DashboardModal } from '../src/DashboardModal'
export { default as DragDrop } from '../src/DragDrop'
export { default as ProgressBar } from '../src/ProgressBar'
export { default as StatusBar } from '../src/StatusBar'

View file

@ -0,0 +1,20 @@
import React = require('react')
import Uppy = require('@uppy/core')
import { expectError } from 'tsd'
import * as components from '../'
const uppy = Uppy<Uppy.StrictTypes>()
function TestComponent() {
return (
<components.Dashboard
uppy={uppy}
closeAfterFinish
hideCancelButton
/>
)
}
// inline option should be removed from proptypes because it is always overridden
// by the component
expectError(<components.Dashboard inline />)

View file

@ -1,18 +1,11 @@
import Uppy = require('@uppy/core');
import Uppy = require('@uppy/core')
declare module ReduxDevTools {
interface ReduxDevToolsOptions extends Uppy.PluginOptions {
}
interface ReduxDevToolsOptions extends Uppy.PluginOptions {}
}
declare class ReduxDevTools extends Uppy.Plugin {
constructor(uppy: Uppy.Uppy, opts: Partial<ReduxDevTools.ReduxDevToolsOptions>);
}
declare class ReduxDevTools extends Uppy.Plugin<
ReduxDevTools.ReduxDevToolsOptions
> {}
export = ReduxDevTools;
declare module '@uppy/core' {
export interface Uppy {
use(pluginClass: typeof ReduxDevTools, opts: Partial<ReduxDevTools.ReduxDevToolsOptions>): Uppy.Uppy;
}
}
export = ReduxDevTools

View file

@ -0,0 +1 @@
import ReduxDevTools = require('../')

View file

@ -1,21 +1,19 @@
import Uppy = require('@uppy/core');
import Uppy = require('@uppy/core')
import GeneratedLocale = require('./generatedLocale')
declare module StatusBar {
export type StatusBarLocale = GeneratedLocale
export interface StatusBarOptions extends Uppy.PluginOptions {
showProgressDetails: boolean;
hideUploadButton: boolean;
hideAfterFinish: boolean;
replaceTargetContent?: boolean
target?: Uppy.PluginTarget
showProgressDetails?: boolean
hideUploadButton?: boolean
hideAfterFinish?: boolean
locale?: StatusBarLocale
}
}
declare class StatusBar extends Uppy.Plugin {
constructor(uppy: Uppy.Uppy, opts: Partial<StatusBar.StatusBarOptions>);
}
declare class StatusBar extends Uppy.Plugin<StatusBar.StatusBarOptions> {}
export = StatusBar;
declare module '@uppy/core' {
export interface Uppy {
use(pluginClass: typeof StatusBar, opts: Partial<StatusBar.StatusBarOptions>): Uppy.Uppy;
}
}
export = StatusBar

View file

@ -0,0 +1,2 @@
import StatusBar = require('../')
// TODO implement

View file

@ -1,11 +1,11 @@
import UppyUtils = require('@uppy/utils');
import UppyUtils = require('@uppy/utils')
declare class DefaultStore implements UppyUtils.Store {
constructor();
getState(): object;
setState(patch: object): void;
subscribe(listener: any): () => void;
constructor ()
getState (): object
setState (patch: object): void
subscribe (listener: any): () => void
}
declare function createDefaultStore(): DefaultStore;
export = createDefaultStore;
declare function createDefaultStore (): DefaultStore
export = createDefaultStore

View file

@ -0,0 +1,6 @@
import DefaultStore = require('../')
const store = DefaultStore()
store.setState({ a: 'b' })
store.getState()

View file

@ -1,6 +0,0 @@
import DefaultStore = require('../');
const store = DefaultStore();
store.setState({ a: 'b' });
store.getState();

View file

@ -1,24 +1,26 @@
import UppyUtils = require('@uppy/utils');
import { Reducer, Middleware, Store as Redux } from 'redux';
import UppyUtils = require('@uppy/utils')
import { Reducer, Middleware, Store as Redux } from 'redux'
declare namespace ReduxStore {
interface ReduxStoreOptions {
store: Redux<object>;
id?: string;
selector?: (state: any) => object;
store: Redux<object>
id?: string
selector?: (state: any) => object
}
interface ReduxStore extends UppyUtils.Store {
constructor(opts: ReduxStoreOptions): ReduxStore;
getState(): object;
setState(patch: object): void;
subscribe(listener: any): () => void;
constructor (opts: ReduxStoreOptions): ReduxStore
getState (): object
setState (patch: object): void
subscribe (listener: any): () => void
}
const reducer: Reducer<object>;
const middleware: Middleware;
const STATE_UPDATE: string;
const reducer: Reducer<object>
const middleware: Middleware
const STATE_UPDATE: string
}
declare function ReduxStore(opts: ReduxStore.ReduxStoreOptions): ReduxStore.ReduxStore;
declare function ReduxStore (
opts: ReduxStore.ReduxStoreOptions
): ReduxStore.ReduxStore
export = ReduxStore;
export = ReduxStore

View file

@ -0,0 +1,13 @@
import { createStore, combineReducers } from 'redux'
import ReduxStore = require('../')
const reducer = combineReducers({
uppy: ReduxStore.reducer
})
const store = ReduxStore({
store: createStore(reducer)
})
store.setState({ a: 1 })
store.getState()

View file

@ -1,13 +0,0 @@
import { createStore, combineReducers } from 'redux';
import ReduxStore = require('../');
const reducer = combineReducers({
uppy: ReduxStore.reducer
});
const store = ReduxStore({
store: createStore(reducer)
});
store.setState({ a: 1 });
store.getState();

View file

@ -1,19 +1,15 @@
import Uppy = require('@uppy/core');
import Uppy = require('@uppy/core')
import ThumbnailGeneratorLocale = require('./generatedLocale')
declare module ThumbnailGenerator {
interface ThumbnailGeneratorOptions extends Uppy.PluginOptions {
thumbnailWidth: number;
thumbnailWidth?: number
locale?: ThumbnailGeneratorLocale
}
}
declare class ThumbnailGenerator extends Uppy.Plugin {
constructor(uppy: Uppy.Uppy, opts: Partial<ThumbnailGenerator.ThumbnailGeneratorOptions>);
}
declare class ThumbnailGenerator extends Uppy.Plugin<
ThumbnailGenerator.ThumbnailGeneratorOptions
> {}
export = ThumbnailGenerator;
declare module '@uppy/core' {
export interface Uppy {
use(pluginClass: typeof ThumbnailGenerator, opts: Partial<ThumbnailGenerator.ThumbnailGeneratorOptions>): Uppy.Uppy;
}
}
export = ThumbnailGenerator

View file

@ -0,0 +1,2 @@
import ThumbnailGenerator = require('../')
// TODO implement

View file

@ -1,40 +1,43 @@
import Uppy = require('@uppy/core');
import Uppy = require('@uppy/core')
import TransloaditLocale = require('./generatedLocale')
declare module Transloadit {
interface AssemblyParameters {
auth: { key: string };
template_id?: string;
steps?: { [step: string]: object };
notify_url?: string;
fields?: { [name: string]: number | string };
auth: { key: string }
template_id?: string
steps?: { [step: string]: object }
notify_url?: string
fields?: { [name: string]: number | string }
}
interface AssemblyOptions {
params: AssemblyParameters;
fields?: { [name: string]: number | string };
signature?: string;
params: AssemblyParameters
fields?: { [name: string]: number | string }
signature?: string
}
interface TransloaditOptions extends Uppy.PluginOptions {
params: AssemblyParameters;
signature: string;
service: string;
waitForEncoding: boolean;
waitForMetadata: boolean;
importFromUploadURLs: boolean;
alwaysRunAssembly: boolean;
getAssemblyOptions: (file: Uppy.UppyFile) => AssemblyOptions | Promise<AssemblyOptions>;
interface TransloaditOptionsBase extends Uppy.PluginOptions {
service?: string
errorReporting?: boolean
waitForEncoding?: boolean
waitForMetadata?: boolean
importFromUploadURLs?: boolean
alwaysRunAssembly?: boolean
locale?: TransloaditLocale
limit?: number
}
// Either have a getAssemblyOptions() that returns an AssemblyOptions, *or* have them embedded in the options
type TransloaditOptions = TransloaditOptionsBase &
(
| {
getAssemblyOptions?: (
file: Uppy.UppyFile
) => AssemblyOptions | Promise<AssemblyOptions>
}
| AssemblyOptions)
}
declare class Transloadit extends Uppy.Plugin {
constructor(uppy: Uppy.Uppy, opts: Partial<Transloadit.TransloaditOptions>);
}
declare class Transloadit extends Uppy.Plugin<Transloadit.TransloaditOptions> {}
export = Transloadit;
declare module '@uppy/core' {
export interface Uppy {
use(pluginClass: typeof Transloadit, opts: Partial<Transloadit.TransloaditOptions>): Uppy.Uppy;
}
}
export = Transloadit

View file

@ -0,0 +1,63 @@
import { expectError, expectType } from 'tsd'
import Uppy = require('@uppy/core')
import Transloadit = require('../')
const validParams = {
auth: { key: 'not so secret key' }
}
{
const uppy = Uppy<Uppy.StrictTypes>()
uppy.use(Transloadit, {
getAssemblyOptions (file) {
expectType<Uppy.UppyFile>(file)
return { params: validParams }
},
waitForEncoding: false,
waitForMetadata: true,
importFromUploadURLs: false,
params: {
auth: { key: 'abc' },
steps: {}
}
})
}
{
const uppy = Uppy<Uppy.StrictTypes>()
// must be bools
expectError(
uppy.use(Transloadit, { waitForEncoding: null, params: validParams })
)
expectError(
uppy.use(Transloadit, { waitForMetadata: null, params: validParams })
)
}
{
const uppy = Uppy<Uppy.StrictTypes>()
// params.auth.key must be string
expectError(uppy.use(Transloadit, { params: {} }))
expectError(uppy.use(Transloadit, { params: { auth: {} } }))
expectError(
uppy.use(Transloadit, {
params: {
auth: { key: null }
}
})
)
expectError(
uppy.use(Transloadit, {
params: {
auth: { key: 'abc' },
steps: 'test'
}
})
)
uppy.use(Transloadit, {
params: {
auth: { key: 'abc' },
steps: { name: {} }
}
})
}

View file

@ -1,53 +0,0 @@
import Uppy = require('@uppy/core')
import Transloadit = require('../')
{
const uppy = Uppy()
uppy.use(Transloadit, {
getAssemblyOptions(file) {
file // $ExpectType Uppy.UppyFile
},
waitForEncoding: false,
waitForMetadata: true,
importFromUploadURLs: false,
params: {
auth: { key: 'abc' },
steps: {}
}
})
}
{
const uppy = Uppy()
// $ExpectError
uppy.use(Transloadit, { waitForEncoding: null })
// $ExpectError
uppy.use(Transloadit, { waitForMetadata: null })
}
{
const uppy = Uppy()
// $ExpectError
uppy.use(Transloadit, { params: {} })
// $ExpectError
uppy.use(Transloadit, { params: { auth: {} } })
// $ExpectError
uppy.use(Transloadit, {
params: {
auth: { key: null }
}
})
// $ExpectError
uppy.use(Transloadit, {
params: {
auth: { key: 'abc' },
steps: 'test'
}
})
uppy.use(Transloadit, {
params: {
auth: { key: 'abc' },
steps: { name: {} }
}
})
}

View file

@ -22,6 +22,7 @@
"url": "git+https://github.com/transloadit/uppy.git"
},
"dependencies": {
"@types/tus-js-client": "^1.8.0",
"@uppy/companion-client": "file:../companion-client",
"@uppy/utils": "file:../utils",
"tus-js-client": "^1.8.0"

View file

@ -1,29 +1,25 @@
import Uppy = require('@uppy/core');
import Uppy = require('@uppy/core')
import { UploadOptions } from 'tus-js-client'
declare module Tus {
export interface TusOptions extends Uppy.PluginOptions {
resume: boolean;
removeFingerprintOnSuccess: boolean;
endpoint: string;
headers: object;
chunkSize: number;
withCredentials: boolean;
overridePatchMethod: boolean;
retryDelays: number[];
metaFields: string[] | null;
autoRetry: boolean;
limit: number;
type TusUploadOptions = Pick<UploadOptions, Exclude<keyof UploadOptions,
| 'fingerprint'
| 'metadata'
| 'onProgress'
| 'onChunkComplete'
| 'onSuccess'
| 'onError'
| 'uploadUrl'
| 'uploadSize'
>>
export interface TusOptions extends Uppy.PluginOptions, TusUploadOptions {
metaFields?: string[] | null
autoRetry?: boolean
limit?: number
}
}
declare class Tus extends Uppy.Plugin {
constructor(uppy: Uppy.Uppy, opts: Partial<Tus.TusOptions>);
}
declare class Tus extends Uppy.Plugin<Tus.TusOptions> {}
export = Tus;
declare module '@uppy/core' {
export interface Uppy {
use(pluginClass: typeof Tus, opts: Partial<Tus.TusOptions>): Uppy.Uppy;
}
}
export = Tus

View file

@ -0,0 +1 @@
import Tus = require('../')

View file

@ -1,20 +1,18 @@
import Uppy = require('@uppy/core');
import Uppy = require('@uppy/core')
import CompanionClient = require('@uppy/companion-client')
import UrlLocale = require('./generatedLocale')
declare module Url {
export interface UrlOptions extends Uppy.PluginOptions {
companionUrl: string;
// TODO inherit from ProviderOptions
export interface UrlOptions
extends Uppy.PluginOptions,
CompanionClient.RequestClientOptions {
replaceTargetContent?: boolean
target?: Uppy.PluginTarget
title?: string
locale?: UrlLocale
}
}
declare class Url extends Uppy.Plugin {
constructor(uppy: Uppy.Uppy, opts: Partial<Url.UrlOptions>);
}
declare class Url extends Uppy.Plugin<Url.UrlOptions> {}
export = Url;
declare module '@uppy/core' {
export interface Uppy {
use(pluginClass: typeof Url, opts: Partial<Url.UrlOptions>): Uppy.Uppy;
}
}
export = Url

View file

@ -0,0 +1,2 @@
import Url = require('../')
// TODO implement

View file

@ -3,15 +3,15 @@ declare module '@uppy/utils/lib/Translator' {
export interface TranslatorOptions {
locale: {
strings: {
[key: string]: string | { [plural: number]: string };
};
pluralize: (n: number) => number;
};
[key: string]: string | { [plural: number]: string }
}
pluralize: (n: number) => number
}
}
}
class Translator {
constructor(opts: Translator.TranslatorOptions);
constructor (opts: Translator.TranslatorOptions)
}
export = Translator
@ -19,17 +19,17 @@ declare module '@uppy/utils/lib/Translator' {
declare module '@uppy/utils/lib/EventTracker' {
namespace EventTracker {
export type EventHandler = (...args: any[]) => void;
export type EventHandler = (...args: any[]) => void
export interface Emitter {
on: (event: string, handler: EventHandler) => void;
off: (event: string, handler: EventHandler) => void;
on: (event: string, handler: EventHandler) => void
off: (event: string, handler: EventHandler) => void
}
}
class EventTracker {
constructor(emitter: EventTracker.Emitter);
on(event: string, handler: EventTracker.EventHandler): void;
remove(): void;
constructor (emitter: EventTracker.Emitter)
on (event: string, handler: EventTracker.EventHandler): void
remove (): void
}
export = EventTracker
@ -37,208 +37,240 @@ declare module '@uppy/utils/lib/EventTracker' {
declare module '@uppy/utils/lib/ProgressTimeout' {
class ProgressTimeout {
constructor(timeout: number, timeoutHandler: () => void);
progress(): void;
done(): void;
constructor (timeout: number, timeoutHandler: () => void)
progress (): void
done (): void
}
export = ProgressTimeout
}
declare module '@uppy/utils/lib/RateLimitedQueue' {
namespace RateLimitedQueue {
export type AbortFunction = () => void;
export type PromiseFunction = (...args: any[]) => Promise<any>;
export type AbortFunction = () => void
export type PromiseFunction = (...args: any[]) => Promise<any>
export type QueueEntry = {
abort: () => void,
done: () => void,
};
abort: () => void
done: () => void
}
}
class RateLimitedQueue {
constructor(limit: number);
run(fn: () => RateLimitedQueue.AbortFunction): RateLimitedQueue.QueueEntry;
wrapPromiseFunction(fn: () => RateLimitedQueue.PromiseFunction): RateLimitedQueue.PromiseFunction;
constructor (limit: number)
run (fn: () => RateLimitedQueue.AbortFunction): RateLimitedQueue.QueueEntry
wrapPromiseFunction(
fn: () => RateLimitedQueue.PromiseFunction
): RateLimitedQueue.PromiseFunction
}
export = RateLimitedQueue
}
declare module '@uppy/utils/lib/canvasToBlob' {
function canvasToBlob(canvas: HTMLCanvasElement, type: string, quality?: number): Promise<Blob>;
function canvasToBlob (
canvas: HTMLCanvasElement,
type: string,
quality?: number
): Promise<Blob>
export = canvasToBlob
}
declare module '@uppy/utils/lib/dataURItoBlob' {
function dataURItoBlob(dataURI: string, opts: { mimeType?: string, name?: string }): Blob;
function dataURItoBlob (
dataURI: string,
opts: { mimeType?: string; name?: string }
): Blob
export = dataURItoBlob
}
declare module '@uppy/utils/lib/dataURItoFile' {
function dataURItoFile(dataURI: string, opts: { mimeType?: string, name?: string }): File;
function dataURItoFile (
dataURI: string,
opts: { mimeType?: string; name?: string }
): File
export = dataURItoFile
}
declare module '@uppy/utils/lib/emitSocketProgress' {
import UppyUtils = require('@uppy/utils');
import UppyUtils = require('@uppy/utils')
interface ProgressData {
progress: number;
bytesUploaded: number;
bytesTotal: number;
progress: number
bytesUploaded: number
bytesTotal: number
}
function emitSocketProgress(uploader: object, progressData: ProgressData, file: UppyUtils.UppyFile): void;
function emitSocketProgress (
uploader: object,
progressData: ProgressData,
file: UppyUtils.UppyFile
): void
export = emitSocketProgress
}
declare module '@uppy/utils/lib/findAllDOMElements' {
function findAllDOMElements(element: string | HTMLElement): HTMLElement[];
function findAllDOMElements (element: string | HTMLElement): HTMLElement[]
export = findAllDOMElements
}
declare module '@uppy/utils/lib/findDOMElement' {
function findDOMElement(element: string | HTMLElement): HTMLElement | null;
function findDOMElement (element: string | HTMLElement): HTMLElement | null
export = findDOMElement
}
declare module '@uppy/utils/lib/generateFileID' {
import UppyUtils = require('@uppy/utils');
import UppyUtils = require('@uppy/utils')
function generateFileID(file: UppyUtils.UppyFile): string;
function generateFileID (file: UppyUtils.UppyFile): string
export = generateFileID
}
declare module '@uppy/utils/lib/getBytesRemaining' {
function getBytesRemaining(progress: { bytesTotal: number, bytesUploaded: number }): number;
function getBytesRemaining (progress: {
bytesTotal: number
bytesUploaded: number
}): number
export = getBytesRemaining
}
declare module '@uppy/utils/lib/getETA' {
function getETA(progress: object): number;
function getETA (progress: object): number
export = getETA
}
declare module '@uppy/utils/lib/getFileNameAndExtension' {
function getFileNameAndExtension(filename: string): { name: string, extension: string | undefined };
function getFileNameAndExtension(
filename: string
): { name: string, extension: string | undefined };
export = getFileNameAndExtension
}
declare module '@uppy/utils/lib/getFileType' {
import UppyUtils = require('@uppy/utils');
import UppyUtils = require('@uppy/utils')
function getFileType(file: UppyUtils.UppyFile): string | null;
function getFileType (file: UppyUtils.UppyFile): string | null
export = getFileType
}
declare module '@uppy/utils/lib/getFileTypeExtension' {
function getFileTypeExtension(mime: string): string;
function getFileTypeExtension (mime: string): string
export = getFileTypeExtension
}
declare module '@uppy/utils/lib/getSocketHost' {
function getSocketHost(url: string): string;
function getSocketHost (url: string): string
export = getSocketHost
}
declare module '@uppy/utils/lib/getSpeed' {
function getSpeed(progress: { bytesTotal: number, bytesUploaded: number }): number;
function getSpeed (progress: {
bytesTotal: number
bytesUploaded: number
}): number
export = getSpeed
}
declare module '@uppy/utils/lib/getTimeStamp' {
function getTimeStamp(): string;
function getTimeStamp (): string
export = getTimeStamp
}
declare module '@uppy/utils/lib/isDOMElement' {
function isDOMElement(element: any): boolean;
function isDOMElement (element: any): boolean
export = isDOMElement
}
declare module '@uppy/utils/lib/isObjectURL' {
function isObjectURL(url: string): boolean;
function isObjectURL (url: string): boolean
export = isObjectURL
}
declare module '@uppy/utils/lib/isDragDropSupported' {
function isDragDropSupported(): boolean;
function isDragDropSupported (): boolean
export = isDragDropSupported
}
declare module '@uppy/utils/lib/isPreviewSupported' {
function isPreviewSupported(mime: string): boolean;
function isPreviewSupported (mime: string): boolean
export = isPreviewSupported
}
declare module '@uppy/utils/lib/isTouchDevice' {
function isTouchDevice(): boolean;
function isTouchDevice (): boolean
export = isTouchDevice
}
declare module '@uppy/utils/lib/prettyETA' {
function prettyETA(seconds: number): string;
function prettyETA (seconds: number): string
export = prettyETA
}
declare module '@uppy/utils/lib/secondsToTime' {
function secondsToTime(seconds: number): string;
function secondsToTime (seconds: number): string
export = secondsToTime
}
declare module '@uppy/utils/lib/settle' {
function settle<T>(promises: Promise<T>[]): Promise<{ successful: T[], failed: any[] }>;
function settle<T> (
promises: Promise<T>[]
): Promise<{ successful: T[]; failed: any[] }>
export = settle
}
declare module '@uppy/utils/lib/toArray' {
function toArray(list: any): any[];
function toArray (list: any): any[]
export = toArray
}
declare module '@uppy/utils/lib/getDroppedFiles' {
function getDroppedFiles(dataTransfer: DataTransfer, options?: object): Promise<File[]>;
function getDroppedFiles (
dataTransfer: DataTransfer,
options?: object
): Promise<File[]>
export = getDroppedFiles
}
declare module '@uppy/utils' {
interface IndexedObject<T> {
[key: string]: T;
[key: number]: T;
[key: string]: T
[key: number]: T
}
export type InternalMetadata = { name: string, type?: string };
export interface UppyFile<TMeta = IndexedObject<any>, TBody = IndexedObject<any>> {
data: Blob | File;
extension: string;
id: string;
isPaused?: boolean;
isRemote: boolean;
meta: InternalMetadata & TMeta;
name: string;
preview?: string;
export type InternalMetadata = { name: string; type?: string }
export interface UppyFile<
TMeta = IndexedObject<any>,
TBody = IndexedObject<any>
> {
data: Blob | File
extension: string
id: string
isPaused?: boolean
isRemote: boolean
meta: InternalMetadata & TMeta
name: string
preview?: string
progress?: {
uploadStarted: number | null;
uploadComplete: boolean;
percentage: number;
bytesUploaded: number;
bytesTotal: number;
};
uploadStarted: number | null
uploadComplete: boolean
percentage: number
bytesUploaded: number
bytesTotal: number
}
remote?: {
host: string;
url: string;
body?: object;
};
size: number;
source?: string;
type?: string;
host: string
url: string
body?: object
}
size: number
source?: string
type?: string
response?: {
body: TBody;
status: number;
uploadURL: string | undefined;
};
body: TBody
status: number
uploadURL: string | undefined
}
}
export interface Store {
getState(): object;
setState(patch: object): void;
subscribe(listener: any): () => void;
getState (): object
setState (patch: object): void
subscribe (listener: any): () => void
}
}

View file

@ -0,0 +1 @@
// TODO implement

View file

@ -1,25 +1,26 @@
import Uppy = require('@uppy/core');
import Uppy = require('@uppy/core')
import WebcamLocale = require('./generatedLocale')
declare module Webcam {
export type WebcamMode = 'video-audio' | 'video-only' | 'audio-only' | 'picture';
export type WebcamMode =
| 'video-audio'
| 'video-only'
| 'audio-only'
| 'picture'
export interface WebcamOptions extends Uppy.PluginOptions {
onBeforeSnapshot?: () => Promise<void>;
countdown?: number | boolean;
mirror?: boolean;
facingMode?: string;
modes: WebcamMode[];
replaceTargetContent?: boolean
target?: Uppy.PluginTarget
onBeforeSnapshot?: () => Promise<void>
countdown?: number | boolean
mirror?: boolean
facingMode?: string
modes?: WebcamMode[]
locale?: WebcamLocale
title?: string
}
}
declare class Webcam extends Uppy.Plugin {
constructor(uppy: Uppy.Uppy, opts: Partial<Webcam.WebcamOptions>);
}
declare class Webcam extends Uppy.Plugin<Webcam.WebcamOptions> {}
export = Webcam;
declare module '@uppy/core' {
export interface Uppy {
use(pluginClass: typeof Webcam, opts: Partial<Webcam.WebcamOptions>): Uppy.Uppy;
}
}
export = Webcam

View file

@ -0,0 +1,8 @@
import Uppy = require('@uppy/core')
import Webcam = require('../')
{
Uppy<Uppy.StrictTypes>().use(Webcam, {
modes: ['video-only']
})
}

View file

@ -1,8 +0,0 @@
import Uppy = require('@uppy/core');
import Webcam = require('../');
{
Uppy().use(Webcam, {
modes: ['video-only']
});
}

View file

@ -1,28 +1,22 @@
import Uppy = require('@uppy/core');
import Uppy = require('@uppy/core')
import XHRUploadLocale = require('./generatedLocale')
declare module XHRUpload {
export interface XHRUploadOptions extends Uppy.PluginOptions {
limit?: number;
bundle?: boolean;
formData?: FormData;
headers?: any;
metaFields?: string[];
fieldName?: string;
timeout?: number;
responseUrlFieldName?: string;
endpoint: string;
method?: 'GET' | 'POST' | 'PUT' | 'HEAD';
limit?: number
bundle?: boolean
formData?: boolean
headers?: any
metaFields?: string[]
fieldName?: string
timeout?: number
responseUrlFieldName?: string
endpoint: string
method?: 'GET' | 'POST' | 'PUT' | 'HEAD' | 'get' | 'post' | 'put' | 'head'
locale?: XHRUploadLocale
}
}
declare class XHRUpload extends Uppy.Plugin {
constructor(uppy: Uppy.Uppy, opts: XHRUpload.XHRUploadOptions);
}
declare class XHRUpload extends Uppy.Plugin<XHRUpload.XHRUploadOptions> {}
export = XHRUpload;
declare module '@uppy/core' {
export interface Uppy {
use(pluginClass: typeof XHRUpload, opts: XHRUpload.XHRUploadOptions): Uppy.Uppy;
}
}
export = XHRUpload

View file

@ -0,0 +1,19 @@
import Uppy = require('@uppy/core')
import XHRUpload = require('../')
Uppy<Uppy.StrictTypes>().use(XHRUpload, {
bundle: false,
formData: true,
endpoint: 'xyz'
})
function methodMayBeUpperOrLowerCase () {
Uppy<Uppy.StrictTypes>().use(XHRUpload, {
endpoint: '/upload',
method: 'post'
})
Uppy<Uppy.StrictTypes>().use(XHRUpload, {
endpoint: '/upload',
method: 'PUT'
})
}

View file

@ -1,9 +0,0 @@
import Uppy = require('@uppy/core');
import XHRUpload = require('../');
{
Uppy().use(XHRUpload, {
bundle: false,
endpoint: 'xyz'
} as XHRUpload.XHRUploadOptions);
}

View file

@ -16,7 +16,7 @@ import {
const isOnTravis = !!(process.env.TRAVIS && process.env.CI)
const TUS_ENDPOINT = `http://${isOnTravis ? 'companion.test' : 'localhost'}:1080/files/`
const uppy = Core({
const uppy = Core<Core.StrictTypes>({
debug: true,
meta: {
username: 'John',

View file

@ -20,9 +20,7 @@
},
"include": [
"packages/*/types/index.d.ts",
"packages/*/types/*-tests.ts",
"packages/@uppy/*/types/index.d.ts",
"packages/@uppy/*/types/*-tests.ts"
"packages/@uppy/*/types/index.d.ts"
],
"exclude": [
"packages/@uppy/companion"

View file

@ -30,6 +30,39 @@ In the [CDN package](/docs/#With-a-script-tag), it is available on the `Uppy` gl
const Core = Uppy.Core
```
## TypeScript
When using TypeScript, Uppy has weak type checking by default. That means that the options to plugins are not type-checked. For example, this is allowed:
```ts
import Uppy = require('@uppy/core')
import Tus = require('@uppy/tus')
const uppy = Uppy()
uppy.use(Tus, {
invalidOption: null,
endpoint: ['a', 'wrong', 'type']
})
```
As of Uppy 1.10, Uppy supports a strict typechecking mode. This mode typechecks the options passed in to plugins. This will be the only mode in Uppy 2.0, but is currently optional to preserve backwards compatibility. The strict mode can be enabled by passing a special generic type parameter to the Uppy constructor:
```ts
import Uppy = require('@uppy/core')
import Tus = require('@uppy/tus')
const uppy = Uppy<Uppy.StrictTypes>()
uppy.use(Tus, {
invalidOption: null // this will now make the compilation fail!
})
```
If you are storing Uppy instances in your code, for example in a property on a React or Angular component class, make sure to add the `StrictTypes` flag there as well:
```ts
class MyComponent extends React.Component {
private uppy: Uppy<Uppy.StrictTypes>
}
```
In Uppy 2.0, this generic parameter will be removed, and your plugin options will always be type-checked.
## Options
The Uppy core module has the following configurable options: