diff --git a/.eslintrc.js b/.eslintrc.js index 3ff23f16f3..f2a6c09586 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -307,8 +307,19 @@ module.exports = { { files: ['./packages/@uppy/companion/**/*.js'], rules: { - 'no-restricted-syntax': 'warn', 'no-underscore-dangle': 'off', + + // transloadit rules we would like to enforce in the future + // but will require separate PRs to gradually get there + // and so the meantime: just warn + 'class-methods-use-this': 'warn', + 'consistent-return': 'warn', + 'global-require': 'warn', + 'import/order': 'warn', + 'no-param-reassign': 'warn', + 'no-redeclare': 'warn', + 'no-shadow': 'warn', + 'no-use-before-define': 'warn', }, }, { diff --git a/packages/@uppy/companion/src/companion.js b/packages/@uppy/companion/src/companion.js index ab2d2501c0..c2e9f7a852 100644 --- a/packages/@uppy/companion/src/companion.js +++ b/packages/@uppy/companion/src/companion.js @@ -77,7 +77,7 @@ module.exports.app = (optionsArg = {}) => { // create singleton redis client if (options.redisUrl) { - redis.client(merge({ url: options.redisUrl }, options.redisOptions || {})) + redis.client(options) } const emitter = createEmitter(options.redisUrl, options.redisPubSubScope) @@ -117,7 +117,7 @@ module.exports.app = (optionsArg = {}) => { // add uppy options to the request object so it can be accessed by subsequent handlers. app.use('*', middlewares.getCompanionMiddleware(options)) - app.use('/s3', s3(options.providerOptions.s3)) + app.use('/s3', s3(options.s3)) app.use('/url', url()) app.post('/:providerName/preauth', middlewares.hasSessionAndProvider, controllers.preauth) diff --git a/packages/@uppy/companion/src/config/companion.js b/packages/@uppy/companion/src/config/companion.js index 5afbdeb788..64cbf4e793 100644 --- a/packages/@uppy/companion/src/config/companion.js +++ b/packages/@uppy/companion/src/config/companion.js @@ -8,15 +8,14 @@ const defaultOptions = { protocol: 'http', path: '', }, - providerOptions: { - s3: { - acl: 'public-read', // todo default to no ACL in next major - endpoint: 'https://{service}.{region}.amazonaws.com', - conditions: [], - useAccelerateEndpoint: false, - getKey: (req, filename) => filename, - expires: ms('5 minutes') / 1000, - }, + providerOptions: {}, + s3: { + acl: 'public-read', // todo default to no ACL in next major + endpoint: 'https://{service}.{region}.amazonaws.com', + conditions: [], + useAccelerateEndpoint: false, + getKey: (req, filename) => filename, + expires: ms('5 minutes') / 1000, }, allowLocalUrls: false, logClientVersion: true, @@ -30,7 +29,8 @@ const defaultOptions = { */ function getMaskableSecrets (companionOptions) { const secrets = [] - const { providerOptions, customProviders } = companionOptions + const { providerOptions, customProviders, s3 } = companionOptions + Object.keys(providerOptions).forEach((provider) => { if (providerOptions[provider].secret) { secrets.push(providerOptions[provider].secret) @@ -45,6 +45,10 @@ function getMaskableSecrets (companionOptions) { }) } + if (s3?.secret) { + secrets.push(s3.secret) + } + return secrets } diff --git a/packages/@uppy/companion/src/server/Uploader.js b/packages/@uppy/companion/src/server/Uploader.js index 6ad8c7723d..d1099eb41c 100644 --- a/packages/@uppy/companion/src/server/Uploader.js +++ b/packages/@uppy/companion/src/server/Uploader.js @@ -345,7 +345,7 @@ class Uploader { storage: redis.client(), s3: req.companion.s3Client ? { client: req.companion.s3Client, - options: req.companion.options.providerOptions.s3, + options: req.companion.options.s3, } : null, chunkSize: req.companion.options.chunkSize, } @@ -400,7 +400,11 @@ class Uploader { */ saveState (state) { if (!this.storage) return - this.storage.set(`${Uploader.STORAGE_PREFIX}:${this.token}`, jsonStringify(state)) + // make sure the keys get cleaned up. + // https://github.com/transloadit/uppy/issues/3748 + const keyExpirySec = 60 * 60 * 24 + const redisKey = `${Uploader.STORAGE_PREFIX}:${this.token}` + this.storage.set(redisKey, jsonStringify(state), 'EX', keyExpirySec) } /** diff --git a/packages/@uppy/companion/src/server/helpers/utils.js b/packages/@uppy/companion/src/server/helpers/utils.js index 42dde25858..98545ba66a 100644 --- a/packages/@uppy/companion/src/server/helpers/utils.js +++ b/packages/@uppy/companion/src/server/helpers/utils.js @@ -43,7 +43,7 @@ module.exports.getURLBuilder = (options) => { * * @param {string} path the tail path of the url * @param {boolean} isExternal if the url is for the external world - * @param {boolean=} excludeHost if the server domain and protocol should be included + * @param {boolean} [excludeHost] if the server domain and protocol should be included */ const buildURL = (path, isExternal, excludeHost) => { let url = path diff --git a/packages/@uppy/companion/src/server/logger.js b/packages/@uppy/companion/src/server/logger.js index d7bb051537..3875190e18 100644 --- a/packages/@uppy/companion/src/server/logger.js +++ b/packages/@uppy/companion/src/server/logger.js @@ -39,8 +39,8 @@ function maskMessage (msg) { * @param {string | Error} arg the message or error to log * @param {string} tag a unique tag to easily search for this message * @param {string} level error | info | debug - * @param {string=} id a unique id to easily trace logs tied to a request - * @param {Function=} color function to display the log in appropriate color + * @param {string} [id] a unique id to easily trace logs tied to a request + * @param {Function} [color] function to display the log in appropriate color */ const log = (arg, tag = '', level, id = '', color = (message) => message) => { const time = new Date().toISOString() @@ -66,8 +66,8 @@ const log = (arg, tag = '', level, id = '', color = (message) => message) => { * INFO level log * * @param {string} msg the message to log - * @param {string=} tag a unique tag to easily search for this message - * @param {string=} traceId a unique id to easily trace logs tied to a request + * @param {string} [tag] a unique tag to easily search for this message + * @param {string} [traceId] a unique id to easily trace logs tied to a request */ exports.info = (msg, tag, traceId) => { log(msg, tag, 'info', traceId) @@ -77,8 +77,8 @@ exports.info = (msg, tag, traceId) => { * WARN level log * * @param {string} msg the message to log - * @param {string=} tag a unique tag to easily search for this message - * @param {string=} traceId a unique id to easily trace logs tied to a request + * @param {string} [tag] a unique tag to easily search for this message + * @param {string} [traceId] a unique id to easily trace logs tied to a request */ exports.warn = (msg, tag, traceId) => { // @ts-ignore @@ -89,8 +89,8 @@ exports.warn = (msg, tag, traceId) => { * ERROR level log * * @param {string | Error} msg the message to log - * @param {string=} tag a unique tag to easily search for this message - * @param {string=} traceId a unique id to easily trace logs tied to a request + * @param {string} [tag] a unique tag to easily search for this message + * @param {string} [traceId] a unique id to easily trace logs tied to a request */ exports.error = (msg, tag, traceId) => { // @ts-ignore @@ -101,8 +101,8 @@ exports.error = (msg, tag, traceId) => { * DEBUG level log * * @param {string} msg the message to log - * @param {string=} tag a unique tag to easily search for this message - * @param {string=} traceId a unique id to easily trace logs tied to a request + * @param {string} [tag] a unique tag to easily search for this message + * @param {string} [traceId] a unique id to easily trace logs tied to a request */ exports.debug = (msg, tag, traceId) => { if (process.env.NODE_ENV !== 'production') { diff --git a/packages/@uppy/companion/src/server/middlewares.js b/packages/@uppy/companion/src/server/middlewares.js index 9e48be859b..b8d16c1bcd 100644 --- a/packages/@uppy/companion/src/server/middlewares.js +++ b/packages/@uppy/companion/src/server/middlewares.js @@ -69,14 +69,14 @@ exports.cookieAuthToken = (req, res, next) => { } exports.loadSearchProviderToken = (req, res, next) => { - const { searchProviders } = req.companion.options.providerOptions + const { providerOptions } = req.companion.options const providerName = req.params.searchProviderName - if (!searchProviders || !searchProviders[providerName] || !searchProviders[providerName].key) { + if (!providerOptions[providerName] || !providerOptions[providerName].key) { logger.info(`unconfigured credentials for ${providerName}`, 'searchtoken.load.unset', req.id) return res.sendStatus(501) } - req.companion.providerToken = searchProviders[providerName].key + req.companion.providerToken = providerOptions[providerName].key next() } diff --git a/packages/@uppy/companion/src/server/provider/box/index.js b/packages/@uppy/companion/src/server/provider/box/index.js index 9023f7551f..532ea1323e 100644 --- a/packages/@uppy/companion/src/server/provider/box/index.js +++ b/packages/@uppy/companion/src/server/provider/box/index.js @@ -41,6 +41,10 @@ class Box extends Provider { * Lists files and folders from Box API * * @param {object} options + * @param {string} options.directory + * @param {any} options.query + * @param {string} options.token + * @param {unknown} options.companion * @param {Function} done */ _list ({ directory, token, query, companion }, done) { diff --git a/packages/@uppy/companion/src/server/provider/index.js b/packages/@uppy/companion/src/server/provider/index.js index 3c9221955b..b2f668c784 100644 --- a/packages/@uppy/companion/src/server/provider/index.js +++ b/packages/@uppy/companion/src/server/provider/index.js @@ -188,8 +188,6 @@ module.exports.addProviderOptions = (companionOptions, grantConfig) => { } else if (server.path) { grantConfig[authProvider].callback = `${server.path}${grantConfig[authProvider].callback}` } - } else if (!['s3', 'searchProviders'].includes(providerName)) { - logger.warn(`skipping one found unsupported provider "${providerName}".`, 'provider.options.skip') } }) } diff --git a/packages/@uppy/companion/src/server/provider/onedrive/index.js b/packages/@uppy/companion/src/server/provider/onedrive/index.js index b7ee7a62ae..23ffeb7b0c 100644 --- a/packages/@uppy/companion/src/server/provider/onedrive/index.js +++ b/packages/@uppy/companion/src/server/provider/onedrive/index.js @@ -37,6 +37,9 @@ class OneDrive extends Provider { * it then waits till both requests are done before proceeding with the callback * * @param {object} options + * @param {string} options.directory + * @param {any} options.query + * @param {string} options.token * @param {Function} done */ _list ({ directory, query, token }, done) { diff --git a/packages/@uppy/companion/src/server/provider/unsplash/adapter.js b/packages/@uppy/companion/src/server/provider/unsplash/adapter.js index 9735b0c1c0..3fb9bcec91 100644 --- a/packages/@uppy/companion/src/server/provider/unsplash/adapter.js +++ b/packages/@uppy/companion/src/server/provider/unsplash/adapter.js @@ -40,7 +40,7 @@ exports.getItemThumbnailUrl = (item) => { } exports.getNextPageQuery = (currentQuery) => { - const newCursor = parseInt(currentQuery.cursor || 1) + 1 + const newCursor = Number.parseInt(currentQuery.cursor || 1, 10) + 1 const query = { ...currentQuery, cursor: newCursor, diff --git a/packages/@uppy/companion/src/server/redis.js b/packages/@uppy/companion/src/server/redis.js index fd1bc3b7f8..4e2bf6c11d 100644 --- a/packages/@uppy/companion/src/server/redis.js +++ b/packages/@uppy/companion/src/server/redis.js @@ -1,21 +1,26 @@ const redis = require('redis') +const merge = require('lodash.merge') let redisClient /** - * A Singleton module that provides only on redis client through out + * A Singleton module that provides a single redis client through out * the lifetime of the server * - * @param {object=} opts node-redis client options + * @param {Record} [opts] node-redis client options */ -module.exports.client = (opts) => { - if (!opts) { - return redisClient - } - +function createClient (opts) { if (!redisClient) { redisClient = redis.createClient(opts) } return redisClient } + +module.exports.client = (companionOptions) => { + if (!companionOptions) { + return redisClient + } + + return createClient(merge({ url: companionOptions.redisUrl }, companionOptions.redisOptions)) +} diff --git a/packages/@uppy/companion/src/server/s3-client.js b/packages/@uppy/companion/src/server/s3-client.js index cce3b41aac..d22e646499 100644 --- a/packages/@uppy/companion/src/server/s3-client.js +++ b/packages/@uppy/companion/src/server/s3-client.js @@ -8,35 +8,35 @@ const AWS = require('aws-sdk') */ module.exports = (companionOptions) => { let s3Client = null - if (companionOptions.providerOptions.s3) { - const s3ProviderOptions = companionOptions.providerOptions.s3 + if (companionOptions.s3) { + const { s3 } = companionOptions - if (s3ProviderOptions.accessKeyId || s3ProviderOptions.secretAccessKey) { + if (s3.accessKeyId || s3.secretAccessKey) { throw new Error('Found `providerOptions.s3.accessKeyId` or `providerOptions.s3.secretAccessKey` configuration, but Companion requires `key` and `secret` option names instead. Please use the `key` property instead of `accessKeyId` and the `secret` property instead of `secretAccessKey`.') } - const rawClientOptions = s3ProviderOptions.awsClientOptions + const rawClientOptions = s3.awsClientOptions if (rawClientOptions && (rawClientOptions.accessKeyId || rawClientOptions.secretAccessKey)) { throw new Error('Found unsupported `providerOptions.s3.awsClientOptions.accessKeyId` or `providerOptions.s3.awsClientOptions.secretAccessKey` configuration. Please use the `providerOptions.s3.key` and `providerOptions.s3.secret` options instead.') } const s3ClientOptions = { signatureVersion: 'v4', - endpoint: s3ProviderOptions.endpoint, - region: s3ProviderOptions.region, + endpoint: s3.endpoint, + region: s3.region, // backwards compat - useAccelerateEndpoint: s3ProviderOptions.useAccelerateEndpoint, + useAccelerateEndpoint: s3.useAccelerateEndpoint, ...rawClientOptions, } // Use credentials to allow assumed roles to pass STS sessions in. // If the user doesn't specify key and secret, the default credentials (process-env) // will be used by S3 in calls below. - if (s3ProviderOptions.key && s3ProviderOptions.secret && !s3ClientOptions.credentials) { + if (s3.key && s3.secret && !s3ClientOptions.credentials) { s3ClientOptions.credentials = new AWS.Credentials( - s3ProviderOptions.key, - s3ProviderOptions.secret, - s3ProviderOptions.sessionToken, + s3.key, + s3.secret, + s3.sessionToken, ) } s3Client = new S3(s3ClientOptions) diff --git a/packages/@uppy/companion/src/standalone/helper.js b/packages/@uppy/companion/src/standalone/helper.js index 260e4f7d3f..20f0748f9e 100644 --- a/packages/@uppy/companion/src/standalone/helper.js +++ b/packages/@uppy/companion/src/standalone/helper.js @@ -64,26 +64,22 @@ const getConfigFromEnv = () => { verificationToken: getSecret('COMPANION_ZOOM_VERIFICATION_TOKEN'), credentialsURL: process.env.COMPANION_ZOOM_KEYS_ENDPOINT, }, - // TODO: remove the redundant searchProviders warpper in next major version - searchProviders: { - unsplash: { - key: process.env.COMPANION_UNSPLASH_KEY, - secret: process.env.COMPANION_UNSPLASH_SECRET, - }, - }, - // TODO: move s3 out of providerOptions, it's a destination, not a source - s3: { - key: process.env.COMPANION_AWS_KEY, - secret: getSecret('COMPANION_AWS_SECRET'), - bucket: process.env.COMPANION_AWS_BUCKET, - endpoint: process.env.COMPANION_AWS_ENDPOINT, - region: process.env.COMPANION_AWS_REGION, - useAccelerateEndpoint: - process.env.COMPANION_AWS_USE_ACCELERATE_ENDPOINT === 'true', - expires: parseInt(process.env.COMPANION_AWS_EXPIRES || '300', 10), - acl: process.env.COMPANION_AWS_DISABLE_ACL === 'true' ? null : (process.env.COMPANION_AWS_ACL || 'public-read'), // todo default to no ACL in next major and remove COMPANION_AWS_DISABLE_ACL + unsplash: { + key: process.env.COMPANION_UNSPLASH_KEY, + secret: process.env.COMPANION_UNSPLASH_SECRET, }, }, + s3: { + key: process.env.COMPANION_AWS_KEY, + secret: getSecret('COMPANION_AWS_SECRET'), + bucket: process.env.COMPANION_AWS_BUCKET, + endpoint: process.env.COMPANION_AWS_ENDPOINT, + region: process.env.COMPANION_AWS_REGION, + useAccelerateEndpoint: + process.env.COMPANION_AWS_USE_ACCELERATE_ENDPOINT === 'true', + expires: parseInt(process.env.COMPANION_AWS_EXPIRES || '300', 10), + acl: process.env.COMPANION_AWS_DISABLE_ACL === 'true' ? null : (process.env.COMPANION_AWS_ACL || 'public-read'), // todo default to no ACL in next major and remove COMPANION_AWS_DISABLE_ACL + }, server: { host: process.env.COMPANION_DOMAIN, protocol: process.env.COMPANION_PROTOCOL, @@ -190,11 +186,6 @@ exports.buildHelpfulStartupMessage = (companionOptions) => { const buildURL = utils.getURLBuilder(companionOptions) const callbackURLs = [] Object.keys(companionOptions.providerOptions).forEach((providerName) => { - // s3 does not need redirect_uris - if (providerName === 's3') { - return - } - callbackURLs.push(buildURL(`/connect/${providerName}/redirect`, true)) }) diff --git a/packages/@uppy/companion/src/standalone/index.js b/packages/@uppy/companion/src/standalone/index.js index 0cfec8431b..5e68490158 100644 --- a/packages/@uppy/companion/src/standalone/index.js +++ b/packages/@uppy/companion/src/standalone/index.js @@ -4,16 +4,16 @@ const helmet = require('helmet') const morgan = require('morgan') const bodyParser = require('body-parser') const { URL } = require('url') -const merge = require('lodash.merge') const session = require('express-session') const addRequestId = require('express-request-id')() +const connectRedis = require('connect-redis') + const logger = require('../server/logger') const redis = require('../server/redis') const companion = require('../companion') const helper = require('./helper') const middlewares = require('../server/middlewares') const { getURLBuilder } = require('../server/helpers/utils') -const connectRedis = require('connect-redis') /** * Configures an Express app for running Companion standalone @@ -141,9 +141,7 @@ module.exports = function server (inputCompanionOptions = {}) { if (companionOptions.redisUrl) { const RedisStore = connectRedis(session) - const redisClient = redis.client( - merge({ url: companionOptions.redisUrl }, companionOptions.redisOptions), - ) + const redisClient = redis.client(companionOptions) sessionOptions.store = new RedisStore({ client: redisClient }) } diff --git a/packages/@uppy/dashboard/src/Dashboard.jsx b/packages/@uppy/dashboard/src/Dashboard.jsx index f369bd0572..df0fccbdc4 100644 --- a/packages/@uppy/dashboard/src/Dashboard.jsx +++ b/packages/@uppy/dashboard/src/Dashboard.jsx @@ -380,7 +380,7 @@ export default class Dashboard extends UIPlugin { meta: { // path of the file relative to the ancestor directory the user selected. // e.g. 'docs/Old Prague/airbnb.pdf' - relativePath: file.relativePath || null, + relativePath: file.relativePath || file.webkitRelativePath || null, }, })) diff --git a/packages/uppy/index.js b/packages/uppy/index.js index 01ed873c38..c9f2e2fb98 100644 --- a/packages/uppy/index.js +++ b/packages/uppy/index.js @@ -20,23 +20,24 @@ exports.Dashboard = require('@uppy/dashboard') exports.DragDrop = require('@uppy/drag-drop') exports.DropTarget = require('@uppy/drop-target') exports.FileInput = require('@uppy/file-input') +exports.ImageEditor = require('@uppy/image-editor') exports.Informer = require('@uppy/informer') exports.ProgressBar = require('@uppy/progress-bar') exports.StatusBar = require('@uppy/status-bar') -exports.ImageEditor = require('@uppy/image-editor') // Acquirers +exports.Audio = require('@uppy/audio') +exports.Box = require('@uppy/box') exports.Dropbox = require('@uppy/dropbox') +exports.Facebook = require('@uppy/facebook') exports.GoogleDrive = require('@uppy/google-drive') exports.Instagram = require('@uppy/instagram') exports.OneDrive = require('@uppy/onedrive') -exports.Box = require('@uppy/box') -exports.Facebook = require('@uppy/facebook') +exports.ScreenCapture = require('@uppy/screen-capture') exports.Unsplash = require('@uppy/unsplash') exports.Url = require('@uppy/url') exports.Webcam = require('@uppy/webcam') -exports.ScreenCapture = require('@uppy/screen-capture') -exports.Audio = require('@uppy/audio') +exports.Zoom = require('@uppy/zoom') // Uploaders exports.AwsS3 = require('@uppy/aws-s3') @@ -46,10 +47,10 @@ exports.Tus = require('@uppy/tus') exports.XHRUpload = require('@uppy/xhr-upload') // Miscellaneous +exports.Compressor = require('@uppy/compressor') exports.Form = require('@uppy/form') exports.GoldenRetriever = require('@uppy/golden-retriever') exports.ReduxDevTools = require('@uppy/redux-dev-tools') exports.ThumbnailGenerator = require('@uppy/thumbnail-generator') -exports.Compressor = require('@uppy/compressor') exports.locales = {} diff --git a/packages/uppy/index.mjs b/packages/uppy/index.mjs index 99117908af..1dd66feec3 100644 --- a/packages/uppy/index.mjs +++ b/packages/uppy/index.mjs @@ -1,5 +1,5 @@ // Core -export { default as Core } from '@uppy/core' +export { default as Core, debugLogger } from '@uppy/core' // Utilities export { default as server } from '@uppy/companion-client' @@ -17,23 +17,24 @@ export { default as Dashboard } from '@uppy/dashboard' export { default as DragDrop } from '@uppy/drag-drop' export { default as DropTarget } from '@uppy/drop-target' export { default as FileInput } from '@uppy/file-input' +export { default as ImageEditor } from '@uppy/image-editor' export { default as Informer } from '@uppy/informer' export { default as ProgressBar } from '@uppy/progress-bar' export { default as StatusBar } from '@uppy/status-bar' -export { default as ImageEditor } from '@uppy/image-editor' // Acquirers +export { default as Audio } from '@uppy/audio' +export { default as Box } from '@uppy/box' export { default as Dropbox } from '@uppy/dropbox' +export { default as Facebook } from '@uppy/facebook' export { default as GoogleDrive } from '@uppy/google-drive' export { default as Instagram } from '@uppy/instagram' export { default as OneDrive } from '@uppy/onedrive' -export { default as Box } from '@uppy/box' -export { default as Facebook } from '@uppy/facebook' +export { default as ScreenCapture } from '@uppy/screen-capture' export { default as Unsplash } from '@uppy/unsplash' export { default as Url } from '@uppy/url' export { default as Webcam } from '@uppy/webcam' -export { default as ScreenCapture } from '@uppy/screen-capture' -export { default as Audio } from '@uppy/audio' +export { default as Zoom } from '@uppy/zoom' // Uploaders export { default as AwsS3 } from '@uppy/aws-s3' @@ -43,7 +44,10 @@ export { default as Tus } from '@uppy/tus' export { default as XHRUpload } from '@uppy/xhr-upload' // Miscellaneous +export { default as Compressor } from '@uppy/compressor' export { default as Form } from '@uppy/form' export { default as GoldenRetriever } from '@uppy/golden-retriever' export { default as ReduxDevTools } from '@uppy/redux-dev-tools' export { default as ThumbnailGenerator } from '@uppy/thumbnail-generator' + +export const locales = {} diff --git a/packages/uppy/package.json b/packages/uppy/package.json index 1815cced35..b6d3d7da7e 100644 --- a/packages/uppy/package.json +++ b/packages/uppy/package.json @@ -64,7 +64,8 @@ "@uppy/unsplash": "workspace:^", "@uppy/url": "workspace:^", "@uppy/webcam": "workspace:^", - "@uppy/xhr-upload": "workspace:^" + "@uppy/xhr-upload": "workspace:^", + "@uppy/zoom": "workspace:^" }, "devDependencies": { "abortcontroller-polyfill": "^1.7.3", diff --git a/website/src/docs/companion.md b/website/src/docs/companion.md index 7b7353af8b..fd403949c7 100644 --- a/website/src/docs/companion.md +++ b/website/src/docs/companion.md @@ -323,16 +323,16 @@ const options = { key: '***', secret: '***', }, - s3: { - getKey: (req, filename, metadata) => filename, - key: '***', - secret: '***', - bucket: 'bucket-name', - region: 'us-east-1', - useAccelerateEndpoint: false, // default: false, - expires: 3600, // default: 300 (5 minutes) - acl: 'private', // default: public-read - }, + }, + s3: { + getKey: (req, filename, metadata) => filename, + key: '***', + secret: '***', + bucket: 'bucket-name', + region: 'us-east-1', + useAccelerateEndpoint: false, // default: false, + expires: 3600, // default: 300 (5 minutes) + acl: 'private', // default: public-read }, server: { host: 'localhost:3020', // or yourdomain.com @@ -417,34 +417,34 @@ Please see [Supported Providers](https://uppy.io/docs/companion/#Supported-provi Companion comes with signature endpoints for AWS S3. These can be used by the Uppy client to sign requests to upload files directly to S3, without exposing secret S3 keys in the browser. Companion also supports uploading files from providers like Dropbox and Instagram directly into S3. -The S3 features can be configured using the `providerOptions.s3` property. +The S3 features can be configured using the `s3` property. -#### `providerOptions.s3.key` +#### `s3.key` The S3 access key ID. The standalone Companion server populates this with the value of the `COMPANION_AWS_KEY` environment variable by default. -#### `providerOptions.s3.secret` +#### `s3.secret` The S3 secret access key. The standalone Companion server populates this with the value of the `COMPANION_AWS_SECRET` environment variable by default. -#### `providerOptions.s3.bucket` +#### `s3.bucket` The name of the bucket to store uploaded files in. The standalone Companion server populates this with the value of the `COMPANION_AWS_BUCKET` environment variable by default. -#### `providerOptions.s3.region` +#### `s3.region` The datacenter region where the target bucket is located. The standalone Companion server populates this with the value of the `COMPANION_AWS_REGION` environment variable by default. -#### `providerOptions.s3.awsClientOptions` +#### `s3.awsClientOptions` -You can supply any [S3 option supported by the AWS SDK](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#constructor-property) in the `providerOptions.s3.awsClientOptions` object, _except for_ the below: +You can supply any [S3 option supported by the AWS SDK](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#constructor-property) in the `s3.awsClientOptions` object, _except for_ the below: -* `accessKeyId`. Instead, use the `providerOptions.s3.key` property. This is to make configuration names consistent between different Companion features. -* `secretAccessKey`. Instead, use the `providerOptions.s3.secret` property. This is to make configuration names consistent between different Companion features. +* `accessKeyId`. Instead, use the `s3.key` property. This is to make configuration names consistent between different Companion features. +* `secretAccessKey`. Instead, use the `s3.secret` property. This is to make configuration names consistent between different Companion features. Be aware that some options may cause wrong behaviour if they conflict with Companion’s assumptions. If you find that a particular option does not work as expected, please [open an issue on the Uppy repository](https://github.com/transloadit/uppy/issues/new) so we can document it here. -#### `providerOptions.s3.getKey(req, filename, metadata)` +#### `s3.getKey(req, filename, metadata)` Get the key name for a file. The key is the file path to which the file will be uploaded in your bucket. This option should be a function receiving three arguments: @@ -456,12 +456,10 @@ This function should return a string `key`. The `req` parameter can be used to u ```js app.use(authenticationMiddleware) -app.use(uppy.app({ - providerOptions: { - s3: { - getKey: (req, filename, metadata) => `${req.user.id}/${filename}`, - /* auth options */ - }, +app.use(companion.app({ + s3: { + getKey: (req, filename, metadata) => `${req.user.id}/${filename}`, + /* auth options */ }, })) ``` @@ -469,11 +467,9 @@ app.use(uppy.app({ The default implementation returns the `filename`, so all files will be uploaded to the root of the bucket as their original file name. ```js -app.use(uppy.app({ - providerOptions: { - s3: { - getKey: (req, filename, metadata) => filename, - }, +app.use(companion.app({ + s3: { + getKey: (req, filename, metadata) => filename, }, })) ``` diff --git a/yarn.lock b/yarn.lock index 0b9ccc24e4..e824f90593 100644 --- a/yarn.lock +++ b/yarn.lock @@ -41006,6 +41006,7 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis: "@uppy/url": "workspace:^" "@uppy/webcam": "workspace:^" "@uppy/xhr-upload": "workspace:^" + "@uppy/zoom": "workspace:^" abortcontroller-polyfill: ^1.7.3 core-js: ~3.19.3 md-gum-polyfill: ^1.0.0