@aws-amplify/datastore
Version:
AppSyncLocal support for aws-amplify
95 lines (82 loc) • 2.9 kB
text/typescript
import { ErrorType } from '../../types';
export type ErrorMap = Partial<{
[key in ErrorType]: (error: Error) => boolean;
}>;
const connectionTimeout = error =>
/^Connection failed: Connection Timeout/.test(error.message);
const serverError = error =>
/^Error: Request failed with status code 5\d\d/.test(error.message);
export const mutationErrorMap: ErrorMap = {
BadModel: () => false,
BadRecord: error => {
const { message } = error;
return (
/^Cannot return \w+ for [\w-_]+ type/.test(message) ||
/^Variable '.+' has coerced Null value for NonNull type/.test(message)
); // newly required field, out of date client
},
ConfigError: () => false,
Transient: error => connectionTimeout(error) || serverError(error),
Unauthorized: error =>
error.message === 'Unauthorized' ||
/^Request failed with status code 401/.test(error.message),
};
export const subscriptionErrorMap: ErrorMap = {
BadModel: () => false,
BadRecord: () => false,
ConfigError: () => false,
Transient: observableError => {
const error = unwrapObservableError(observableError);
return connectionTimeout(error) || serverError(error);
},
Unauthorized: observableError => {
const error = unwrapObservableError(observableError);
return /Connection failed.+Unauthorized/.test(error.message);
},
};
export const syncErrorMap: ErrorMap = {
BadModel: () => false,
BadRecord: error => /^Cannot return \w+ for [\w-_]+ type/.test(error.message),
ConfigError: () => false,
Transient: error => connectionTimeout(error) || serverError(error),
Unauthorized: error => (error as any).errorType === 'Unauthorized',
};
/**
* Get the first error reason of an observable.
* Allows for error maps to be easily applied to observable errors
*
* @param observableError an error from ZenObservable subscribe error callback
*/
function unwrapObservableError(observableError: any) {
const {
error: { errors: [error] } = {
errors: [],
},
} = observableError;
return error;
}
export function getMutationErrorType(error: Error): ErrorType {
return mapErrorToType(mutationErrorMap, error);
}
export function getSubscriptionErrorType(error: Error): ErrorType {
return mapErrorToType(subscriptionErrorMap, error);
}
export function getSyncErrorType(error: Error): ErrorType {
return mapErrorToType(syncErrorMap, error);
}
/**
* Categorizes an error with a broad error type, intended to make
* customer error handling code simpler.
* @param errorMap Error names and a list of patterns that indicate them (each pattern as a regex or function)
* @param error The underying error to categorize.
*/
export function mapErrorToType(errorMap: ErrorMap, error: Error): ErrorType {
const errorTypes = [...Object.keys(errorMap)] as ErrorType[];
for (const errorType of errorTypes) {
const matcher = errorMap[errorType];
if (matcher?.(error)) {
return errorType;
}
}
return 'Unknown';
}