import { createExtractOptionsFn, isObject, BaseError, isBaseError } from 'ebec';

function isOptions(input) {
    if (!isObject(input)) {
        return false;
    }
    if (typeof input.statusCode !== 'undefined' && typeof input.statusCode !== 'number' && typeof input.statusCode !== 'string') {
        return false;
    }
    if (typeof input.statusMessage !== 'undefined' && typeof input.statusMessage !== 'string') {
        return false;
    }
    return typeof input.redirectURL === 'undefined' || typeof input.redirectURL === 'string';
}
const check = createExtractOptionsFn(isOptions);
function extractOptions(...input) {
    return check(...input);
}

/**
 * \x20-\x7E: This range represents printable ASCII characters. \x20 is the hexadecimal code for space, and \x7E is the code for tilde.
 * \t: Matches the tab character.
 * \n: Matches the newline character.
 * \r: Matches the carriage return character.
 * \x0B: Matches the vertical tab character.
 * \x0C: Matches the form feed character.
 */ // eslint-disable-next-line no-control-regex
const pattern = /[^\x20-\x7E\t\n\r\x0B\x0C]+/g;
function sanitizeStatusMessage(input) {
    return input.replace(pattern, '');
}
function sanitizeStatusCode(input) {
    const code = parseInt(`${input}`, 10);
    if (!Number.isInteger(code) || code < 100 || code > 599) {
        return 500;
    }
    return code;
}

class HTTPError extends BaseError {
    constructor(...input){
        super(...input);
        const options = extractOptions(...input);
        this.statusCode = options.statusCode ? sanitizeStatusCode(options.statusCode) : 500;
        this.statusMessage = options.statusMessage ? sanitizeStatusMessage(options.statusMessage) : undefined;
        this.redirectURL = options.redirectURL;
    }
}
function isHTTPError(error) {
    if (!isOptions(error)) {
        return false;
    }
    if (typeof error.statusCode !== 'number' || error.statusCode < 400 || error.statusCode > 599) {
        return false;
    }
    return isBaseError(error);
}

class ClientError extends HTTPError {
    constructor(...input){
        super({
            expose: true
        }, ...input);
    }
}
function isClientError(input) {
    if (!isHTTPError(input)) {
        return false;
    }
    return input.statusCode >= 400 && input.statusCode < 500;
}

class ServerError extends HTTPError {
    constructor(...input){
        super({
            expose: false
        }, ...input);
    }
}
function isServerError(error) {
    if (!isHTTPError(error)) {
        return false;
    }
    return error.statusCode >= 500 && error.statusCode < 600;
}

const BadRequestErrorOptions = {
    code: `BAD_REQUEST`,
    statusCode: 400,
    statusMessage: `Bad Request`
};
class BadRequestError extends ClientError {
    constructor(...input){
        super(BadRequestErrorOptions, ...input);
    }
}

const UnauthorizedErrorOptions = {
    code: `UNAUTHORIZED`,
    statusCode: 401,
    statusMessage: `Unauthorized`
};
class UnauthorizedError extends ClientError {
    constructor(...input){
        super(UnauthorizedErrorOptions, ...input);
    }
}

const ForbiddenErrorOptions = {
    code: `FORBIDDEN`,
    statusCode: 403,
    statusMessage: `Forbidden`
};
class ForbiddenError extends ClientError {
    constructor(...input){
        super(ForbiddenErrorOptions, ...input);
    }
}

const NotFoundErrorOptions = {
    code: `NOT_FOUND`,
    statusCode: 404,
    statusMessage: `Not Found`
};
class NotFoundError extends ClientError {
    constructor(...input){
        super(NotFoundErrorOptions, ...input);
    }
}

const MethodNotAllowedErrorOptions = {
    code: `METHOD_NOT_ALLOWED`,
    statusCode: 405,
    statusMessage: `Method Not Allowed`
};
class MethodNotAllowedError extends ClientError {
    constructor(...input){
        super(MethodNotAllowedErrorOptions, ...input);
    }
}

const NotAcceptableErrorOptions = {
    code: `NOT_ACCEPTABLE`,
    statusCode: 406,
    statusMessage: `Not Acceptable`
};
class NotAcceptableError extends ClientError {
    constructor(...input){
        super(NotAcceptableErrorOptions, ...input);
    }
}

const ProxyAuthenticationRequiredErrorOptions = {
    code: `PROXY_AUTHENTICATION_REQUIRED`,
    statusCode: 407,
    statusMessage: `Proxy Authentication Required`
};
class ProxyAuthenticationRequiredError extends ClientError {
    constructor(...input){
        super(ProxyAuthenticationRequiredErrorOptions, ...input);
    }
}

const RequestTimeoutErrorOptions = {
    code: `REQUEST_TIMEOUT`,
    statusCode: 408,
    statusMessage: `Request Timeout`
};
class RequestTimeoutError extends ClientError {
    constructor(...input){
        super(RequestTimeoutErrorOptions, ...input);
    }
}

const ConflictErrorOptions = {
    code: `CONFLICT`,
    statusCode: 409,
    statusMessage: `Conflict`
};
class ConflictError extends ClientError {
    constructor(...input){
        super(ConflictErrorOptions, ...input);
    }
}

const GoneErrorOptions = {
    code: `GONE`,
    statusCode: 410,
    statusMessage: `Gone`
};
class GoneError extends ClientError {
    constructor(...input){
        super(GoneErrorOptions, ...input);
    }
}

const LengthRequiredErrorOptions = {
    code: `LENGTH_REQUIRED`,
    statusCode: 411,
    statusMessage: `Length Required`
};
class LengthRequiredError extends ClientError {
    constructor(...input){
        super(LengthRequiredErrorOptions, ...input);
    }
}

const PreconditionFailedErrorOptions = {
    code: `PRECONDITION_FAILED`,
    statusCode: 412,
    statusMessage: `Precondition Failed`
};
class PreconditionFailedError extends ClientError {
    constructor(...input){
        super(PreconditionFailedErrorOptions, ...input);
    }
}

const RequestEntityTooLargeErrorOptions = {
    code: `REQUEST_ENTITY_TOO_LARGE`,
    statusCode: 413,
    statusMessage: `REQUEST_ENTITY_TOO_LARGE`
};
class RequestEntityTooLargeError extends ClientError {
    constructor(...input){
        super(RequestEntityTooLargeErrorOptions, ...input);
    }
}

const RequestURITooLongErrorOptions = {
    code: `REQUEST_URI_TOO_LONG`,
    statusCode: 414,
    statusMessage: `Request-URI Too Long`
};
class RequestURITooLongError extends ClientError {
    constructor(...input){
        super(RequestURITooLongErrorOptions, ...input);
    }
}

const UnsupportedMediaTypeErrorOptions = {
    code: `UNSUPPORTED_MEDIA_TYPE`,
    statusCode: 415,
    statusMessage: `Unsupported Media Type`
};
class UnsupportedMediaTypeError extends ClientError {
    constructor(...input){
        super(UnsupportedMediaTypeErrorOptions, ...input);
    }
}

const RequestedRangeNotSatisfiableErrorOptions = {
    code: `REQUESTED_RANGE_NOT_SATISFIABLE`,
    statusCode: 416,
    statusMessage: `Requested Range Not Satisfiable`
};
class RequestedRangeNotSatisfiableError extends ClientError {
    constructor(...input){
        super(RequestedRangeNotSatisfiableErrorOptions, ...input);
    }
}

const ExpectationFailedErrorOptions = {
    code: `EXPECTATION_FAILED`,
    statusCode: 417,
    statusMessage: `Expectation Failed`
};
class ExpectationFailedError extends ClientError {
    constructor(...input){
        super(ExpectationFailedErrorOptions, ...input);
    }
}

const ImATeapotErrorOptions = {
    code: `IM_A_TEAPOT`,
    statusCode: 418,
    statusMessage: `I&#39;m a Teapot`
};
class ImATeapotError extends ClientError {
    constructor(...input){
        super(ImATeapotErrorOptions, ...input);
    }
}

const EnhanceYourCalmErrorOptions = {
    code: `ENHANCE_YOUR_CALM`,
    statusCode: 420,
    statusMessage: `Enhance Your Calm`
};
class EnhanceYourCalmError extends ClientError {
    constructor(...input){
        super(EnhanceYourCalmErrorOptions, ...input);
    }
}

const UnprocessableEntityErrorOptions = {
    code: `UNPROCESSABLE_ENTITY`,
    statusCode: 422,
    statusMessage: `Unprocessable Entity`
};
class UnprocessableEntityError extends ClientError {
    constructor(...input){
        super(UnprocessableEntityErrorOptions, ...input);
    }
}

const LockedErrorOptions = {
    code: `LOCKED`,
    statusCode: 423,
    statusMessage: `Locked`
};
class LockedError extends ClientError {
    constructor(...input){
        super(LockedErrorOptions, ...input);
    }
}

const FailedDependencyErrorOptions = {
    code: `FAILED_DEPENDENCY`,
    statusCode: 424,
    statusMessage: `Failed Dependency`
};
class FailedDependencyError extends ClientError {
    constructor(...input){
        super(FailedDependencyErrorOptions, ...input);
    }
}

const UnorderedCollectionErrorOptions = {
    code: `UNORDERED_COLLECTION`,
    statusCode: 425,
    statusMessage: `Unordered Collection`
};
class UnorderedCollectionError extends ClientError {
    constructor(...input){
        super(UnorderedCollectionErrorOptions, ...input);
    }
}

const UpgradeRequiredErrorOptions = {
    code: `UPGRADE_REQUIRED`,
    statusCode: 426,
    statusMessage: `Upgrade Required`
};
class UpgradeRequiredError extends ClientError {
    constructor(...input){
        super(UpgradeRequiredErrorOptions, ...input);
    }
}

const PreconditionRequiredErrorOptions = {
    code: `PRECONDITION_REQUIRED`,
    statusCode: 428,
    statusMessage: `Precondition Required`
};
class PreconditionRequiredError extends ClientError {
    constructor(...input){
        super(PreconditionRequiredErrorOptions, ...input);
    }
}

const TooManyRequestsErrorOptions = {
    code: `TOO_MANY_REQUESTS`,
    statusCode: 429,
    statusMessage: `Too Many Requests`
};
class TooManyRequestsError extends ClientError {
    constructor(...input){
        super(TooManyRequestsErrorOptions, ...input);
    }
}

const RequestHeaderFieldsTooLargeErrorOptions = {
    code: `REQUEST_HEADER_FIELDS_TOO_LARGE`,
    statusCode: 431,
    statusMessage: `Request Header Fields Too Large`
};
class RequestHeaderFieldsTooLargeError extends ClientError {
    constructor(...input){
        super(RequestHeaderFieldsTooLargeErrorOptions, ...input);
    }
}

const NoResponseErrorOptions = {
    code: `NO_RESPONSE`,
    statusCode: 444,
    statusMessage: `No Response`
};
class NoResponseError extends ClientError {
    constructor(...input){
        super(NoResponseErrorOptions, ...input);
    }
}

const RetryWithErrorOptions = {
    code: `RETRY_WITH`,
    statusCode: 449,
    statusMessage: `Retry With`
};
class RetryWithError extends ClientError {
    constructor(...input){
        super(RetryWithErrorOptions, ...input);
    }
}

const BlockedByWindowsParentalControlsErrorOptions = {
    code: `BLOCKED_BY_WINDOWS_PARENTAL_CONTROLS`,
    statusCode: 450,
    statusMessage: `Blocked By Windows Parental Controls`
};
class BlockedByWindowsParentalControlsError extends ClientError {
    constructor(...input){
        super(BlockedByWindowsParentalControlsErrorOptions, ...input);
    }
}

const ClientClosedRequestErrorOptions = {
    code: `CLIENT_CLOSED_REQUEST`,
    statusCode: 499,
    statusMessage: `Client Closed Request`
};
class ClientClosedRequestError extends ClientError {
    constructor(...input){
        super(ClientClosedRequestErrorOptions, ...input);
    }
}

const InternalServerErrorOptions = {
    code: `INTERNAL_SERVER_ERROR`,
    statusCode: 500,
    statusMessage: `Internal Server Error`
};
class InternalServerError extends ServerError {
    constructor(...input){
        super(InternalServerErrorOptions, ...input);
    }
}

const NotImplementedErrorOptions = {
    code: `NOT_IMPLEMENTED`,
    statusCode: 501,
    statusMessage: `Not Implemented`
};
class NotImplementedError extends ServerError {
    constructor(...input){
        super(NotImplementedErrorOptions, ...input);
    }
}

const BadGatewayErrorOptions = {
    code: `BAD_GATEWAY`,
    statusCode: 502,
    statusMessage: `Bad Gateway`
};
class BadGatewayError extends ServerError {
    constructor(...input){
        super(BadGatewayErrorOptions, ...input);
    }
}

const ServiceUnavailableErrorOptions = {
    code: `SERVICE_UNAVAILABLE`,
    statusCode: 503,
    statusMessage: `Service Unavailable`
};
class ServiceUnavailableError extends ServerError {
    constructor(...input){
        super(ServiceUnavailableErrorOptions, ...input);
    }
}

const GatewayTimeoutErrorOptions = {
    code: `GATEWAY_TIMEOUT`,
    statusCode: 504,
    statusMessage: `Gateway Timeout`
};
class GatewayTimeoutError extends ServerError {
    constructor(...input){
        super(GatewayTimeoutErrorOptions, ...input);
    }
}

const HTTPVersionNotSupportedErrorOptions = {
    code: `HTTP_VERSION_NOT_SUPPORTED`,
    statusCode: 505,
    statusMessage: `HTTP Version Not Supported`
};
class HTTPVersionNotSupportedError extends ServerError {
    constructor(...input){
        super(HTTPVersionNotSupportedErrorOptions, ...input);
    }
}

const VariantAlsoNegotiatesErrorOptions = {
    code: `VARIANT_ALSO_NEGOTIATES`,
    statusCode: 506,
    statusMessage: `Variant Also Negotiates`
};
class VariantAlsoNegotiatesError extends ServerError {
    constructor(...input){
        super(VariantAlsoNegotiatesErrorOptions, ...input);
    }
}

const InsufficientStorageErrorOptions = {
    code: `INSUFFICIENT_STORAGE`,
    statusCode: 507,
    statusMessage: `Insufficient Storage`
};
class InsufficientStorageError extends ServerError {
    constructor(...input){
        super(InsufficientStorageErrorOptions, ...input);
    }
}

const LoopDetectedErrorOptions = {
    code: `LOOP_DETECTED`,
    statusCode: 508,
    statusMessage: `Loop Detected`
};
class LoopDetectedError extends ServerError {
    constructor(...input){
        super(LoopDetectedErrorOptions, ...input);
    }
}

const BandwidthLimitExceededErrorOptions = {
    code: `BANDWIDTH_LIMIT_EXCEEDED`,
    statusCode: 509,
    statusMessage: `Bandwidth Limit Exceeded`
};
class BandwidthLimitExceededError extends ServerError {
    constructor(...input){
        super(BandwidthLimitExceededErrorOptions, ...input);
    }
}

const NotExtendedErrorOptions = {
    code: `NOT_EXTENDED`,
    statusCode: 510,
    statusMessage: `Not Extended`
};
class NotExtendedError extends ServerError {
    constructor(...input){
        super(NotExtendedErrorOptions, ...input);
    }
}

const NetworkAuthenticationRequiredErrorOptions = {
    code: `NETWORK_AUTHENTICATION_REQUIRED`,
    statusCode: 511,
    statusMessage: `Network Authentication Required`
};
class NetworkAuthenticationRequiredError extends ServerError {
    constructor(...input){
        super(NetworkAuthenticationRequiredErrorOptions, ...input);
    }
}

export { BadGatewayError, BadGatewayErrorOptions, BadRequestError, BadRequestErrorOptions, BandwidthLimitExceededError, BandwidthLimitExceededErrorOptions, BlockedByWindowsParentalControlsError, BlockedByWindowsParentalControlsErrorOptions, ClientClosedRequestError, ClientClosedRequestErrorOptions, ClientError, ConflictError, ConflictErrorOptions, EnhanceYourCalmError, EnhanceYourCalmErrorOptions, ExpectationFailedError, ExpectationFailedErrorOptions, FailedDependencyError, FailedDependencyErrorOptions, ForbiddenError, ForbiddenErrorOptions, GatewayTimeoutError, GatewayTimeoutErrorOptions, GoneError, GoneErrorOptions, HTTPError, HTTPVersionNotSupportedError, HTTPVersionNotSupportedErrorOptions, ImATeapotError, ImATeapotErrorOptions, InsufficientStorageError, InsufficientStorageErrorOptions, InternalServerError, InternalServerErrorOptions, LengthRequiredError, LengthRequiredErrorOptions, LockedError, LockedErrorOptions, LoopDetectedError, LoopDetectedErrorOptions, MethodNotAllowedError, MethodNotAllowedErrorOptions, NetworkAuthenticationRequiredError, NetworkAuthenticationRequiredErrorOptions, NoResponseError, NoResponseErrorOptions, NotAcceptableError, NotAcceptableErrorOptions, NotExtendedError, NotExtendedErrorOptions, NotFoundError, NotFoundErrorOptions, NotImplementedError, NotImplementedErrorOptions, PreconditionFailedError, PreconditionFailedErrorOptions, PreconditionRequiredError, PreconditionRequiredErrorOptions, ProxyAuthenticationRequiredError, ProxyAuthenticationRequiredErrorOptions, RequestEntityTooLargeError, RequestEntityTooLargeErrorOptions, RequestHeaderFieldsTooLargeError, RequestHeaderFieldsTooLargeErrorOptions, RequestTimeoutError, RequestTimeoutErrorOptions, RequestURITooLongError, RequestURITooLongErrorOptions, RequestedRangeNotSatisfiableError, RequestedRangeNotSatisfiableErrorOptions, RetryWithError, RetryWithErrorOptions, ServerError, ServiceUnavailableError, ServiceUnavailableErrorOptions, TooManyRequestsError, TooManyRequestsErrorOptions, UnauthorizedError, UnauthorizedErrorOptions, UnorderedCollectionError, UnorderedCollectionErrorOptions, UnprocessableEntityError, UnprocessableEntityErrorOptions, UnsupportedMediaTypeError, UnsupportedMediaTypeErrorOptions, UpgradeRequiredError, UpgradeRequiredErrorOptions, VariantAlsoNegotiatesError, VariantAlsoNegotiatesErrorOptions, extractOptions, isClientError, isHTTPError, isOptions, isServerError, sanitizeStatusCode, sanitizeStatusMessage };
//# sourceMappingURL=index.mjs.map
