@uppy/companion-client
Advanced tools
Comparing version 3.1.3 to 3.2.0
@@ -9,5 +9,3 @@ 'use strict'; | ||
} | ||
} | ||
export default AuthError; |
'use strict'; | ||
/** | ||
* Manages communications with Companion | ||
*/ | ||
export { default as RequestClient } from './RequestClient.js'; | ||
@@ -7,0 +7,0 @@ export { default as Provider } from './Provider.js'; |
'use strict'; | ||
function _classPrivateFieldLooseBase(receiver, privateKey) { if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) { throw new TypeError("attempted to use private field on non-instance"); } return receiver; } | ||
var id = 0; | ||
function _classPrivateFieldLooseKey(name) { return "__private_" + id++ + "_" + name; } | ||
import RequestClient from './RequestClient.js'; | ||
import * as tokenStorage from './tokenStorage.js'; | ||
const getName = id => { | ||
return id.split('-').map(s => s.charAt(0).toUpperCase() + s.slice(1)).join(' '); | ||
}; | ||
var _refreshingTokenPromise = /*#__PURE__*/_classPrivateFieldLooseKey("refreshingTokenPromise"); | ||
var _getAuthToken = /*#__PURE__*/_classPrivateFieldLooseKey("getAuthToken"); | ||
var _removeAuthToken = /*#__PURE__*/_classPrivateFieldLooseKey("removeAuthToken"); | ||
export default class Provider extends RequestClient { | ||
constructor(uppy, opts) { | ||
super(uppy, opts); | ||
Object.defineProperty(this, _removeAuthToken, { | ||
value: _removeAuthToken2 | ||
}); | ||
Object.defineProperty(this, _getAuthToken, { | ||
value: _getAuthToken2 | ||
}); | ||
Object.defineProperty(this, _refreshingTokenPromise, { | ||
writable: true, | ||
value: void 0 | ||
}); | ||
this.provider = opts.provider; | ||
@@ -21,11 +35,8 @@ this.id = this.provider; | ||
} | ||
async headers() { | ||
const [headers, token] = await Promise.all([super.headers(), this.getAuthToken()]); | ||
const [headers, token] = await Promise.all([super.headers(), _classPrivateFieldLooseBase(this, _getAuthToken)[_getAuthToken]()]); | ||
const authHeaders = {}; | ||
if (token) { | ||
authHeaders['uppy-auth-token'] = token; | ||
} | ||
if (this.companionKeysParams) { | ||
@@ -36,8 +47,7 @@ authHeaders['uppy-credentials-params'] = btoa(JSON.stringify({ | ||
} | ||
return { ...headers, | ||
return { | ||
...headers, | ||
...authHeaders | ||
}; | ||
} | ||
onReceiveResponse(response) { | ||
@@ -53,10 +63,5 @@ super.onReceiveResponse(response); | ||
} | ||
setAuthToken(token) { | ||
async setAuthToken(token) { | ||
return this.uppy.getPlugin(this.pluginId).storage.setItem(this.tokenKey, token); | ||
} | ||
getAuthToken() { | ||
return this.uppy.getPlugin(this.pluginId).storage.getItem(this.tokenKey); | ||
} | ||
/** | ||
@@ -66,8 +71,5 @@ * Ensure we have a preauth token if necessary. Attempts to fetch one if we don't, | ||
*/ | ||
async ensurePreAuth() { | ||
if (this.companionKeysParams && !this.preAuthToken) { | ||
await this.fetchPreAuthToken(); | ||
if (!this.preAuthToken) { | ||
@@ -78,3 +80,2 @@ throw new Error('Could not load authentication data required for third-party login. Please try again later.'); | ||
} | ||
authUrl(queries) { | ||
@@ -84,12 +85,11 @@ if (queries === void 0) { | ||
} | ||
const params = new URLSearchParams(queries); | ||
if (this.preAuthToken) { | ||
params.set('uppyPreAuthToken', this.preAuthToken); | ||
} | ||
return `${this.hostname}/${this.id}/connect?${params}`; | ||
} | ||
refreshTokenUrl() { | ||
return `${this.hostname}/${this.id}/refresh-token`; | ||
} | ||
fileUrl(id) { | ||
@@ -99,2 +99,32 @@ return `${this.hostname}/${this.id}/get/${id}`; | ||
/** @protected */ | ||
async request() { | ||
await _classPrivateFieldLooseBase(this, _refreshingTokenPromise)[_refreshingTokenPromise]; | ||
try { | ||
// throw Object.assign(new Error(), { isAuthError: true }) // testing simulate access token expired (to refresh token) | ||
return await super.request(...arguments); | ||
} catch (err) { | ||
if (!err.isAuthError) throw err; // only handle auth errors (401 from provider) | ||
await _classPrivateFieldLooseBase(this, _refreshingTokenPromise)[_refreshingTokenPromise]; | ||
// Many provider requests may be starting at once, however refresh token should only be called once. | ||
// Once a refresh token operation has started, we need all other request to wait for this operation (atomically) | ||
_classPrivateFieldLooseBase(this, _refreshingTokenPromise)[_refreshingTokenPromise] = (async () => { | ||
try { | ||
const response = await super.request({ | ||
path: this.refreshTokenUrl(), | ||
method: 'POST' | ||
}); | ||
await this.setAuthToken(response.uppyAuthToken); | ||
} finally { | ||
_classPrivateFieldLooseBase(this, _refreshingTokenPromise)[_refreshingTokenPromise] = undefined; | ||
} | ||
})(); | ||
await _classPrivateFieldLooseBase(this, _refreshingTokenPromise)[_refreshingTokenPromise]; | ||
// now retry the request with our new refresh token | ||
return super.request(...arguments); | ||
} | ||
} | ||
async fetchPreAuthToken() { | ||
@@ -104,3 +134,2 @@ if (!this.companionKeysParams) { | ||
} | ||
try { | ||
@@ -115,14 +144,10 @@ const res = await this.post(`${this.id}/preauth/`, { | ||
} | ||
list(directory) { | ||
return this.get(`${this.id}/list/${directory || ''}`); | ||
} | ||
logout() { | ||
return this.get(`${this.id}/logout`).then(response => Promise.all([response, this.uppy.getPlugin(this.pluginId).storage.removeItem(this.tokenKey)])).then(_ref => { | ||
let [response] = _ref; | ||
return response; | ||
}); | ||
async logout() { | ||
const response = await this.get(`${this.id}/logout`); | ||
await _classPrivateFieldLooseBase(this, _removeAuthToken)[_removeAuthToken](); | ||
return response; | ||
} | ||
static initPlugin(plugin, opts, defaultOpts) { | ||
@@ -132,20 +157,17 @@ /* eslint-disable no-param-reassign */ | ||
plugin.files = []; | ||
if (defaultOpts) { | ||
plugin.opts = { ...defaultOpts, | ||
plugin.opts = { | ||
...defaultOpts, | ||
...opts | ||
}; | ||
} | ||
if (opts.serverUrl || opts.serverPattern) { | ||
throw new Error('`serverUrl` and `serverPattern` have been renamed to `companionUrl` and `companionAllowedHosts` respectively in the 0.30.5 release. Please consult the docs (for example, https://uppy.io/docs/instagram/ for the Instagram plugin) and use the updated options.`'); | ||
} | ||
if (opts.companionAllowedHosts) { | ||
const pattern = opts.companionAllowedHosts; // validate companionAllowedHosts param | ||
const pattern = opts.companionAllowedHosts; | ||
// validate companionAllowedHosts param | ||
if (typeof pattern !== 'string' && !Array.isArray(pattern) && !(pattern instanceof RegExp)) { | ||
throw new TypeError(`${plugin.id}: the option "companionAllowedHosts" must be one of string, Array, RegExp`); | ||
} | ||
plugin.opts.companionAllowedHosts = pattern; | ||
@@ -158,7 +180,11 @@ } else if (/^(?!https?:\/\/).*$/i.test(opts.companionUrl)) { | ||
} | ||
plugin.storage = plugin.opts.storage || tokenStorage; | ||
/* eslint-enable no-param-reassign */ | ||
} | ||
} | ||
async function _getAuthToken2() { | ||
return this.uppy.getPlugin(this.pluginId).storage.getItem(this.tokenKey); | ||
} | ||
async function _removeAuthToken2() { | ||
return this.uppy.getPlugin(this.pluginId).storage.removeItem(this.tokenKey); | ||
} |
'use strict'; | ||
let _Symbol$for; | ||
function _classPrivateFieldLooseBase(receiver, privateKey) { if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) { throw new TypeError("attempted to use private field on non-instance"); } return receiver; } | ||
var id = 0; | ||
function _classPrivateFieldLooseKey(name) { return "__private_" + id++ + "_" + name; } | ||
import fetchWithNetworkError from '@uppy/utils/lib/fetchWithNetworkError'; | ||
@@ -15,9 +11,7 @@ import ErrorWithCause from '@uppy/utils/lib/ErrorWithCause'; | ||
const packageJson = { | ||
"version": "3.1.3" | ||
"version": "3.2.0" | ||
}; // Remove the trailing slash so we can always safely append /xyz. | ||
function stripSlash(url) { | ||
return url.replace(/\/$/, ''); | ||
} | ||
async function handleJSONResponse(res) { | ||
@@ -27,11 +21,7 @@ if (res.status === 401) { | ||
} | ||
const jsonPromise = res.json(); | ||
if (res.ok) { | ||
return jsonPromise; | ||
} | ||
let errMsg = `Failed request with status: ${res.status}. ${res.statusText}`; | ||
try { | ||
@@ -41,24 +31,13 @@ const errData = await jsonPromise; | ||
errMsg = errData.requestId ? `${errMsg} request-Id: ${errData.requestId}` : errMsg; | ||
} catch { | ||
/* if the response contains invalid JSON, let's ignore the error */ | ||
} | ||
} catch {/* if the response contains invalid JSON, let's ignore the error */} | ||
throw new Error(errMsg); | ||
} // todo pull out into core instead? | ||
} | ||
// todo pull out into core instead? | ||
const allowedHeadersCache = new Map(); | ||
var _companionHeaders = /*#__PURE__*/_classPrivateFieldLooseKey("companionHeaders"); | ||
var _getUrl = /*#__PURE__*/_classPrivateFieldLooseKey("getUrl"); | ||
var _request = /*#__PURE__*/_classPrivateFieldLooseKey("request"); | ||
_Symbol$for = Symbol.for('uppy test: getCompanionHeaders'); | ||
export default class RequestClient { | ||
constructor(uppy, opts) { | ||
Object.defineProperty(this, _request, { | ||
value: _request2 | ||
}); | ||
Object.defineProperty(this, _getUrl, { | ||
@@ -76,11 +55,8 @@ value: _getUrl2 | ||
} | ||
setCompanionHeaders(headers) { | ||
_classPrivateFieldLooseBase(this, _companionHeaders)[_companionHeaders] = headers; | ||
} | ||
[_Symbol$for]() { | ||
return _classPrivateFieldLooseBase(this, _companionHeaders)[_companionHeaders]; | ||
} | ||
get hostname() { | ||
@@ -93,3 +69,2 @@ const { | ||
} | ||
async headers() { | ||
@@ -101,7 +76,7 @@ const defaultHeaders = { | ||
}; | ||
return { ...defaultHeaders, | ||
return { | ||
...defaultHeaders, | ||
..._classPrivateFieldLooseBase(this, _companionHeaders)[_companionHeaders] | ||
}; | ||
} | ||
onReceiveResponse(_ref) { | ||
@@ -113,7 +88,9 @@ let { | ||
const companion = state.companion || {}; | ||
const host = this.opts.companionUrl; // Store the self-identified domain name for the Companion instance we just hit. | ||
const host = this.opts.companionUrl; | ||
// Store the self-identified domain name for the Companion instance we just hit. | ||
if (headers.has('i-am') && headers.get('i-am') !== companion[host]) { | ||
this.uppy.setState({ | ||
companion: { ...companion, | ||
companion: { | ||
...companion, | ||
[host]: headers.get('i-am') | ||
@@ -124,3 +101,2 @@ } | ||
} | ||
/* | ||
@@ -143,3 +119,2 @@ Preflight was added to avoid breaking change between older Companion-client versions and | ||
const fallbackAllowedHeaders = ['accept', 'content-type', 'uppy-auth-token']; | ||
const promise = (async () => { | ||
@@ -151,3 +126,2 @@ try { | ||
const header = response.headers.get('access-control-allow-headers'); | ||
if (header == null || header === '*') { | ||
@@ -157,3 +131,2 @@ allowedHeadersCache.set(this.hostname, fallbackAllowedHeaders); | ||
} | ||
this.uppy.log(`[CompanionClient] adding allowed preflight headers to companion cache: ${this.hostname} ${header}`); | ||
@@ -164,21 +137,17 @@ const allowedHeaders = header.split(',').map(headerName => headerName.trim().toLowerCase()); | ||
} catch (err) { | ||
this.uppy.log(`[CompanionClient] unable to make preflight request ${err}`, 'warning'); // If the user gets a network error or similar, we should try preflight | ||
this.uppy.log(`[CompanionClient] unable to make preflight request ${err}`, 'warning'); | ||
// If the user gets a network error or similar, we should try preflight | ||
// again next time, or else we might get incorrect behaviour. | ||
allowedHeadersCache.delete(this.hostname); // re-fetch next time | ||
return fallbackAllowedHeaders; | ||
} | ||
})(); | ||
allowedHeadersCache.set(this.hostname, promise); | ||
return promise; | ||
} | ||
async preflightAndHeaders(path) { | ||
const [allowedHeaders, headers] = await Promise.all([this.preflight(path), this.headers()]); // filter to keep only allowed Headers | ||
const [allowedHeaders, headers] = await Promise.all([this.preflight(path), this.headers()]); | ||
// filter to keep only allowed Headers | ||
return Object.fromEntries(Object.entries(headers).filter(_ref2 => { | ||
let [header] = _ref2; | ||
if (!allowedHeaders.includes(header.toLowerCase())) { | ||
@@ -188,3 +157,2 @@ this.uppy.log(`[CompanionClient] excluding disallowed header ${header}`); | ||
} | ||
return true; | ||
@@ -194,2 +162,29 @@ })); | ||
/** @protected */ | ||
async request(_ref3) { | ||
let { | ||
path, | ||
method = 'GET', | ||
data, | ||
skipPostResponse, | ||
signal | ||
} = _ref3; | ||
try { | ||
const headers = await this.preflightAndHeaders(path); | ||
const response = await fetchWithNetworkError(_classPrivateFieldLooseBase(this, _getUrl)[_getUrl](path), { | ||
method, | ||
signal, | ||
headers, | ||
credentials: this.opts.companionCookiesRule || 'same-origin', | ||
body: data ? JSON.stringify(data) : null | ||
}); | ||
if (!skipPostResponse) this.onReceiveResponse(response); | ||
return handleJSONResponse(response); | ||
} catch (err) { | ||
if (err != null && err.isAuthError) throw err; | ||
throw new ErrorWithCause(`Could not ${method} ${_classPrivateFieldLooseBase(this, _getUrl)[_getUrl](path)}`, { | ||
cause: err | ||
}); | ||
} | ||
} | ||
async get(path, options) { | ||
@@ -199,3 +194,2 @@ if (options === void 0) { | ||
} | ||
// TODO: remove boolean support for options that was added for backward compatibility. | ||
@@ -206,7 +200,7 @@ // eslint-disable-next-line no-param-reassign | ||
}; | ||
return _classPrivateFieldLooseBase(this, _request)[_request]({ ...options, | ||
return this.request({ | ||
...options, | ||
path | ||
}); | ||
} | ||
async post(path, data, options) { | ||
@@ -216,3 +210,2 @@ if (options === void 0) { | ||
} | ||
// TODO: remove boolean support for options that was added for backward compatibility. | ||
@@ -223,3 +216,4 @@ // eslint-disable-next-line no-param-reassign | ||
}; | ||
return _classPrivateFieldLooseBase(this, _request)[_request]({ ...options, | ||
return this.request({ | ||
...options, | ||
path, | ||
@@ -230,3 +224,2 @@ method: 'POST', | ||
} | ||
async delete(path, data, options) { | ||
@@ -236,3 +229,2 @@ if (data === void 0) { | ||
} | ||
// TODO: remove boolean support for options that was added for backward compatibility. | ||
@@ -243,3 +235,4 @@ // eslint-disable-next-line no-param-reassign | ||
}; | ||
return _classPrivateFieldLooseBase(this, _request)[_request]({ ...options, | ||
return this.request({ | ||
...options, | ||
path, | ||
@@ -250,5 +243,3 @@ method: 'DELETE', | ||
} | ||
} | ||
function _getUrl2(url) { | ||
@@ -258,34 +249,4 @@ if (/^(https?:|)\/\//.test(url)) { | ||
} | ||
return `${this.hostname}/${url}`; | ||
} | ||
async function _request2(_ref3) { | ||
let { | ||
path, | ||
method = 'GET', | ||
data, | ||
skipPostResponse, | ||
signal | ||
} = _ref3; | ||
try { | ||
const headers = await this.preflightAndHeaders(path); | ||
const response = await fetchWithNetworkError(_classPrivateFieldLooseBase(this, _getUrl)[_getUrl](path), { | ||
method, | ||
signal, | ||
headers, | ||
credentials: this.opts.companionCookiesRule || 'same-origin', | ||
body: data ? JSON.stringify(data) : null | ||
}); | ||
if (!skipPostResponse) this.onReceiveResponse(response); | ||
return handleJSONResponse(response); | ||
} catch (err) { | ||
if (err != null && err.isAuthError) throw err; | ||
throw new ErrorWithCause(`Could not ${method} ${_classPrivateFieldLooseBase(this, _getUrl)[_getUrl](path)}`, { | ||
cause: err | ||
}); | ||
} | ||
} | ||
RequestClient.VERSION = packageJson.version; |
'use strict'; | ||
import RequestClient from './RequestClient.js'; | ||
const getName = id => { | ||
return id.split('-').map(s => s.charAt(0).toUpperCase() + s.slice(1)).join(' '); | ||
}; | ||
export default class SearchProvider extends RequestClient { | ||
@@ -17,11 +15,8 @@ constructor(uppy, opts) { | ||
} | ||
fileUrl(id) { | ||
return `${this.hostname}/search/${this.id}/get/${id}`; | ||
} | ||
search(text, queries) { | ||
return this.get(`search/${this.id}/list?q=${encodeURIComponent(text)}${queries ? `&${queries}` : ''}`); | ||
} | ||
} |
let _Symbol$for, _Symbol$for2; | ||
function _classPrivateFieldLooseBase(receiver, privateKey) { if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) { throw new TypeError("attempted to use private field on non-instance"); } return receiver; } | ||
var id = 0; | ||
function _classPrivateFieldLooseKey(name) { return "__private_" + id++ + "_" + name; } | ||
import ee from 'namespace-emitter'; | ||
var _queued = /*#__PURE__*/_classPrivateFieldLooseKey("queued"); | ||
var _emitter = /*#__PURE__*/_classPrivateFieldLooseKey("emitter"); | ||
var _isOpen = /*#__PURE__*/_classPrivateFieldLooseKey("isOpen"); | ||
var _socket = /*#__PURE__*/_classPrivateFieldLooseKey("socket"); | ||
var _handleMessage = /*#__PURE__*/_classPrivateFieldLooseKey("handleMessage"); | ||
_Symbol$for = Symbol.for('uppy test: getSocket'); | ||
@@ -54,3 +44,2 @@ _Symbol$for2 = Symbol.for('uppy test: getQueued'); | ||
this.opts = opts; | ||
if (!opts || opts.autoOpen !== false) { | ||
@@ -60,29 +49,21 @@ this.open(); | ||
} | ||
get isOpen() { | ||
return _classPrivateFieldLooseBase(this, _isOpen)[_isOpen]; | ||
} | ||
[_Symbol$for]() { | ||
return _classPrivateFieldLooseBase(this, _socket)[_socket]; | ||
} | ||
[_Symbol$for2]() { | ||
return _classPrivateFieldLooseBase(this, _queued)[_queued]; | ||
} | ||
open() { | ||
if (_classPrivateFieldLooseBase(this, _socket)[_socket] != null) return; | ||
_classPrivateFieldLooseBase(this, _socket)[_socket] = new WebSocket(this.opts.target); | ||
_classPrivateFieldLooseBase(this, _socket)[_socket].onopen = () => { | ||
_classPrivateFieldLooseBase(this, _isOpen)[_isOpen] = true; | ||
while (_classPrivateFieldLooseBase(this, _queued)[_queued].length > 0 && _classPrivateFieldLooseBase(this, _isOpen)[_isOpen]) { | ||
const first = _classPrivateFieldLooseBase(this, _queued)[_queued].shift(); | ||
this.send(first.action, first.payload); | ||
} | ||
}; | ||
_classPrivateFieldLooseBase(this, _socket)[_socket].onclose = () => { | ||
@@ -92,14 +73,11 @@ _classPrivateFieldLooseBase(this, _isOpen)[_isOpen] = false; | ||
}; | ||
_classPrivateFieldLooseBase(this, _socket)[_socket].onmessage = _classPrivateFieldLooseBase(this, _handleMessage)[_handleMessage]; | ||
} | ||
close() { | ||
var _classPrivateFieldLoo; | ||
(_classPrivateFieldLoo = _classPrivateFieldLooseBase(this, _socket)[_socket]) == null ? void 0 : _classPrivateFieldLoo.close(); | ||
} | ||
send(action, payload) { | ||
// attach uuid | ||
if (!_classPrivateFieldLooseBase(this, _isOpen)[_isOpen]) { | ||
@@ -110,6 +88,4 @@ _classPrivateFieldLooseBase(this, _queued)[_queued].push({ | ||
}); | ||
return; | ||
} | ||
_classPrivateFieldLooseBase(this, _socket)[_socket].send(JSON.stringify({ | ||
@@ -120,15 +96,11 @@ action, | ||
} | ||
on(action, handler) { | ||
_classPrivateFieldLooseBase(this, _emitter)[_emitter].on(action, handler); | ||
} | ||
emit(action, payload) { | ||
_classPrivateFieldLooseBase(this, _emitter)[_emitter].emit(action, payload); | ||
} | ||
once(action, handler) { | ||
_classPrivateFieldLooseBase(this, _emitter)[_emitter].once(action, handler); | ||
} | ||
} |
'use strict'; | ||
/** | ||
* This module serves as an Async wrapper for LocalStorage | ||
*/ | ||
export function setItem(key, value) { | ||
@@ -7,0 +7,0 @@ return new Promise(resolve => { |
{ | ||
"name": "@uppy/companion-client", | ||
"description": "Client library for communication with Companion. Intended for use in Uppy plugins.", | ||
"version": "3.1.3", | ||
"version": "3.2.0", | ||
"license": "MIT", | ||
@@ -25,3 +25,3 @@ "main": "lib/index.js", | ||
"dependencies": { | ||
"@uppy/utils": "^5.3.0", | ||
"@uppy/utils": "^5.4.0", | ||
"namespace-emitter": "^2.0.1" | ||
@@ -28,0 +28,0 @@ }, |
@@ -11,2 +11,4 @@ 'use strict' | ||
export default class Provider extends RequestClient { | ||
#refreshingTokenPromise | ||
constructor (uppy, opts) { | ||
@@ -24,3 +26,3 @@ super(uppy, opts) | ||
async headers () { | ||
const [headers, token] = await Promise.all([super.headers(), this.getAuthToken()]) | ||
const [headers, token] = await Promise.all([super.headers(), this.#getAuthToken()]) | ||
const authHeaders = {} | ||
@@ -48,10 +50,14 @@ if (token) { | ||
setAuthToken (token) { | ||
async setAuthToken (token) { | ||
return this.uppy.getPlugin(this.pluginId).storage.setItem(this.tokenKey, token) | ||
} | ||
getAuthToken () { | ||
async #getAuthToken () { | ||
return this.uppy.getPlugin(this.pluginId).storage.getItem(this.tokenKey) | ||
} | ||
async #removeAuthToken () { | ||
return this.uppy.getPlugin(this.pluginId).storage.removeItem(this.tokenKey) | ||
} | ||
/** | ||
@@ -80,2 +86,6 @@ * Ensure we have a preauth token if necessary. Attempts to fetch one if we don't, | ||
refreshTokenUrl () { | ||
return `${this.hostname}/${this.id}/refresh-token` | ||
} | ||
fileUrl (id) { | ||
@@ -85,2 +95,32 @@ return `${this.hostname}/${this.id}/get/${id}` | ||
/** @protected */ | ||
async request (...args) { | ||
await this.#refreshingTokenPromise | ||
try { | ||
// throw Object.assign(new Error(), { isAuthError: true }) // testing simulate access token expired (to refresh token) | ||
return await super.request(...args) | ||
} catch (err) { | ||
if (!err.isAuthError) throw err // only handle auth errors (401 from provider) | ||
await this.#refreshingTokenPromise | ||
// Many provider requests may be starting at once, however refresh token should only be called once. | ||
// Once a refresh token operation has started, we need all other request to wait for this operation (atomically) | ||
this.#refreshingTokenPromise = (async () => { | ||
try { | ||
const response = await super.request({ path: this.refreshTokenUrl(), method: 'POST' }) | ||
await this.setAuthToken(response.uppyAuthToken) | ||
} finally { | ||
this.#refreshingTokenPromise = undefined | ||
} | ||
})() | ||
await this.#refreshingTokenPromise | ||
// now retry the request with our new refresh token | ||
return super.request(...args) | ||
} | ||
} | ||
async fetchPreAuthToken () { | ||
@@ -103,8 +143,6 @@ if (!this.companionKeysParams) { | ||
logout () { | ||
return this.get(`${this.id}/logout`) | ||
.then((response) => Promise.all([ | ||
response, | ||
this.uppy.getPlugin(this.pluginId).storage.removeItem(this.tokenKey), | ||
])).then(([response]) => response) | ||
async logout () { | ||
const response = await this.get(`${this.id}/logout`) | ||
await this.#removeAuthToken() | ||
return response | ||
} | ||
@@ -111,0 +149,0 @@ |
@@ -153,3 +153,4 @@ 'use strict' | ||
async #request ({ path, method = 'GET', data, skipPostResponse, signal }) { | ||
/** @protected */ | ||
async request ({ path, method = 'GET', data, skipPostResponse, signal }) { | ||
try { | ||
@@ -176,3 +177,3 @@ const headers = await this.preflightAndHeaders(path) | ||
if (typeof options === 'boolean') options = { skipPostResponse: options } | ||
return this.#request({ ...options, path }) | ||
return this.request({ ...options, path }) | ||
} | ||
@@ -184,3 +185,3 @@ | ||
if (typeof options === 'boolean') options = { skipPostResponse: options } | ||
return this.#request({ ...options, path, method: 'POST', data }) | ||
return this.request({ ...options, path, method: 'POST', data }) | ||
} | ||
@@ -192,4 +193,4 @@ | ||
if (typeof options === 'boolean') options = { skipPostResponse: options } | ||
return this.#request({ ...options, path, method: 'DELETE', data }) | ||
return this.request({ ...options, path, method: 'DELETE', data }) | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
88815
1201
Updated@uppy/utils@^5.4.0