Socket
Socket
Sign inDemoInstall

@uppy/companion-client

Package Overview
Dependencies
Maintainers
6
Versions
88
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@uppy/companion-client - npm Package Compare versions

Comparing version 3.6.1 to 3.7.0

7

CHANGELOG.md
# @uppy/companion-client
## 3.7.0
Released: 2023-12-12
Included in: Uppy v3.21.0
- @uppy/companion-client: avoid unnecessary preflight requests (Antoine du Hamel / #4462)
## 3.6.1

@@ -4,0 +11,0 @@

3

lib/AuthError.js

@@ -7,2 +7,5 @@ 'use strict';

this.name = 'AuthError';
// we use a property because of instanceof is unsafe:
// https://github.com/transloadit/uppy/pull/4619#discussion_r1406225982
this.isAuthError = true;

@@ -9,0 +12,0 @@ }

@@ -6,3 +6,3 @@ 'use strict';

function _classPrivateFieldLooseKey(name) { return "__private_" + id++ + "_" + name; }
import RequestClient from './RequestClient.js';
import RequestClient, { authErrorStatusCode } from './RequestClient.js';
import * as tokenStorage from './tokenStorage.js';

@@ -31,9 +31,6 @@ const getName = id => {

var _getAuthToken = /*#__PURE__*/_classPrivateFieldLooseKey("getAuthToken");
var _removeAuthToken = /*#__PURE__*/_classPrivateFieldLooseKey("removeAuthToken");
export default class Provider extends RequestClient {
constructor(uppy, opts) {
var _opts$supportsRefresh;
super(uppy, opts);
Object.defineProperty(this, _removeAuthToken, {
value: _removeAuthToken2
});
Object.defineProperty(this, _getAuthToken, {

@@ -53,3 +50,5 @@ value: _getAuthToken2

this.preAuthToken = null;
this.supportsRefreshToken = (_opts$supportsRefresh = opts.supportsRefreshToken) != null ? _opts$supportsRefresh : true; // todo false in next major
}
async headers() {

@@ -75,3 +74,3 @@ const [headers, token] = await Promise.all([super.headers(), _classPrivateFieldLooseBase(this, _getAuthToken)[_getAuthToken]()]);

const oldAuthenticated = plugin.getPluginState().authenticated;
const authenticated = oldAuthenticated ? response.status !== 401 : response.status < 400;
const authenticated = oldAuthenticated ? response.status !== authErrorStatusCode : response.status < 400;
plugin.setPluginState({

@@ -85,2 +84,7 @@ authenticated

}
/** @protected */
async removeAuthToken() {
return this.uppy.getPlugin(this.pluginId).storage.removeItem(this.tokenKey);
}
/**

@@ -98,11 +102,20 @@ * Ensure we have a preauth token if necessary. Attempts to fetch one if we don't,

}
authUrl(queries) {
if (queries === void 0) {
queries = {};
}
// eslint-disable-next-line class-methods-use-this
authQuery() {
return {};
}
authUrl(_temp) {
let {
authFormData,
query
} = _temp === void 0 ? {} : _temp;
const params = new URLSearchParams({
...query,
state: btoa(JSON.stringify({
origin: getOrigin()
})),
...queries
...this.authQuery({
authFormData
})
});

@@ -114,7 +127,39 @@ if (this.preAuthToken) {

}
async login(queries) {
/** @protected */
async loginSimpleAuth(_ref) {
let {
uppyVersions,
authFormData,
signal
} = _ref;
const response = await this.post(`${this.id}/simple-auth`, {
form: authFormData
}, {
qs: {
uppyVersions
},
signal
});
this.setAuthToken(response.uppyAuthToken);
}
/** @protected */
async loginOAuth(_ref2) {
let {
uppyVersions,
authFormData,
signal
} = _ref2;
await this.ensurePreAuth();
signal.throwIfAborted();
return new Promise((resolve, reject) => {
const link = this.authUrl(queries);
const link = this.authUrl({
query: {
uppyVersions
},
authFormData
});
const authWindow = window.open(link, '_blank');
let cleanup;
const handleToken = e => {

@@ -161,9 +206,26 @@ if (e.source !== authWindow) {

}
cleanup();
resolve(this.setAuthToken(data.token));
};
cleanup = () => {
authWindow.close();
window.removeEventListener('message', handleToken);
this.setAuthToken(data.token).then(() => resolve()).catch(reject);
signal.removeEventListener('abort', cleanup);
};
signal.addEventListener('abort', cleanup);
window.addEventListener('message', handleToken);
});
}
async login(_ref3) {
let {
uppyVersions,
authFormData,
signal
} = _ref3;
return this.loginOAuth({
uppyVersions,
authFormData,
signal
});
}
refreshTokenUrl() {

@@ -188,2 +250,3 @@ return `${this.hostname}/${this.id}/refresh-token`;

} catch (err) {
if (!this.supportsRefreshToken) throw err;
// only handle auth errors (401 from provider), and only handle them if we have a (refresh) token

@@ -206,3 +269,3 @@ const authTokenAfter = await _classPrivateFieldLooseBase(this, _getAuthToken)[_getAuthToken]();

// if refresh-token has failed with auth error, delete token, so we don't keep trying to refresh in future
await _classPrivateFieldLooseBase(this, _removeAuthToken)[_removeAuthToken]();
await this.removeAuthToken();
}

@@ -239,3 +302,3 @@ throw err;

const response = await this.get(`${this.id}/logout`, options);
await _classPrivateFieldLooseBase(this, _removeAuthToken)[_removeAuthToken]();
await this.removeAuthToken();
return response;

@@ -275,5 +338,2 @@ }

return this.uppy.getPlugin(this.pluginId).storage.getItem(this.tokenKey);
}
async function _removeAuthToken2() {
return this.uppy.getPlugin(this.pluginId).storage.removeItem(this.tokenKey);
}

114

lib/RequestClient.js
'use strict';
// eslint-disable-next-line import/no-extraneous-dependencies
let _Symbol$for;

@@ -8,2 +7,4 @@ function _classPrivateFieldLooseBase(receiver, privateKey) { if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) { throw new TypeError("attempted to use private field on non-instance"); } return receiver; }

function _classPrivateFieldLooseKey(name) { return "__private_" + id++ + "_" + name; }
import UserFacingApiError from '@uppy/utils/lib/UserFacingApiError';
// eslint-disable-next-line import/no-extraneous-dependencies
import pRetry, { AbortError } from 'p-retry';

@@ -16,3 +17,3 @@ import fetchWithNetworkError from '@uppy/utils/lib/fetchWithNetworkError';

const packageJson = {
"version": "3.6.1"
"version": "3.7.0"
}; // Remove the trailing slash so we can always safely append /xyz.

@@ -25,3 +26,3 @@ function stripSlash(url) {

const authErrorStatusCode = 401;
export const authErrorStatusCode = 401;
class HttpError extends Error {

@@ -35,2 +36,3 @@ constructor(_ref) {

this.statusCode = void 0;
this.name = 'HttpError';
this.statusCode = statusCode;

@@ -47,9 +49,16 @@ }

let errMsg = `Failed request with status: ${res.status}. ${res.statusText}`;
let errData;
try {
const errData = await res.json();
errMsg = errData.message ? `${errMsg} message: ${errData.message}` : errMsg;
errMsg = errData.requestId ? `${errMsg} request-Id: ${errData.requestId}` : errMsg;
} catch {
/* if the response contains invalid JSON, let's ignore the error */
errData = await res.json();
if (errData.message) errMsg = `${errMsg} message: ${errData.message}`;
if (errData.requestId) errMsg = `${errMsg} request-Id: ${errData.requestId}`;
} catch (cause) {
// if the response contains invalid JSON, let's ignore the error data
throw new Error(errMsg, {
cause
});
}
if (res.status >= 400 && res.status <= 499 && errData.message) {
throw new UserFacingApiError(errData.message);
}
throw new HttpError({

@@ -60,5 +69,2 @@ statusCode: res.status,

}
// todo pull out into core instead?
const allowedHeadersCache = new Map();
var _companionHeaders = /*#__PURE__*/_classPrivateFieldLooseKey("companionHeaders");

@@ -124,7 +130,12 @@ var _getUrl = /*#__PURE__*/_classPrivateFieldLooseKey("getUrl");

}
async headers() {
async headers(emptyBody) {
if (emptyBody === void 0) {
emptyBody = false;
}
const defaultHeaders = {
Accept: 'application/json',
'Content-Type': 'application/json',
'Uppy-Versions': `@uppy/companion-client=${RequestClient.VERSION}`
...(emptyBody ? undefined : {
// Passing those headers on requests with no data forces browsers to first make a preflight request.
'Content-Type': 'application/json'
})
};

@@ -154,59 +165,4 @@ return {

}
/*
Preflight was added to avoid breaking change between older Companion-client versions and
newer Companion versions and vice-versa. Usually the break will manifest via CORS errors because a
version of companion-client could be sending certain headers to a version of Companion server that
does not support those headers. In which case, the default preflight would lead to CORS.
So to avoid those errors, we do preflight ourselves, to see what headers the Companion server
we are communicating with allows. And based on that, companion-client knows what headers to
send and what headers to not send.
The preflight only happens once throughout the life-cycle of a certain
Companion-client <-> Companion-server pair (allowedHeadersCache).
Subsequent requests use the cached result of the preflight.
However if there is an error retrieving the allowed headers, we will try again next time
*/
async preflight(path) {
const allowedHeadersCached = allowedHeadersCache.get(this.hostname);
if (allowedHeadersCached != null) return allowedHeadersCached;
const fallbackAllowedHeaders = ['accept', 'content-type', 'uppy-auth-token'];
const promise = (async () => {
try {
const response = await fetch(_classPrivateFieldLooseBase(this, _getUrl)[_getUrl](path), {
method: 'OPTIONS'
});
const header = response.headers.get('access-control-allow-headers');
if (header == null || header === '*') {
allowedHeadersCache.set(this.hostname, fallbackAllowedHeaders);
return fallbackAllowedHeaders;
}
this.uppy.log(`[CompanionClient] adding allowed preflight headers to companion cache: ${this.hostname} ${header}`);
const allowedHeaders = header.split(',').map(headerName => headerName.trim().toLowerCase());
allowedHeadersCache.set(this.hostname, allowedHeaders);
return allowedHeaders;
} 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
// 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
return Object.fromEntries(Object.entries(headers).filter(_ref4 => {
let [header] = _ref4;
if (!allowedHeaders.includes(header.toLowerCase())) {
this.uppy.log(`[CompanionClient] excluding disallowed header ${header}`);
return false;
}
return true;
}));
}
/** @protected */
async request(_ref5) {
async request(_ref4) {
let {

@@ -218,5 +174,5 @@ path,

signal
} = _ref5;
} = _ref4;
try {
const headers = await this.preflightAndHeaders(path);
const headers = await this.headers(!data);
const response = await fetchWithNetworkError(_classPrivateFieldLooseBase(this, _getUrl)[_getUrl](path), {

@@ -233,3 +189,3 @@ method,

// pass these through
if (err instanceof AuthError || err.name === 'AbortError') throw err;
if (err.isAuthError || err.name === 'UserFacingApiError' || err.name === 'AbortError') throw err;
throw new ErrorWithCause(`Could not ${method} ${_classPrivateFieldLooseBase(this, _getUrl)[_getUrl](path)}`, {

@@ -327,7 +283,7 @@ cause: err

// throwing AbortError will cause p-retry to stop retrying
if (outerErr instanceof AuthError) throw new AbortError(outerErr);
if (outerErr.isAuthError) throw new AbortError(outerErr);
if (outerErr.cause == null) throw outerErr;
const err = outerErr.cause;
const isRetryableHttpError = () => [408, 409, 429, 418, 423].includes(err.statusCode) || err.statusCode >= 500 && err.statusCode <= 599 && ![501, 505].includes(err.statusCode);
if (err instanceof HttpError && !isRetryableHttpError()) throw new AbortError(err);
if (err.name === 'HttpError' && !isRetryableHttpError()) throw new AbortError(err);

@@ -380,3 +336,3 @@ // p-retry will retry most other errors,

}
async function _awaitRemoteFileUpload2(_ref6) {
async function _awaitRemoteFileUpload2(_ref5) {
let {

@@ -386,3 +342,3 @@ file,

signal
} = _ref6;
} = _ref5;
let removeEventHandlers;

@@ -543,7 +499,7 @@ const {

};
const onCancelAll = _ref7 => {
const onCancelAll = _ref6 => {
var _socketAbortControlle5;
let {
reason
} = _ref7;
} = _ref6;
if (reason === 'user') {

@@ -550,0 +506,0 @@ socketSend('cancel');

{
"name": "@uppy/companion-client",
"description": "Client library for communication with Companion. Intended for use in Uppy plugins.",
"version": "3.6.1",
"version": "3.7.0",
"license": "MIT",

@@ -25,3 +25,3 @@ "main": "lib/index.js",

"dependencies": {
"@uppy/utils": "^5.6.0",
"@uppy/utils": "^5.7.0",
"namespace-emitter": "^2.0.1",

@@ -28,0 +28,0 @@ "p-retry": "^6.1.0"

'use strict'
class AuthError extends Error {
constructor () {
constructor() {
super('Authorization required')
this.name = 'AuthError'
// we use a property because of instanceof is unsafe:
// https://github.com/transloadit/uppy/pull/4619#discussion_r1406225982
this.isAuthError = true

@@ -8,0 +11,0 @@ }

'use strict'
import RequestClient from './RequestClient.js'
import RequestClient, { authErrorStatusCode } from './RequestClient.js'
import * as tokenStorage from './tokenStorage.js'
const getName = (id) => {

@@ -10,3 +11,3 @@ return id.split('-').map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join(' ')

function getOrigin () {
function getOrigin() {
// eslint-disable-next-line no-restricted-globals

@@ -16,3 +17,3 @@ return location.origin

function getRegex (value) {
function getRegex(value) {
if (typeof value === 'string') {

@@ -26,3 +27,3 @@ return new RegExp(`^${value}$`)

function isOriginAllowed (origin, allowedOrigin) {
function isOriginAllowed(origin, allowedOrigin) {
const patterns = Array.isArray(allowedOrigin) ? allowedOrigin.map(getRegex) : [getRegex(allowedOrigin)]

@@ -36,3 +37,3 @@ return patterns

constructor (uppy, opts) {
constructor(uppy, opts) {
super(uppy, opts)

@@ -46,5 +47,6 @@ this.provider = opts.provider

this.preAuthToken = null
this.supportsRefreshToken = opts.supportsRefreshToken ?? true // todo false in next major
}
async headers () {
async headers() {
const [headers, token] = await Promise.all([super.headers(), this.#getAuthToken()])

@@ -64,7 +66,7 @@ const authHeaders = {}

onReceiveResponse (response) {
onReceiveResponse(response) {
super.onReceiveResponse(response)
const plugin = this.uppy.getPlugin(this.pluginId)
const oldAuthenticated = plugin.getPluginState().authenticated
const authenticated = oldAuthenticated ? response.status !== 401 : response.status < 400
const authenticated = oldAuthenticated ? response.status !== authErrorStatusCode : response.status < 400
plugin.setPluginState({ authenticated })

@@ -74,11 +76,12 @@ return response

async setAuthToken (token) {
async setAuthToken(token) {
return this.uppy.getPlugin(this.pluginId).storage.setItem(this.tokenKey, token)
}
async #getAuthToken () {
async #getAuthToken() {
return this.uppy.getPlugin(this.pluginId).storage.getItem(this.tokenKey)
}
async #removeAuthToken () {
/** @protected */
async removeAuthToken() {
return this.uppy.getPlugin(this.pluginId).storage.removeItem(this.tokenKey)

@@ -91,3 +94,3 @@ }

*/
async ensurePreAuth () {
async ensurePreAuth() {
if (this.companionKeysParams && !this.preAuthToken) {

@@ -102,7 +105,14 @@ await this.fetchPreAuthToken()

authUrl (queries = {}) {
// eslint-disable-next-line class-methods-use-this
authQuery() {
return {}
}
authUrl({ authFormData, query } = {}) {
const params = new URLSearchParams({
...query,
state: btoa(JSON.stringify({ origin: getOrigin() })),
...queries,
...this.authQuery({ authFormData }),
})
if (this.preAuthToken) {

@@ -115,8 +125,20 @@ params.set('uppyPreAuthToken', this.preAuthToken)

async login (queries) {
/** @protected */
async loginSimpleAuth({ uppyVersions, authFormData, signal }) {
const response = await this.post(`${this.id}/simple-auth`, { form: authFormData }, { qs: { uppyVersions }, signal })
this.setAuthToken(response.uppyAuthToken)
}
/** @protected */
async loginOAuth({ uppyVersions, authFormData, signal }) {
await this.ensurePreAuth()
signal.throwIfAborted()
return new Promise((resolve, reject) => {
const link = this.authUrl(queries)
const link = this.authUrl({ query: { uppyVersions }, authFormData })
const authWindow = window.open(link, '_blank')
let cleanup
const handleToken = (e) => {

@@ -161,6 +183,13 @@ if (e.source !== authWindow) {

cleanup()
resolve(this.setAuthToken(data.token))
}
cleanup = () => {
authWindow.close()
window.removeEventListener('message', handleToken)
this.setAuthToken(data.token).then(() => resolve()).catch(reject)
signal.removeEventListener('abort', cleanup)
}
signal.addEventListener('abort', cleanup)
window.addEventListener('message', handleToken)

@@ -170,7 +199,11 @@ })

refreshTokenUrl () {
async login({ uppyVersions, authFormData, signal }) {
return this.loginOAuth({ uppyVersions, authFormData, signal })
}
refreshTokenUrl() {
return `${this.hostname}/${this.id}/refresh-token`
}
fileUrl (id) {
fileUrl(id) {
return `${this.hostname}/${this.id}/get/${id}`

@@ -180,3 +213,3 @@ }

/** @protected */
async request (...args) {
async request(...args) {
await this.#refreshingTokenPromise

@@ -193,2 +226,3 @@

} catch (err) {
if (!this.supportsRefreshToken) throw err
// only handle auth errors (401 from provider), and only handle them if we have a (refresh) token

@@ -209,3 +243,3 @@ const authTokenAfter = await this.#getAuthToken()

// if refresh-token has failed with auth error, delete token, so we don't keep trying to refresh in future
await this.#removeAuthToken()
await this.removeAuthToken()
}

@@ -226,3 +260,3 @@ throw err

async fetchPreAuthToken () {
async fetchPreAuthToken() {
if (!this.companionKeysParams) {

@@ -240,13 +274,13 @@ return

list (directory, options) {
list(directory, options) {
return this.get(`${this.id}/list/${directory || ''}`, options)
}
async logout (options) {
async logout(options) {
const response = await this.get(`${this.id}/logout`, options)
await this.#removeAuthToken()
await this.removeAuthToken()
return response
}
static initPlugin (plugin, opts, defaultOpts) {
static initPlugin(plugin, opts, defaultOpts) {
/* eslint-disable no-param-reassign */

@@ -253,0 +287,0 @@ plugin.type = 'acquirer'

'use strict'
import UserFacingApiError from '@uppy/utils/lib/UserFacingApiError'
// eslint-disable-next-line import/no-extraneous-dependencies

@@ -16,3 +17,3 @@ import pRetry, { AbortError } from 'p-retry'

// Remove the trailing slash so we can always safely append /xyz.
function stripSlash (url) {
function stripSlash(url) {
return url.replace(/\/$/, '')

@@ -24,3 +25,3 @@ }

const authErrorStatusCode = 401
export const authErrorStatusCode = 401

@@ -32,2 +33,3 @@ class HttpError extends Error {

super(message)
this.name = 'HttpError'
this.statusCode = statusCode

@@ -37,3 +39,3 @@ }

async function handleJSONResponse (res) {
async function handleJSONResponse(res) {
if (res.status === authErrorStatusCode) {

@@ -48,19 +50,20 @@ throw new AuthError()

let errMsg = `Failed request with status: ${res.status}. ${res.statusText}`
let errData
try {
const errData = await res.json()
errData = await res.json()
errMsg = errData.message ? `${errMsg} message: ${errData.message}` : errMsg
errMsg = errData.requestId
? `${errMsg} request-Id: ${errData.requestId}`
: errMsg
} catch {
/* if the response contains invalid JSON, let's ignore the error */
if (errData.message) errMsg = `${errMsg} message: ${errData.message}`
if (errData.requestId) errMsg = `${errMsg} request-Id: ${errData.requestId}`
} catch (cause) {
// if the response contains invalid JSON, let's ignore the error data
throw new Error(errMsg, { cause })
}
if (res.status >= 400 && res.status <= 499 && errData.message) {
throw new UserFacingApiError(errData.message)
}
throw new HttpError({ statusCode: res.status, message: errMsg })
}
// todo pull out into core instead?
const allowedHeadersCache = new Map()
export default class RequestClient {

@@ -71,3 +74,3 @@ static VERSION = packageJson.version

constructor (uppy, opts) {
constructor(uppy, opts) {
this.uppy = uppy

@@ -79,11 +82,11 @@ this.opts = opts

setCompanionHeaders (headers) {
setCompanionHeaders(headers) {
this.#companionHeaders = headers
}
[Symbol.for('uppy test: getCompanionHeaders')] () {
[Symbol.for('uppy test: getCompanionHeaders')]() {
return this.#companionHeaders
}
get hostname () {
get hostname() {
const { companion } = this.uppy.getState()

@@ -94,7 +97,9 @@ const host = this.opts.companionUrl

async headers () {
async headers (emptyBody = false) {
const defaultHeaders = {
Accept: 'application/json',
'Content-Type': 'application/json',
'Uppy-Versions': `@uppy/companion-client=${RequestClient.VERSION}`,
...(emptyBody ? undefined : {
// Passing those headers on requests with no data forces browsers to first make a preflight request.
'Content-Type': 'application/json',
}),
}

@@ -108,3 +113,3 @@

onReceiveResponse ({ headers }) {
onReceiveResponse({ headers }) {
const state = this.uppy.getState()

@@ -122,3 +127,3 @@ const companion = state.companion || {}

#getUrl (url) {
#getUrl(url) {
if (/^(https?:|)\/\//.test(url)) {

@@ -130,84 +135,6 @@ return url

/*
Preflight was added to avoid breaking change between older Companion-client versions and
newer Companion versions and vice-versa. Usually the break will manifest via CORS errors because a
version of companion-client could be sending certain headers to a version of Companion server that
does not support those headers. In which case, the default preflight would lead to CORS.
So to avoid those errors, we do preflight ourselves, to see what headers the Companion server
we are communicating with allows. And based on that, companion-client knows what headers to
send and what headers to not send.
The preflight only happens once throughout the life-cycle of a certain
Companion-client <-> Companion-server pair (allowedHeadersCache).
Subsequent requests use the cached result of the preflight.
However if there is an error retrieving the allowed headers, we will try again next time
*/
async preflight (path) {
const allowedHeadersCached = allowedHeadersCache.get(this.hostname)
if (allowedHeadersCached != null) return allowedHeadersCached
const fallbackAllowedHeaders = [
'accept',
'content-type',
'uppy-auth-token',
]
const promise = (async () => {
try {
const response = await fetch(this.#getUrl(path), { method: 'OPTIONS' })
const header = response.headers.get('access-control-allow-headers')
if (header == null || header === '*') {
allowedHeadersCache.set(this.hostname, fallbackAllowedHeaders)
return fallbackAllowedHeaders
}
this.uppy.log(
`[CompanionClient] adding allowed preflight headers to companion cache: ${this.hostname} ${header}`,
)
const allowedHeaders = header
.split(',')
.map((headerName) => headerName.trim().toLowerCase())
allowedHeadersCache.set(this.hostname, allowedHeaders)
return allowedHeaders
} 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
// 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
return Object.fromEntries(
Object.entries(headers).filter(([header]) => {
if (!allowedHeaders.includes(header.toLowerCase())) {
this.uppy.log(
`[CompanionClient] excluding disallowed header ${header}`,
)
return false
}
return true
}),
)
}
/** @protected */
async request ({ path, method = 'GET', data, skipPostResponse, signal }) {
async request({ path, method = 'GET', data, skipPostResponse, signal }) {
try {
const headers = await this.preflightAndHeaders(path)
const headers = await this.headers(!data)
const response = await fetchWithNetworkError(this.#getUrl(path), {

@@ -225,3 +152,3 @@ method,

// pass these through
if (err instanceof AuthError || err.name === 'AbortError') throw err
if (err.isAuthError || err.name === 'UserFacingApiError' || err.name === 'AbortError') throw err

@@ -234,3 +161,3 @@ throw new ErrorWithCause(`Could not ${method} ${this.#getUrl(path)}`, {

async get (path, options = undefined) {
async get(path, options = undefined) {
// TODO: remove boolean support for options that was added for backward compatibility.

@@ -242,3 +169,3 @@ // eslint-disable-next-line no-param-reassign

async post (path, data, options = undefined) {
async post(path, data, options = undefined) {
// TODO: remove boolean support for options that was added for backward compatibility.

@@ -250,3 +177,3 @@ // eslint-disable-next-line no-param-reassign

async delete (path, data = undefined, options) {
async delete(path, data = undefined, options) {
// TODO: remove boolean support for options that was added for backward compatibility.

@@ -271,3 +198,3 @@ // eslint-disable-next-line no-param-reassign

*/
async uploadRemoteFile (file, reqBody, options = {}) {
async uploadRemoteFile(file, reqBody, options = {}) {
try {

@@ -289,3 +216,3 @@ const { signal, getQueue } = options

// throwing AbortError will cause p-retry to stop retrying
if (outerErr instanceof AuthError) throw new AbortError(outerErr)
if (outerErr.isAuthError) throw new AbortError(outerErr)

@@ -299,4 +226,4 @@ if (outerErr.cause == null) throw outerErr

)
if (err instanceof HttpError && !isRetryableHttpError()) throw new AbortError(err);
if (err.name === 'HttpError' && !isRetryableHttpError()) throw new AbortError(err);
// p-retry will retry most other errors,

@@ -353,3 +280,3 @@ // but it will not retry TypeError (except network error TypeErrors)

*/
async #awaitRemoteFileUpload ({ file, queue, signal }) {
async #awaitRemoteFileUpload({ file, queue, signal }) {
let removeEventHandlers

@@ -381,3 +308,3 @@

payload: payload ?? {},
}))
}))
};

@@ -402,3 +329,3 @@

}
// todo instead implement the ability for users to cancel / retry *currently uploading files* in the UI

@@ -438,3 +365,3 @@ function resetActivityTimeout() {

const { action, payload } = JSON.parse(e.data)
switch (action) {

@@ -455,4 +382,4 @@ case 'progress': {

}
default:
this.uppy.log(`Companion socket unknown action ${action}`, 'warning')
default:
this.uppy.log(`Companion socket unknown action ${action}`, 'warning')
}

@@ -470,3 +397,3 @@ } catch (err) {

}
socketAbortController.signal.addEventListener('abort', () => {

@@ -473,0 +400,0 @@ closeSocket()

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

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc