1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-01-20 00:08:02 +01:00
unleash.unleash/src/lib/error/from-legacy-error.ts

123 lines
3.3 KiB
TypeScript
Raw Normal View History

import { fromJoiError } from './bad-data-error';
import { ValidationError as JoiValidationError } from 'joi';
import {
GenericUnleashError,
UnleashApiErrorName,
UnleashApiErrorTypes,
UnleashError,
} from './unleash-error';
refactor: move status codes into classes (#4200) Make each error class have to define its own status code. This makes it easier for developers to see which code an error corresponds to and means less jumping back and forth between files. In other words: improved locality. Unfortunately, the long switch needs to stay in case we get errors thrown that aren't of the Unleash Error type, but we can move it to the `fromLegacyError` file instead. Tradeoff analysis by @kwasniew: + I like the locality of error to code reasoning - now HTTP leaks to the non-HTTP code that throws those errors e.g. application services If we had other delivery mechanisms other than HTTP then it wouldn't make sense to couple error codes to one protocol (HTTP). But since we're mostly doing web it may not be a problem. @thomasheartman's response: This is a good point and something I hadn't considered. The same data was always available on those errors (by using the same property), I've just made the declaration local to each error instead of something that the parent class handles. The idea was to make it easier to create new error classes with their corresponding error codes. Because the errors are intended to be API errors (or at least, I've always considered them to be that), I think that makes sense. Taking your comment into consideration, I still think it's the right thing to do, but I'm not bullish about it. We could always walk it back later if we find that it's not appropriate. The old code is still available and we could easily enough roll back this change if we find that we want to decouple it later.
2023-07-11 09:20:11 +02:00
const getStatusCode = (errorName: string): number => {
switch (errorName) {
case 'ContentTypeError':
return 415;
case 'ValidationError':
return 400;
case 'BadDataError':
return 400;
case 'OwaspValidationError':
return 400;
case 'PasswordUndefinedError':
return 400;
case 'MinimumOneEnvironmentError':
return 400;
case 'InvalidTokenError':
return 401;
case 'UsedTokenError':
return 403;
case 'InvalidOperationError':
return 403;
case 'IncompatibleProjectError':
return 403;
case 'OperationDeniedError':
return 403;
case 'NotFoundError':
return 404;
case 'NameExistsError':
return 409;
case 'FeatureHasTagError':
return 409;
case 'RoleInUseError':
return 400;
case 'ProjectWithoutOwnerError':
return 409;
case 'UnknownError':
return 500;
case 'InternalError':
return 500;
case 'PasswordMismatch':
return 401;
case 'UnauthorizedError':
return 401;
case 'DisabledError':
return 422;
case 'NotImplementedError':
return 405;
case 'NoAccessError':
return 403;
case 'AuthenticationRequired':
return 401;
case 'ForbiddenError':
return 403;
case 'PermissionError':
return 403;
case 'BadRequestError': //thrown by express; do not remove
return 400;
default:
return 500;
}
};
export const fromLegacyError = (e: Error): UnleashError => {
if (e instanceof UnleashError) {
return e;
}
const name = UnleashApiErrorTypes.includes(e.name as UnleashApiErrorName)
? (e.name as UnleashApiErrorName)
: 'UnknownError';
refactor: move status codes into classes (#4200) Make each error class have to define its own status code. This makes it easier for developers to see which code an error corresponds to and means less jumping back and forth between files. In other words: improved locality. Unfortunately, the long switch needs to stay in case we get errors thrown that aren't of the Unleash Error type, but we can move it to the `fromLegacyError` file instead. Tradeoff analysis by @kwasniew: + I like the locality of error to code reasoning - now HTTP leaks to the non-HTTP code that throws those errors e.g. application services If we had other delivery mechanisms other than HTTP then it wouldn't make sense to couple error codes to one protocol (HTTP). But since we're mostly doing web it may not be a problem. @thomasheartman's response: This is a good point and something I hadn't considered. The same data was always available on those errors (by using the same property), I've just made the declaration local to each error instead of something that the parent class handles. The idea was to make it easier to create new error classes with their corresponding error codes. Because the errors are intended to be API errors (or at least, I've always considered them to be that), I think that makes sense. Taking your comment into consideration, I still think it's the right thing to do, but I'm not bullish about it. We could always walk it back later if we find that it's not appropriate. The old code is still available and we could easily enough roll back this change if we find that we want to decouple it later.
2023-07-11 09:20:11 +02:00
const statusCode = getStatusCode(name);
if (name === 'NoAccessError') {
return new GenericUnleashError({
name: 'NoAccessError',
message: e.message,
refactor: move status codes into classes (#4200) Make each error class have to define its own status code. This makes it easier for developers to see which code an error corresponds to and means less jumping back and forth between files. In other words: improved locality. Unfortunately, the long switch needs to stay in case we get errors thrown that aren't of the Unleash Error type, but we can move it to the `fromLegacyError` file instead. Tradeoff analysis by @kwasniew: + I like the locality of error to code reasoning - now HTTP leaks to the non-HTTP code that throws those errors e.g. application services If we had other delivery mechanisms other than HTTP then it wouldn't make sense to couple error codes to one protocol (HTTP). But since we're mostly doing web it may not be a problem. @thomasheartman's response: This is a good point and something I hadn't considered. The same data was always available on those errors (by using the same property), I've just made the declaration local to each error instead of something that the parent class handles. The idea was to make it easier to create new error classes with their corresponding error codes. Because the errors are intended to be API errors (or at least, I've always considered them to be that), I think that makes sense. Taking your comment into consideration, I still think it's the right thing to do, but I'm not bullish about it. We could always walk it back later if we find that it's not appropriate. The old code is still available and we could easily enough roll back this change if we find that we want to decouple it later.
2023-07-11 09:20:11 +02:00
statusCode,
});
}
if (e instanceof JoiValidationError) {
return fromJoiError(e);
}
if (name === 'ValidationError' || name === 'BadDataError') {
return new GenericUnleashError({
name: 'BadDataError',
message: e.message,
refactor: move status codes into classes (#4200) Make each error class have to define its own status code. This makes it easier for developers to see which code an error corresponds to and means less jumping back and forth between files. In other words: improved locality. Unfortunately, the long switch needs to stay in case we get errors thrown that aren't of the Unleash Error type, but we can move it to the `fromLegacyError` file instead. Tradeoff analysis by @kwasniew: + I like the locality of error to code reasoning - now HTTP leaks to the non-HTTP code that throws those errors e.g. application services If we had other delivery mechanisms other than HTTP then it wouldn't make sense to couple error codes to one protocol (HTTP). But since we're mostly doing web it may not be a problem. @thomasheartman's response: This is a good point and something I hadn't considered. The same data was always available on those errors (by using the same property), I've just made the declaration local to each error instead of something that the parent class handles. The idea was to make it easier to create new error classes with their corresponding error codes. Because the errors are intended to be API errors (or at least, I've always considered them to be that), I think that makes sense. Taking your comment into consideration, I still think it's the right thing to do, but I'm not bullish about it. We could always walk it back later if we find that it's not appropriate. The old code is still available and we could easily enough roll back this change if we find that we want to decouple it later.
2023-07-11 09:20:11 +02:00
statusCode,
});
}
if (name === 'OwaspValidationError') {
return new GenericUnleashError({
name: 'OwaspValidationError',
message: e.message,
refactor: move status codes into classes (#4200) Make each error class have to define its own status code. This makes it easier for developers to see which code an error corresponds to and means less jumping back and forth between files. In other words: improved locality. Unfortunately, the long switch needs to stay in case we get errors thrown that aren't of the Unleash Error type, but we can move it to the `fromLegacyError` file instead. Tradeoff analysis by @kwasniew: + I like the locality of error to code reasoning - now HTTP leaks to the non-HTTP code that throws those errors e.g. application services If we had other delivery mechanisms other than HTTP then it wouldn't make sense to couple error codes to one protocol (HTTP). But since we're mostly doing web it may not be a problem. @thomasheartman's response: This is a good point and something I hadn't considered. The same data was always available on those errors (by using the same property), I've just made the declaration local to each error instead of something that the parent class handles. The idea was to make it easier to create new error classes with their corresponding error codes. Because the errors are intended to be API errors (or at least, I've always considered them to be that), I think that makes sense. Taking your comment into consideration, I still think it's the right thing to do, but I'm not bullish about it. We could always walk it back later if we find that it's not appropriate. The old code is still available and we could easily enough roll back this change if we find that we want to decouple it later.
2023-07-11 09:20:11 +02:00
statusCode,
});
}
if (name === 'AuthenticationRequired') {
return new GenericUnleashError({
name: 'AuthenticationRequired',
message: `You must be authenticated to view this content. Please log in.`,
refactor: move status codes into classes (#4200) Make each error class have to define its own status code. This makes it easier for developers to see which code an error corresponds to and means less jumping back and forth between files. In other words: improved locality. Unfortunately, the long switch needs to stay in case we get errors thrown that aren't of the Unleash Error type, but we can move it to the `fromLegacyError` file instead. Tradeoff analysis by @kwasniew: + I like the locality of error to code reasoning - now HTTP leaks to the non-HTTP code that throws those errors e.g. application services If we had other delivery mechanisms other than HTTP then it wouldn't make sense to couple error codes to one protocol (HTTP). But since we're mostly doing web it may not be a problem. @thomasheartman's response: This is a good point and something I hadn't considered. The same data was always available on those errors (by using the same property), I've just made the declaration local to each error instead of something that the parent class handles. The idea was to make it easier to create new error classes with their corresponding error codes. Because the errors are intended to be API errors (or at least, I've always considered them to be that), I think that makes sense. Taking your comment into consideration, I still think it's the right thing to do, but I'm not bullish about it. We could always walk it back later if we find that it's not appropriate. The old code is still available and we could easily enough roll back this change if we find that we want to decouple it later.
2023-07-11 09:20:11 +02:00
statusCode,
});
}
return new GenericUnleashError({
name: name as UnleashApiErrorName,
message: e.message,
refactor: move status codes into classes (#4200) Make each error class have to define its own status code. This makes it easier for developers to see which code an error corresponds to and means less jumping back and forth between files. In other words: improved locality. Unfortunately, the long switch needs to stay in case we get errors thrown that aren't of the Unleash Error type, but we can move it to the `fromLegacyError` file instead. Tradeoff analysis by @kwasniew: + I like the locality of error to code reasoning - now HTTP leaks to the non-HTTP code that throws those errors e.g. application services If we had other delivery mechanisms other than HTTP then it wouldn't make sense to couple error codes to one protocol (HTTP). But since we're mostly doing web it may not be a problem. @thomasheartman's response: This is a good point and something I hadn't considered. The same data was always available on those errors (by using the same property), I've just made the declaration local to each error instead of something that the parent class handles. The idea was to make it easier to create new error classes with their corresponding error codes. Because the errors are intended to be API errors (or at least, I've always considered them to be that), I think that makes sense. Taking your comment into consideration, I still think it's the right thing to do, but I'm not bullish about it. We could always walk it back later if we find that it's not appropriate. The old code is still available and we could easily enough roll back this change if we find that we want to decouple it later.
2023-07-11 09:20:11 +02:00
statusCode,
});
};