Parcourir la source

Merge branch 'master' into feature/tl-preset

Renée Kooi il y a 6 ans
Parent
commit
9b02bc71ff

+ 2 - 0
CHANGELOG.md

@@ -75,6 +75,8 @@ PRs are welcome! Please do open an issue to discuss first if it's a big feature,
 - [ ] Consider uploading image thumbnails too #1212
 - [ ] dashboard: if you specified a delete endpoint, the “remove/cancel upload” button remains after the upload and it not only removes, but also sends a request to that endpoint #1216
 - [ ] dashboard: Show upload speed too if `showProgressDetails: true`. Maybe have separate options for which things are displayed, or at least have css-classes that can be hidden with `display: none` #766
+- [ ] react: Component wrappers to manage the Uppy instance, many people initialize it in render() which does not work correctly so this could make it easier for them https://github.com/transloadit/uppy/pull/1247#issuecomment-458063951
+- [ ] core: Fire event when a restriction fails #1251
 
 ## 1.0 Goals
 

+ 466 - 51
package-lock.json

@@ -1518,9 +1518,9 @@
 			"integrity": "sha1-yRNQTT3CgQr61VW1ma6uwsxMZ2g="
 		},
 		"@types/aws-lambda": {
-			"version": "8.10.17",
-			"resolved": "https://registry.npmjs.org/@types/aws-lambda/-/aws-lambda-8.10.17.tgz",
-			"integrity": "sha512-KV/9fMAvv5428/v4+AP4nDOfSB4sJIBOGgBtv5YbuQVaAEapL1/Bc8IyACZ48Q3hYukVFjzAdVFq94zTxyd5Yw=="
+			"version": "8.10.18",
+			"resolved": "https://registry.npmjs.org/@types/aws-lambda/-/aws-lambda-8.10.18.tgz",
+			"integrity": "sha512-ePcNYGsgBJaF00+fG92e8zDcre7K6/X7wJeEyn7ICAwez9+NS47XEYlGrA0+udxo0jSuZVC8xg//PUiGNk43pA=="
 		},
 		"@types/aws-serverless-express": {
 			"version": "3.3.0",
@@ -1589,14 +1589,14 @@
 			}
 		},
 		"@types/events": {
-			"version": "1.2.0",
-			"resolved": "https://registry.npmjs.org/@types/events/-/events-1.2.0.tgz",
-			"integrity": "sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA=="
+			"version": "3.0.0",
+			"resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz",
+			"integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g=="
 		},
 		"@types/express": {
-			"version": "4.16.0",
-			"resolved": "https://registry.npmjs.org/@types/express/-/express-4.16.0.tgz",
-			"integrity": "sha512-TtPEYumsmSTtTetAPXlJVf3kEqb6wZK0bZojpJQrnD/djV4q1oB6QQ8aKvKqwNPACoe02GNiy5zDzcYivR5Z2w==",
+			"version": "4.16.1",
+			"resolved": "https://registry.npmjs.org/@types/express/-/express-4.16.1.tgz",
+			"integrity": "sha512-V0clmJow23WeyblmACoxbHBu2JKlE5TiIme6Lem14FnPW9gsttyHtk6wq7njcdIWH1njAaFgR8gW09lgY98gQg==",
 			"requires": {
 				"@types/body-parser": "*",
 				"@types/express-serve-static-core": "*",
@@ -1604,11 +1604,10 @@
 			}
 		},
 		"@types/express-serve-static-core": {
-			"version": "4.16.0",
-			"resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.16.0.tgz",
-			"integrity": "sha512-lTeoCu5NxJU4OD9moCgm0ESZzweAx0YqsAcab6OB0EB3+As1OaHtKnaGJvcngQxYsi9UNv0abn4/DRavrRxt4w==",
+			"version": "4.16.1",
+			"resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.16.1.tgz",
+			"integrity": "sha512-QgbIMRU1EVRry5cIu1ORCQP4flSYqLM1lS5LYyGWfKnFT3E58f0gKto7BR13clBFVrVZ0G0rbLZ1hUpSkgQQOA==",
 			"requires": {
-				"@types/events": "*",
 				"@types/node": "*",
 				"@types/range-parser": "*"
 			}
@@ -2729,11 +2728,6 @@
 						"punycode": "1.3.2",
 						"querystring": "0.2.0"
 					}
-				},
-				"uuid": {
-					"version": "3.3.2",
-					"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
-					"integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA=="
 				}
 			}
 		},
@@ -6286,11 +6280,6 @@
 					"requires": {
 						"ms": "^2.1.1"
 					}
-				},
-				"ms": {
-					"version": "2.1.1",
-					"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
-					"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
 				}
 			}
 		},
@@ -7504,6 +7493,13 @@
 			"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
 			"requires": {
 				"ms": "2.0.0"
+			},
+			"dependencies": {
+				"ms": {
+					"version": "2.0.0",
+					"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+					"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+				}
 			}
 		},
 		"debuglog": {
@@ -8242,6 +8238,14 @@
 					"dev": true,
 					"requires": {
 						"ms": "2.0.0"
+					},
+					"dependencies": {
+						"ms": {
+							"version": "2.0.0",
+							"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+							"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+							"dev": true
+						}
 					}
 				},
 				"safe-buffer": {
@@ -8287,6 +8291,13 @@
 					"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
 					"requires": {
 						"ms": "2.0.0"
+					},
+					"dependencies": {
+						"ms": {
+							"version": "2.0.0",
+							"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+							"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+						}
 					}
 				},
 				"safe-buffer": {
@@ -8873,6 +8884,14 @@
 					"dev": true,
 					"requires": {
 						"ms": "2.0.0"
+					},
+					"dependencies": {
+						"ms": {
+							"version": "2.0.0",
+							"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+							"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+							"dev": true
+						}
 					}
 				},
 				"doctrine": {
@@ -10364,6 +10383,14 @@
 					"dev": true,
 					"requires": {
 						"ms": "2.0.0"
+					},
+					"dependencies": {
+						"ms": {
+							"version": "2.0.0",
+							"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+							"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+							"dev": true
+						}
 					}
 				}
 			}
@@ -12262,6 +12289,14 @@
 					"dev": true,
 					"requires": {
 						"ms": "2.0.0"
+					},
+					"dependencies": {
+						"ms": {
+							"version": "2.0.0",
+							"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+							"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+							"dev": true
+						}
 					}
 				}
 			}
@@ -12300,6 +12335,14 @@
 					"dev": true,
 					"requires": {
 						"ms": "2.0.0"
+					},
+					"dependencies": {
+						"ms": {
+							"version": "2.0.0",
+							"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+							"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+							"dev": true
+						}
 					}
 				}
 			}
@@ -14090,13 +14133,6 @@
 				"lodash.isstring": "^4.0.1",
 				"lodash.once": "^4.0.0",
 				"ms": "^2.1.1"
-			},
-			"dependencies": {
-				"ms": {
-					"version": "2.1.1",
-					"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
-					"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
-				}
 			}
 		},
 		"jsprim": {
@@ -14366,6 +14402,14 @@
 					"dev": true,
 					"requires": {
 						"ms": "2.0.0"
+					},
+					"dependencies": {
+						"ms": {
+							"version": "2.0.0",
+							"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+							"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+							"dev": true
+						}
 					}
 				},
 				"execa": {
@@ -15435,6 +15479,14 @@
 					"dev": true,
 					"requires": {
 						"ms": "2.0.0"
+					},
+					"dependencies": {
+						"ms": {
+							"version": "2.0.0",
+							"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+							"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+							"dev": true
+						}
 					}
 				},
 				"glob": {
@@ -15584,9 +15636,9 @@
 			}
 		},
 		"ms": {
-			"version": "2.0.0",
-			"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-			"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+			"version": "2.1.1",
+			"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+			"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
 		},
 		"multi-glob": {
 			"version": "1.0.2",
@@ -16587,6 +16639,11 @@
 						"to-regex": "^3.0.2"
 					}
 				},
+				"ms": {
+					"version": "2.0.0",
+					"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+					"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+				},
 				"semver": {
 					"version": "5.6.0",
 					"resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz",
@@ -20807,13 +20864,6 @@
 				"oauth-sign": "^0.8.2",
 				"qs": "^6.5.1",
 				"uuid": "^3.2.1"
-			},
-			"dependencies": {
-				"uuid": {
-					"version": "3.3.2",
-					"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
-					"integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA=="
-				}
 			}
 		},
 		"request-promise-core": {
@@ -21558,6 +21608,11 @@
 					"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
 					"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
 				},
+				"ms": {
+					"version": "2.0.0",
+					"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+					"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+				},
 				"statuses": {
 					"version": "1.4.0",
 					"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
@@ -21899,6 +21954,14 @@
 					"dev": true,
 					"requires": {
 						"ms": "2.0.0"
+					},
+					"dependencies": {
+						"ms": {
+							"version": "2.0.0",
+							"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+							"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+							"dev": true
+						}
 					}
 				}
 			}
@@ -21936,6 +21999,13 @@
 					"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
 					"requires": {
 						"ms": "2.0.0"
+					},
+					"dependencies": {
+						"ms": {
+							"version": "2.0.0",
+							"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+							"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+						}
 					}
 				}
 			}
@@ -21956,6 +22026,13 @@
 					"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
 					"requires": {
 						"ms": "2.0.0"
+					},
+					"dependencies": {
+						"ms": {
+							"version": "2.0.0",
+							"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+							"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+						}
 					}
 				}
 			}
@@ -22575,11 +22652,6 @@
 					"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
 					"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
 				},
-				"ms": {
-					"version": "2.1.1",
-					"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
-					"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
-				},
 				"process-nextick-args": {
 					"version": "2.0.0",
 					"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
@@ -23256,12 +23328,13 @@
 			}
 		},
 		"tus-js-client": {
-			"version": "1.5.2",
-			"resolved": "https://registry.npmjs.org/tus-js-client/-/tus-js-client-1.5.2.tgz",
-			"integrity": "sha512-ZhWOLNw3ZRfwS2Ud47GWxdSnXfcVUg0VEDA6feHyv0BHjsB27vl9KftJSXiiWiYRfDAb2HUo9kp1V+N6H2XgPQ==",
+			"version": "1.6.0",
+			"resolved": "https://registry.npmjs.org/tus-js-client/-/tus-js-client-1.6.0.tgz",
+			"integrity": "sha512-8y3A/pq5SKHZPJPU2LZ0KC+TNaol7TDNplprS5PEsfnjOcqHU2pJ7E6oTEXsA32tZkWHs+4JguAfXZd4XV0Jlg==",
 			"requires": {
 				"buffer-from": "^0.1.1",
 				"extend": "^3.0.0",
+				"js-base64": "^2.4.9",
 				"lodash.throttle": "^4.1.1",
 				"url-parse": "^1.4.3"
 			},
@@ -23270,6 +23343,11 @@
 					"version": "0.1.2",
 					"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-0.1.2.tgz",
 					"integrity": "sha512-RiWIenusJsmI2KcvqQABB83tLxCByE3upSP8QU3rJDMVFGPWLvPQJt/O1Su9moRWeH7d+Q2HYb68f6+v+tw2vg=="
+				},
+				"js-base64": {
+					"version": "2.5.1",
+					"resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.1.tgz",
+					"integrity": "sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw=="
 				}
 			}
 		},
@@ -23767,9 +23845,9 @@
 			"integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
 		},
 		"uuid": {
-			"version": "2.0.2",
-			"resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.2.tgz",
-			"integrity": "sha1-SL1WmPBnfjx5AaHEbvFbFkN5RyY="
+			"version": "3.3.2",
+			"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
+			"integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA=="
 		},
 		"v8flags": {
 			"version": "2.1.1",
@@ -23914,12 +23992,147 @@
 					"integrity": "sha512-sVXqklSaotK9at437sFlFpyOcJonxe0yST/AG9DkQKUdIE6IqGIMv4SfAQSKaJbSdVEJYItASCrBiVQHq1HQew==",
 					"dev": true
 				},
+				"encodeurl": {
+					"version": "1.0.2",
+					"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+					"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=",
+					"dev": true
+				},
 				"esprima": {
 					"version": "4.0.1",
 					"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
 					"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
 					"dev": true
 				},
+				"express": {
+					"version": "4.16.3",
+					"resolved": "https://registry.npmjs.org/express/-/express-4.16.3.tgz",
+					"integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=",
+					"dev": true,
+					"requires": {
+						"accepts": "~1.3.5",
+						"array-flatten": "1.1.1",
+						"body-parser": "1.18.2",
+						"content-disposition": "0.5.2",
+						"content-type": "~1.0.4",
+						"cookie": "0.3.1",
+						"cookie-signature": "1.0.6",
+						"debug": "2.6.9",
+						"depd": "~1.1.2",
+						"encodeurl": "~1.0.2",
+						"escape-html": "~1.0.3",
+						"etag": "~1.8.1",
+						"finalhandler": "1.1.1",
+						"fresh": "0.5.2",
+						"merge-descriptors": "1.0.1",
+						"methods": "~1.1.2",
+						"on-finished": "~2.3.0",
+						"parseurl": "~1.3.2",
+						"path-to-regexp": "0.1.7",
+						"proxy-addr": "~2.0.3",
+						"qs": "6.5.1",
+						"range-parser": "~1.2.0",
+						"safe-buffer": "5.1.1",
+						"send": "0.16.2",
+						"serve-static": "1.13.2",
+						"setprototypeof": "1.1.0",
+						"statuses": "~1.4.0",
+						"type-is": "~1.6.16",
+						"utils-merge": "1.0.1",
+						"vary": "~1.1.2"
+					},
+					"dependencies": {
+						"body-parser": {
+							"version": "1.18.2",
+							"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz",
+							"integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=",
+							"dev": true,
+							"requires": {
+								"bytes": "3.0.0",
+								"content-type": "~1.0.4",
+								"debug": "2.6.9",
+								"depd": "~1.1.1",
+								"http-errors": "~1.6.2",
+								"iconv-lite": "0.4.19",
+								"on-finished": "~2.3.0",
+								"qs": "6.5.1",
+								"raw-body": "2.3.2",
+								"type-is": "~1.6.15"
+							}
+						},
+						"iconv-lite": {
+							"version": "0.4.19",
+							"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz",
+							"integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==",
+							"dev": true
+						},
+						"qs": {
+							"version": "6.5.1",
+							"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz",
+							"integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==",
+							"dev": true
+						},
+						"raw-body": {
+							"version": "2.3.2",
+							"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz",
+							"integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=",
+							"dev": true,
+							"requires": {
+								"bytes": "3.0.0",
+								"http-errors": "1.6.2",
+								"iconv-lite": "0.4.19",
+								"unpipe": "1.0.0"
+							},
+							"dependencies": {
+								"depd": {
+									"version": "1.1.1",
+									"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz",
+									"integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=",
+									"dev": true
+								},
+								"http-errors": {
+									"version": "1.6.2",
+									"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz",
+									"integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=",
+									"dev": true,
+									"requires": {
+										"depd": "1.1.1",
+										"inherits": "2.0.3",
+										"setprototypeof": "1.0.3",
+										"statuses": ">= 1.3.1 < 2"
+									}
+								},
+								"setprototypeof": {
+									"version": "1.0.3",
+									"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz",
+									"integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=",
+									"dev": true
+								}
+							}
+						},
+						"safe-buffer": {
+							"version": "5.1.1",
+							"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
+							"integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==",
+							"dev": true
+						}
+					}
+				},
+				"finalhandler": {
+					"version": "1.1.1",
+					"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz",
+					"integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==",
+					"dev": true,
+					"requires": {
+						"debug": "2.6.9",
+						"encodeurl": "~1.0.2",
+						"escape-html": "~1.0.3",
+						"on-finished": "~2.3.0",
+						"parseurl": "~1.3.2",
+						"statuses": "~1.4.0",
+						"unpipe": "~1.0.0"
+					}
+				},
 				"handlebars": {
 					"version": "4.0.11",
 					"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz",
@@ -23949,6 +24162,12 @@
 						"safer-buffer": ">= 2.1.2 < 3"
 					}
 				},
+				"ipaddr.js": {
+					"version": "1.8.0",
+					"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz",
+					"integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4=",
+					"dev": true
+				},
 				"js-base64": {
 					"version": "2.4.8",
 					"resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.8.tgz",
@@ -23965,6 +24184,23 @@
 						"esprima": "^4.0.0"
 					}
 				},
+				"jsonwebtoken": {
+					"version": "8.3.0",
+					"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.3.0.tgz",
+					"integrity": "sha512-oge/hvlmeJCH+iIz1DwcO7vKPkNGJHhgkspk8OH3VKlw+mbi42WtD4ig1+VXRln765vxptAv+xT26Fd3cteqag==",
+					"dev": true,
+					"requires": {
+						"jws": "^3.1.5",
+						"lodash.includes": "^4.3.0",
+						"lodash.isboolean": "^3.0.3",
+						"lodash.isinteger": "^4.0.4",
+						"lodash.isnumber": "^3.0.3",
+						"lodash.isplainobject": "^4.0.6",
+						"lodash.isstring": "^4.0.1",
+						"lodash.once": "^4.0.0",
+						"ms": "^2.1.1"
+					}
+				},
 				"marked": {
 					"version": "0.4.0",
 					"resolved": "https://registry.npmjs.org/marked/-/marked-0.4.0.tgz",
@@ -23992,6 +24228,22 @@
 						"mime-db": "~1.37.0"
 					}
 				},
+				"ms": {
+					"version": "2.1.1",
+					"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+					"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
+					"dev": true
+				},
+				"proxy-addr": {
+					"version": "2.0.4",
+					"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz",
+					"integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==",
+					"dev": true,
+					"requires": {
+						"forwarded": "~0.1.2",
+						"ipaddr.js": "1.8.0"
+					}
+				},
 				"raw-body": {
 					"version": "2.3.3",
 					"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz",
@@ -24061,6 +24313,12 @@
 						"amdefine": ">=0.0.4"
 					}
 				},
+				"statuses": {
+					"version": "1.4.0",
+					"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
+					"integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==",
+					"dev": true
+				},
 				"type-is": {
 					"version": "1.6.16",
 					"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz",
@@ -24103,6 +24361,141 @@
 						"type-is": "~1.6.16"
 					}
 				},
+				"encodeurl": {
+					"version": "1.0.2",
+					"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+					"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=",
+					"dev": true
+				},
+				"express": {
+					"version": "4.16.3",
+					"resolved": "https://registry.npmjs.org/express/-/express-4.16.3.tgz",
+					"integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=",
+					"dev": true,
+					"requires": {
+						"accepts": "~1.3.5",
+						"array-flatten": "1.1.1",
+						"body-parser": "1.18.2",
+						"content-disposition": "0.5.2",
+						"content-type": "~1.0.4",
+						"cookie": "0.3.1",
+						"cookie-signature": "1.0.6",
+						"debug": "2.6.9",
+						"depd": "~1.1.2",
+						"encodeurl": "~1.0.2",
+						"escape-html": "~1.0.3",
+						"etag": "~1.8.1",
+						"finalhandler": "1.1.1",
+						"fresh": "0.5.2",
+						"merge-descriptors": "1.0.1",
+						"methods": "~1.1.2",
+						"on-finished": "~2.3.0",
+						"parseurl": "~1.3.2",
+						"path-to-regexp": "0.1.7",
+						"proxy-addr": "~2.0.3",
+						"qs": "6.5.1",
+						"range-parser": "~1.2.0",
+						"safe-buffer": "5.1.1",
+						"send": "0.16.2",
+						"serve-static": "1.13.2",
+						"setprototypeof": "1.1.0",
+						"statuses": "~1.4.0",
+						"type-is": "~1.6.16",
+						"utils-merge": "1.0.1",
+						"vary": "~1.1.2"
+					},
+					"dependencies": {
+						"body-parser": {
+							"version": "1.18.2",
+							"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz",
+							"integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=",
+							"dev": true,
+							"requires": {
+								"bytes": "3.0.0",
+								"content-type": "~1.0.4",
+								"debug": "2.6.9",
+								"depd": "~1.1.1",
+								"http-errors": "~1.6.2",
+								"iconv-lite": "0.4.19",
+								"on-finished": "~2.3.0",
+								"qs": "6.5.1",
+								"raw-body": "2.3.2",
+								"type-is": "~1.6.15"
+							}
+						},
+						"iconv-lite": {
+							"version": "0.4.19",
+							"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz",
+							"integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==",
+							"dev": true
+						},
+						"qs": {
+							"version": "6.5.1",
+							"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz",
+							"integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==",
+							"dev": true
+						},
+						"raw-body": {
+							"version": "2.3.2",
+							"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz",
+							"integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=",
+							"dev": true,
+							"requires": {
+								"bytes": "3.0.0",
+								"http-errors": "1.6.2",
+								"iconv-lite": "0.4.19",
+								"unpipe": "1.0.0"
+							},
+							"dependencies": {
+								"depd": {
+									"version": "1.1.1",
+									"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz",
+									"integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=",
+									"dev": true
+								},
+								"http-errors": {
+									"version": "1.6.2",
+									"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz",
+									"integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=",
+									"dev": true,
+									"requires": {
+										"depd": "1.1.1",
+										"inherits": "2.0.3",
+										"setprototypeof": "1.0.3",
+										"statuses": ">= 1.3.1 < 2"
+									}
+								},
+								"setprototypeof": {
+									"version": "1.0.3",
+									"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz",
+									"integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=",
+									"dev": true
+								}
+							}
+						},
+						"safe-buffer": {
+							"version": "5.1.1",
+							"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
+							"integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==",
+							"dev": true
+						}
+					}
+				},
+				"finalhandler": {
+					"version": "1.1.1",
+					"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz",
+					"integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==",
+					"dev": true,
+					"requires": {
+						"debug": "2.6.9",
+						"encodeurl": "~1.0.2",
+						"escape-html": "~1.0.3",
+						"on-finished": "~2.3.0",
+						"parseurl": "~1.3.2",
+						"statuses": "~1.4.0",
+						"unpipe": "~1.0.0"
+					}
+				},
 				"iconv-lite": {
 					"version": "0.4.23",
 					"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz",
@@ -24112,6 +24505,12 @@
 						"safer-buffer": ">= 2.1.2 < 3"
 					}
 				},
+				"ipaddr.js": {
+					"version": "1.8.0",
+					"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz",
+					"integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4=",
+					"dev": true
+				},
 				"mime-db": {
 					"version": "1.37.0",
 					"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz",
@@ -24127,6 +24526,16 @@
 						"mime-db": "~1.37.0"
 					}
 				},
+				"proxy-addr": {
+					"version": "2.0.4",
+					"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz",
+					"integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==",
+					"dev": true,
+					"requires": {
+						"forwarded": "~0.1.2",
+						"ipaddr.js": "1.8.0"
+					}
+				},
 				"raw-body": {
 					"version": "2.3.3",
 					"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz",
@@ -24181,6 +24590,12 @@
 					"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
 					"dev": true
 				},
+				"statuses": {
+					"version": "1.4.0",
+					"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
+					"integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==",
+					"dev": true
+				},
 				"type-is": {
 					"version": "1.6.16",
 					"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz",

+ 2 - 1
package.json

@@ -141,5 +141,6 @@
     "testMatch": [
       "**/packages/**/*.test.js"
     ]
-  }
+  },
+  "dependencies": {}
 }

+ 10 - 2
packages/@uppy/aws-s3-multipart/src/index.js

@@ -171,7 +171,11 @@ module.exports = class AwsS3Multipart extends Plugin {
           reject(err)
         },
         onSuccess: (result) => {
-          this.uppy.emit('upload-success', file, upload, result.location)
+          const uploadResp = {
+            uploadURL: result.location
+          }
+
+          this.uppy.emit('upload-success', file, uploadResp)
 
           if (result.location) {
             this.uppy.log('Download ' + upload.file.name + ' from ' + result.location)
@@ -328,7 +332,11 @@ module.exports = class AwsS3Multipart extends Plugin {
       })
 
       socket.on('success', (data) => {
-        this.uppy.emit('upload-success', file, data, data.url)
+        const uploadResp = {
+          uploadURL: data.url
+        }
+
+        this.uppy.emit('upload-success', file, uploadResp)
         resolve()
       })
     })

+ 2 - 2
packages/@uppy/aws-s3/src/index.js

@@ -70,8 +70,8 @@ module.exports = class AwsS3 extends Plugin {
       throw new Error('Expected a `serverUrl` option containing a Companion address.')
     }
 
-    const filename = encodeURIComponent(file.name)
-    const type = encodeURIComponent(file.type)
+    const filename = encodeURIComponent(file.meta.name)
+    const type = encodeURIComponent(file.meta.type)
     return this.client.get(`s3/params?filename=${filename}&type=${type}`)
       .then(assertServerError)
   }

+ 18 - 18
packages/@uppy/companion/package.json

@@ -30,34 +30,34 @@
   },
   "dependencies": {
     "@purest/providers": "1.0.0",
-    "@uppy/fs-tail-stream": "^1.2.0",
+    "@uppy/fs-tail-stream": "1.2.0",
     "atob": "2.1.0",
-    "aws-sdk": "^2.254.1",
+    "aws-sdk": "2.388.0",
     "body-parser": "1.18.2",
-    "common-tags": "^1.7.2",
-    "connect-redis": "^3.3.0",
+    "common-tags": "1.8.0",
+    "connect-redis": "3.4.0",
     "cookie-parser": "1.4.3",
-    "express": "^4.16.0",
-    "express-interceptor": "^1.2.0",
-    "express-prom-bundle": "^3.1.0",
+    "express": "4.16.3",
+    "express-interceptor": "1.2.0",
+    "express-prom-bundle": "3.3.0",
     "express-session": "1.15.6",
     "grant-express": "4.1.2",
     "helmet": "3.8.2",
     "isobject": "3.0.1",
-    "jsonwebtoken": "^8.0.1",
-    "lodash.merge": "^4.6.0",
+    "jsonwebtoken": "8.3.0",
+    "lodash.merge": "4.6.1",
     "morgan": "1.9.1",
-    "ms": "^2.0.0",
-    "node-redis-pubsub": "^2.0.0",
-    "node-schedule": "^1.3.0",
-    "prom-client": "^10.0.2",
+    "ms": "2.1.1",
+    "node-redis-pubsub": "2.0.0",
+    "node-schedule": "1.3.1",
+    "prom-client": "10.2.3",
     "purest": "3.0.0",
-    "redis": "^2.7.1",
+    "redis": "2.8.0",
     "request": "2.85.0",
-    "serialize-error": "^2.1.0",
-    "tus-js-client": "^1.5.1",
-    "uuid": "2.0.2",
-    "validator": "^9.0.0",
+    "serialize-error": "2.1.0",
+    "tus-js-client": "1.6.0",
+    "uuid": "3.3.2",
+    "validator": "9.4.1",
     "ws": "1.1.5"
   },
   "devDependencies": {

+ 1 - 1
packages/@uppy/companion/src/uppy.js

@@ -51,7 +51,7 @@ module.exports.app = (options = {}) => {
 
   // create singleton redis client
   if (options.redisUrl) {
-    redis.client({ url: options.redisUrl })
+    redis.client(merge({ url: options.redisUrl }, options.redisOptions || {}))
   }
   emitter(options.multipleInstances && options.redisUrl)
 

+ 9 - 4
packages/@uppy/core/src/index.js

@@ -697,8 +697,12 @@ class Uppy {
       this.setState({ error: error.message })
     })
 
-    this.on('upload-error', (file, error) => {
-      this.setFileState(file.id, { error: error.message })
+    this.on('upload-error', (file, error, response) => {
+      this.setFileState(file.id, {
+        error: error.message,
+        response
+      })
+
       this.setState({ error: error.message })
 
       let message = this.i18n('failedToUpload', { file: file.name })
@@ -736,7 +740,7 @@ class Uppy {
 
     this.on('upload-progress', this._calculateProgress)
 
-    this.on('upload-success', (file, uploadResp, uploadURL) => {
+    this.on('upload-success', (file, uploadResp) => {
       const currentProgress = this.getFile(file.id).progress
       this.setFileState(file.id, {
         progress: Object.assign({}, currentProgress, {
@@ -744,7 +748,8 @@ class Uppy {
           percentage: 100,
           bytesUploaded: currentProgress.bytesTotal
         }),
-        uploadURL: uploadURL,
+        response: uploadResp,
+        uploadURL: uploadResp.uploadURL,
         isPaused: false
       })
 

+ 1 - 0
packages/@uppy/dashboard/package.json

@@ -28,6 +28,7 @@
     "@uppy/thumbnail-generator": "0.29.1",
     "@uppy/utils": "0.29.1",
     "classnames": "^2.2.6",
+    "cuid": "^2.1.1",
     "drag-drop": "2.13.3",
     "lodash.throttle": "^4.1.1",
     "preact": "^8.2.9",

+ 14 - 4
packages/@uppy/dashboard/src/index.js

@@ -7,6 +7,7 @@ const Informer = require('@uppy/informer')
 const ThumbnailGenerator = require('@uppy/thumbnail-generator')
 const findAllDOMElements = require('@uppy/utils/lib/findAllDOMElements')
 const toArray = require('@uppy/utils/lib/toArray')
+const cuid = require('cuid')
 // const prettyBytes = require('prettier-bytes')
 const ResizeObserver = require('resize-observer-polyfill').default || require('resize-observer-polyfill')
 const { defaultTabIcon } = require('./components/icons')
@@ -49,7 +50,7 @@ module.exports = class Dashboard extends Plugin {
     this.id = this.opts.id || 'Dashboard'
     this.title = 'Dashboard'
     this.type = 'orchestrator'
-    this.modalName = 'uppy-Dashboard'
+    this.modalName = `uppy-Dashboard-${cuid()}`
 
     const defaultLocale = {
       strings: {
@@ -149,7 +150,7 @@ module.exports = class Dashboard extends Plugin {
     }
 
     // merge default options with the ones set by user
-    this.opts = Object.assign({}, defaultOptions, opts)
+    this.opts = { ...defaultOptions, ...opts }
 
     // i18n
     this.translator = new Translator([ defaultLocale, this.uppy.locale, this.opts.locale ])
@@ -265,7 +266,10 @@ module.exports = class Dashboard extends Plugin {
     // Ensure history state does not already contain our modal name to avoid double-pushing
     if (!history.state || !history.state[this.modalName]) {
       // Push to history so that the page is not lost on browser back button press
-      history.pushState({ [this.modalName]: true }, '')
+      history.pushState({
+        ...history.state,
+        [this.modalName]: true
+      }, '')
     }
 
     // Listen for back button presses
@@ -274,7 +278,7 @@ module.exports = class Dashboard extends Plugin {
 
   handlePopState (event) {
     // Close the modal if the history state no longer contains our modal name
-    if (!event.state || !event.state[this.modalName]) {
+    if (this.isModalOpen() && (!event.state || !event.state[this.modalName])) {
       this.closeModal({ manualClose: false })
     }
 
@@ -351,6 +355,12 @@ module.exports = class Dashboard extends Plugin {
       manualClose = true // Whether the modal is being closed by the user (`true`) or by other means (e.g. browser back button)
     } = opts
 
+    const { isHidden, isClosing } = this.getPluginState()
+    if (isHidden || isClosing) {
+      // short-circuit if animation is ongoing
+      return
+    }
+
     const { promise, resolve } = createPromise()
 
     if (this.opts.disablePageScrollWhenModalOpen) {

+ 17 - 2
packages/@uppy/react/src/Dashboard.js

@@ -11,6 +11,21 @@ const h = React.createElement
 
 class Dashboard extends React.Component {
   componentDidMount () {
+    this.installPlugin()
+  }
+
+  componentDidUpdate (prevProps) {
+    if (prevProps.uppy !== this.props.uppy) {
+      this.uninstallPlugin(prevProps)
+      this.installPlugin()
+    }
+  }
+
+  componentWillUnmount () {
+    this.uninstallPlugin()
+  }
+
+  installPlugin () {
     const uppy = this.props.uppy
     const options = Object.assign(
       { id: 'react:Dashboard' },
@@ -23,8 +38,8 @@ class Dashboard extends React.Component {
     this.plugin = uppy.getPlugin(options.id)
   }
 
-  componentWillUnmount () {
-    const uppy = this.props.uppy
+  uninstallPlugin (props = this.props) {
+    const uppy = props.uppy
 
     uppy.removePlugin(this.plugin)
   }

+ 1 - 1
packages/@uppy/react/src/DashboardModal.d.ts

@@ -1,7 +1,7 @@
 import { DashboardProps } from './Dashboard';
 
 export interface DashboardModalProps extends DashboardProps {
-  target: string | HTMLElement;
+  target?: string | HTMLElement;
   open?: boolean;
   onRequestClose?: VoidFunction;
   closeModalOnClickOutside?: boolean;

+ 17 - 2
packages/@uppy/react/src/DashboardModal.js

@@ -12,6 +12,21 @@ const h = React.createElement
 
 class DashboardModal extends React.Component {
   componentDidMount () {
+    this.installPlugin()
+  }
+
+  componentDidUpdate (prevProps) {
+    if (prevProps.uppy !== this.props.uppy) {
+      this.uninstallPlugin(prevProps)
+      this.installPlugin()
+    }
+  }
+
+  componentWillUnmount () {
+    this.uninstallPlugin()
+  }
+
+  installPlugin () {
     const uppy = this.props.uppy
     const options = Object.assign(
       { id: 'react:DashboardModal' },
@@ -34,8 +49,8 @@ class DashboardModal extends React.Component {
     }
   }
 
-  componentWillUnmount () {
-    const uppy = this.props.uppy
+  uninstallPlugin (props = this.props) {
+    const uppy = props.uppy
 
     uppy.removePlugin(this.plugin)
   }

+ 17 - 2
packages/@uppy/react/src/DragDrop.js

@@ -11,6 +11,21 @@ const h = React.createElement
 
 class DragDrop extends React.Component {
   componentDidMount () {
+    this.installPlugin()
+  }
+
+  componentDidUpdate (prevProps) {
+    if (prevProps.uppy !== this.props.uppy) {
+      this.uninstallPlugin(prevProps)
+      this.installPlugin()
+    }
+  }
+
+  componentWillUnmount () {
+    this.uninstallPlugin()
+  }
+
+  installPlugin () {
     const uppy = this.props.uppy
     const options = Object.assign(
       { id: 'react:DragDrop' },
@@ -24,8 +39,8 @@ class DragDrop extends React.Component {
     this.plugin = uppy.getPlugin(options.id)
   }
 
-  componentWillUnmount () {
-    const uppy = this.props.uppy
+  uninstallPlugin (props = this.props) {
+    const uppy = props.uppy
 
     uppy.removePlugin(this.plugin)
   }

+ 17 - 2
packages/@uppy/react/src/ProgressBar.js

@@ -11,6 +11,21 @@ const h = React.createElement
 
 class ProgressBar extends React.Component {
   componentDidMount () {
+    this.installPlugin()
+  }
+
+  componentDidUpdate (prevProps) {
+    if (prevProps.uppy !== this.props.uppy) {
+      this.uninstallPlugin(prevProps)
+      this.installPlugin()
+    }
+  }
+
+  componentWillUnmount () {
+    this.uninstallPlugin()
+  }
+
+  installPlugin () {
     const uppy = this.props.uppy
     const options = Object.assign(
       { id: 'react:ProgressBar' },
@@ -24,8 +39,8 @@ class ProgressBar extends React.Component {
     this.plugin = uppy.getPlugin(options.id)
   }
 
-  componentWillUnmount () {
-    const uppy = this.props.uppy
+  uninstallPlugin (props = this.props) {
+    const uppy = props.uppy
 
     uppy.removePlugin(this.plugin)
   }

+ 17 - 2
packages/@uppy/react/src/StatusBar.js

@@ -12,6 +12,21 @@ const h = React.createElement
 
 class StatusBar extends React.Component {
   componentDidMount () {
+    this.installPlugin()
+  }
+
+  componentDidUpdate (prevProps) {
+    if (prevProps.uppy !== this.props.uppy) {
+      this.uninstallPlugin(prevProps)
+      this.installPlugin()
+    }
+  }
+
+  componentWillUnmount () {
+    this.uninstallPlugin()
+  }
+
+  installPlugin () {
     const uppy = this.props.uppy
     const options = Object.assign(
       { id: 'react:StatusBar' },
@@ -25,8 +40,8 @@ class StatusBar extends React.Component {
     this.plugin = uppy.getPlugin(options.id)
   }
 
-  componentWillUnmount () {
-    const uppy = this.props.uppy
+  uninstallPlugin (props = this.props) {
+    const uppy = props.uppy
 
     uppy.removePlugin(this.plugin)
   }

+ 17 - 2
packages/@uppy/react/src/Wrapper.js

@@ -12,14 +12,29 @@ class UppyWrapper extends React.Component {
   }
 
   componentDidMount () {
+    this.installPlugin()
+  }
+
+  componentDidUpdate (prevProps) {
+    if (prevProps.uppy !== this.props.uppy) {
+      this.uninstallPlugin(prevProps)
+      this.installPlugin()
+    }
+  }
+
+  componentWillUnmount () {
+    this.uninstallPlugin()
+  }
+
+  installPlugin () {
     const plugin = this.props.uppy
       .getPlugin(this.props.plugin)
 
     plugin.mount(this.container, plugin)
   }
 
-  componentWillUnmount () {
-    const plugin = this.props.uppy
+  uninstallPlugin (props = this.props) {
+    const plugin = props.uppy
       .getPlugin(this.props.plugin)
 
     plugin.unmount()

+ 1 - 1
packages/@uppy/tus/package.json

@@ -24,7 +24,7 @@
   "dependencies": {
     "@uppy/companion-client": "0.27.3",
     "@uppy/utils": "0.29.1",
-    "tus-js-client": "^1.5.1"
+    "tus-js-client": "1.6.0"
   },
   "devDependencies": {
     "@uppy/core": "0.29.1"

+ 10 - 2
packages/@uppy/tus/src/index.js

@@ -154,7 +154,11 @@ module.exports = class Tus extends Plugin {
       }
 
       optsTus.onSuccess = () => {
-        this.uppy.emit('upload-success', file, upload, upload.url)
+        const uploadResp = {
+          uploadURL: upload.url
+        }
+
+        this.uppy.emit('upload-success', file, uploadResp)
 
         if (upload.url) {
           this.uppy.log('Download ' + upload.file.name + ' from ' + upload.url)
@@ -327,7 +331,11 @@ module.exports = class Tus extends Plugin {
       })
 
       socket.on('success', (data) => {
-        this.uppy.emit('upload-success', file, data, data.url)
+        const uploadResp = {
+          uploadURL: data.url
+        }
+
+        this.uppy.emit('upload-success', file, uploadResp)
         this.resetUploaderReferences(file.id)
         resolve()
       })

+ 19 - 12
packages/@uppy/xhr-upload/src/index.js

@@ -232,15 +232,13 @@ module.exports = class XHRUpload extends Plugin {
           const body = opts.getResponseData(xhr.responseText, xhr)
           const uploadURL = body[opts.responseUrlFieldName]
 
-          const response = {
+          const uploadResp = {
             status: ev.target.status,
             body,
             uploadURL
           }
 
-          this.uppy.setFileState(file.id, { response })
-
-          this.uppy.emit('upload-success', file, body, uploadURL)
+          this.uppy.emit('upload-success', file, uploadResp)
 
           if (uploadURL) {
             this.uppy.log(`Download ${file.name} from ${file.uploadURL}`)
@@ -256,9 +254,7 @@ module.exports = class XHRUpload extends Plugin {
             body
           }
 
-          this.uppy.setFileState(file.id, { response })
-
-          this.uppy.emit('upload-error', file, error)
+          this.uppy.emit('upload-error', file, error, response)
           return reject(error)
         }
       })
@@ -332,9 +328,16 @@ module.exports = class XHRUpload extends Plugin {
         socket.on('progress', (progressData) => emitSocketProgress(this, progressData, file))
 
         socket.on('success', (data) => {
-          const resp = opts.getResponseData(data.response.responseText, data.response)
-          const uploadURL = resp[opts.responseUrlFieldName]
-          this.uppy.emit('upload-success', file, resp, uploadURL)
+          const body = opts.getResponseData(data.response.responseText, data.response)
+          const uploadURL = body[opts.responseUrlFieldName]
+
+          const uploadResp = {
+            status: data.response.status,
+            body,
+            uploadURL
+          }
+
+          this.uppy.emit('upload-success', file, uploadResp)
           socket.close()
           return resolve()
         })
@@ -399,9 +402,13 @@ module.exports = class XHRUpload extends Plugin {
         timer.done()
 
         if (ev.target.status >= 200 && ev.target.status < 300) {
-          const resp = this.opts.getResponseData(xhr.responseText, xhr)
+          const body = this.opts.getResponseData(xhr.responseText, xhr)
+          const uploadResp = {
+            status: ev.target.status,
+            body
+          }
           files.forEach((file) => {
-            this.uppy.emit('upload-success', file, resp)
+            this.uppy.emit('upload-success', file, uploadResp)
           })
           return resolve()
         }

+ 26 - 0
website/src/docs/react-dashboard-modal.md

@@ -35,6 +35,32 @@ Import general Core styles from `@uppy/core/dist/style.css` first, then add the
 
 Styles for Provider plugins, like Google Drive and Instagram, are also bundled with Dashboard styles. Styles for other plugins, such as `@uppy/url` and `@uppy/webcam`, are not inluded. If you are using those, please see their docs and make sure to include styles for them as well.
 
+## Initializing Uppy
+
+Your Uppy instance must be initialized before passing it to an `uppy={}` prop, and should be cleaned up using `uppy.close()` when you are done with it. A simple approach is to initialize it in your React component's `constructor()` and destroy it in `componentWillUnmount()`.
+
+> ⚠ Uppy instances are stateful, so the same instance must be used across different renders.
+> Do **NOT** initialize Uppy in a `render()` method!
+> Do **NOT** initialize Uppy in a function component!
+
+```js
+class MyComponent extends React.Component {
+  constructor (props) {
+    super(props)
+    this.uppy = Uppy()
+      .use(Transloadit, {})
+  }
+
+  componentWillUnmount () {
+    this.uppy.close()
+  }
+
+  render () {
+    return <DashboardModal uppy={this.uppy} />
+  }
+}
+```
+
 <!-- Make sure the old name of this section still works -->
 <a id="Options"></a>
 

+ 26 - 0
website/src/docs/react-dashboard.md

@@ -35,6 +35,32 @@ Import general Core styles from `@uppy/core/dist/style.css` first, then add the
 
 Styles for Provider plugins, like Google Drive and Instagram, are also bundled with Dashboard styles. Styles for other plugins, such as `@uppy/url` and `@uppy/webcam`, are not inluded. If you are using those, please see their docs and make sure to include styles for them as well.
 
+## Initializing Uppy
+
+Your Uppy instance must be initialized before passing it to an `uppy={}` prop, and should be cleaned up using `uppy.close()` when you are done with it. A simple approach is to initialize it in your React component's `constructor()` and destroy it in `componentWillUnmount()`.
+
+> ⚠ Uppy instances are stateful, so the same instance must be used across different renders.
+> Do **NOT** initialize Uppy in a `render()` method!
+> Do **NOT** initialize Uppy in a function component!
+
+```js
+class MyComponent extends React.Component {
+  constructor (props) {
+    super(props)
+    this.uppy = Uppy()
+      .use(Transloadit, {})
+  }
+
+  componentWillUnmount () {
+    this.uppy.close()
+  }
+
+  render () {
+    return <Dashboard uppy={this.uppy} />
+  }
+}
+```
+
 ## Props
 
 The `<Dashboard />` component supports all [`@uppy/dashboard`][] options as props.

+ 26 - 0
website/src/docs/react-dragdrop.md

@@ -32,6 +32,32 @@ import '@uppy/drag-drop/dist/style.css'
 
 Import general Core styles from `@uppy/core/dist/style.css` first, then add the Drag & Drop styles from `@uppy/drag-drop/dist/style.css`. A minified version is also available as `style.min.css` at the same path. The way to do import depends on your build system.
 
+## Initializing Uppy
+
+Your Uppy instance must be initialized before passing it to an `uppy={}` prop, and should be cleaned up using `uppy.close()` when you are done with it. A simple approach is to initialize it in your React component's `constructor()` and destroy it in `componentWillUnmount()`.
+
+> ⚠ Uppy instances are stateful, so the same instance must be used across different renders.
+> Do **NOT** initialize Uppy in a `render()` method!
+> Do **NOT** initialize Uppy in a function component!
+
+```js
+class MyComponent extends React.Component {
+  constructor (props) {
+    super(props)
+    this.uppy = Uppy()
+      .use(Transloadit, {})
+  }
+
+  componentWillUnmount () {
+    this.uppy.close()
+  }
+
+  render () {
+    return <DragDrop uppy={this.uppy} />
+  }
+}
+```
+
 ## Props
 
 The `<DragDrop />` component supports all [DragDrop][] options as props.

+ 26 - 0
website/src/docs/react-progressbar.md

@@ -32,6 +32,32 @@ import '@uppy/progress-bar/dist/style.css'
 
 Import general Core styles from `@uppy/core/dist/style.css` first, then add the Progress Bar styles from `@uppy/progress-bar/dist/style.css`. A minified version is also available as `style.min.css` at the same path. The way to do import depends on your build system.
 
+## Initializing Uppy
+
+Your Uppy instance must be initialized before passing it to an `uppy={}` prop, and should be cleaned up using `uppy.close()` when you are done with it. A simple approach is to initialize it in your React component's `constructor()` and destroy it in `componentWillUnmount()`.
+
+> ⚠ Uppy instances are stateful, so the same instance must be used across different renders.
+> Do **NOT** initialize Uppy in a `render()` method!
+> Do **NOT** initialize Uppy in a function component!
+
+```js
+class MyComponent extends React.Component {
+  constructor (props) {
+    super(props)
+    this.uppy = Uppy()
+      .use(Transloadit, {})
+  }
+
+  componentWillUnmount () {
+    this.uppy.close()
+  }
+
+  render () {
+    return <ProgressBar uppy={this.uppy} />
+  }
+}
+```
+
 ## Props
 
 The `<ProgressBar />` component supports all [`@uppy/progress-bar`][] options as props.

+ 26 - 0
website/src/docs/react-statusbar.md

@@ -32,6 +32,32 @@ import '@uppy/status-bar/dist/style.css'
 
 Import general Core styles from `@uppy/core/dist/style.css` first, then add the Status Bar styles from `@uppy/status-bar/dist/style.css`. A minified version is also available as `style.min.css` at the same path. The way to do import depends on your build system.
 
+## Initializing Uppy
+
+Your Uppy instance must be initialized before passing it to an `uppy={}` prop, and should be cleaned up using `uppy.close()` when you are done with it. A simple approach is to initialize it in your React component's `constructor()` and destroy it in `componentWillUnmount()`.
+
+> ⚠ Uppy instances are stateful, so the same instance must be used across different renders.
+> Do **NOT** initialize Uppy in a `render()` method!
+> Do **NOT** initialize Uppy in a function component!
+
+```js
+class MyComponent extends React.Component {
+  constructor (props) {
+    super(props)
+    this.uppy = Uppy()
+      .use(Transloadit, {})
+  }
+
+  componentWillUnmount () {
+    this.uppy.close()
+  }
+
+  render () {
+    return <StatusBar uppy={this.uppy} />
+  }
+}
+```
+
 ## Props
 
 The `<StatusBar />` component supports all [`@uppy/status-bar`][] options as props.

+ 1 - 0
website/src/docs/react.md

@@ -62,6 +62,7 @@ const AvatarPicker = ({ currentAvatar }) => {
             dropHereOr: 'Drop here or %{browse}',
             // Used as the label for the link that opens the system file selection dialog.
             browse: 'browse'
+          }
         }}
       />
     </div>

+ 25 - 6
website/src/docs/uppy.md

@@ -549,13 +549,23 @@ uppy.on('upload-progress', (file, progress) => {
 
 Fired each time a single upload is completed.
 
+`response` object (depending on the uploader plugin used, it might contain less info, the example is for `@uppy/xhr-upload`):
+
+```js
+{
+  status, // HTTP status code (0, 200, 300)
+  body, // response body
+  uploadURL // the file url, if it was returned
+}
+```
+
 ``` javascript
-uppy.on('upload-success', (file, resp, uploadURL) => {
-  console.log(file.name, uploadURL)
+uppy.on('upload-success', (file, response) => {
+  console.log(file.name, response.uploadURL)
   var img = new Image()
   img.width = 300
-  img.alt = fileId
-  img.src = uploadURL
+  img.alt = file.id
+  img.src = response.uploadURL
   document.body.appendChild(img)
 })
 ```
@@ -579,10 +589,19 @@ Fired when Uppy fails to upload/encode the entire upload. That error is then set
 
 ### `upload-error`
 
-Fired when an error occurs with a specific file:
+Fired each time a single upload has errored.
+
+`response` object (depending on the uploader plugin used, it might contain less info, the example is for `@uppy/xhr-upload`):
+
+```js
+{
+  status, // HTTP status code (0, 200, 300)
+  body // response body
+}
+```
 
 ``` javascript
-uppy.on('upload-error', (file, error) => {
+uppy.on('upload-error', (file, error, response) => {
   console.log('error with file:', file.id)
   console.log('error message:', error)
 })

+ 2 - 0
website/themes/uppy/layout/layout.ejs

@@ -20,6 +20,8 @@
     <meta name="twitter:description" content="<%- excerpt %>">
     <meta property="og:image" content="<%- image %>">
     <meta name="twitter:image" content="<%- image %>">
+    
+    <meta name="google-site-verification" content="JxARoHXoCI8bD07pLV_u3z6xpuWNcSIZIcHEytyCkUc" />
 
     <link rel="icon" href="<%- config.logo_icon %>" type="image/x-icon">
     <link rel="alternate" type="application/rss+xml" title="<%= config.title %>" href="/atom.xml">