@uppy/companion
Version:
OAuth helper and remote fetcher for Uppy's (https://uppy.io) extensible file upload widget with support for drag&drop, resumable uploads, previews, restrictions, file processing/encoding, remote providers like Dropbox and Google Drive, S3 and more :dog:
66 lines (65 loc) • 2.39 kB
JavaScript
import * as logger from '../logger.js';
import { ProviderApiError, ProviderAuthError, ProviderUserError, parseHttpError, } from './error.js';
export { parseHttpError };
/**
*
* @param {{
* fn: () => any,
* tag: string,
* providerName: string,
* isAuthError?: (a: { statusCode: number, body?: object }) => boolean,
* isUserFacingError?: (a: { statusCode: number, body?: object }) => boolean,
* getJsonErrorMessage: (a: object) => string
* }} param0
* @returns
*/
export async function withProviderErrorHandling({ fn, tag, providerName, isAuthError = () => false, isUserFacingError = () => false, getJsonErrorMessage, }) {
function getErrorMessage({ statusCode, body }) {
if (typeof body === 'object') {
const message = getJsonErrorMessage(body);
if (message != null)
return message;
}
if (typeof body === 'string') {
return body;
}
return `request to ${providerName} returned ${statusCode}`;
}
try {
return await fn();
}
catch (err) {
const httpError = parseHttpError(err);
// Wrap all HTTP errors according to the provider's desired error handling
if (httpError) {
const { statusCode, body } = httpError;
let knownErr;
if (isAuthError({ statusCode, body })) {
knownErr = new ProviderAuthError();
}
else if (isUserFacingError({ statusCode, body })) {
knownErr = new ProviderUserError({
message: getErrorMessage({ statusCode, body }),
});
}
else {
knownErr = new ProviderApiError(getErrorMessage({ statusCode, body }), statusCode);
}
logger.error(knownErr, tag);
throw knownErr;
}
// non HTTP errors will be passed through
logger.error(err, tag);
throw err;
}
}
export async function withGoogleErrorHandling(providerName, tag, fn) {
return withProviderErrorHandling({
fn,
tag,
providerName,
isAuthError: (response) => response.statusCode === 401 ||
(response.statusCode === 400 && response.body?.error === 'invalid_grant'), // Refresh token has expired or been revoked
getJsonErrorMessage: (body) => body?.error?.message,
});
}