diff --git a/httperr/httperr-tests.ts b/httperr/httperr-tests.ts new file mode 100644 index 000000000..131ec4dab --- /dev/null +++ b/httperr/httperr-tests.ts @@ -0,0 +1,90 @@ +/// +import httperr = require('httperr'); + + +// ---------------------------------------- +// Basic usage example from: https://github.com/pluma/httperr/blob/1.0.0/README.md +var err = httperr[404]('The path "/example" could not be resolved'); +console.log(err); +/* +{ [NotFound: The path "/example" could not be resolved] + title: 'Not Found', + name: 'NotFound', + code: 'NOT_FOUND', + statusCode: 404, + message: 'The path "/example" could not be resolved' +} +*/ +throw err; +/* +NotFound: The path "/example" could not be resolved + at ... +*/ + +console.log(httperr.methodNotAllowed({allowed: ['GET', 'POST']})); +/* +{ [MethodNotAllowed] + title: 'Method Not Allowed', + name: 'MethodNotAllowed', + code: 'METHOD_NOT_ALLOWED', + statusCode: 405, + message: '', + allowed: ['GET', 'POST'] +} +*/ + +err = new httperr.NotFound(); +console.log(err); +/* +{ [NotFound] + title: 'Not Found', + name: 'NotFound', + code: 'NOT_FOUND', + statusCode: 404, + message: 'The path "/example" could not be resolved' +} +*/ + +console.log(err instanceof httperr.NotFound); // true +console.log(err instanceof httperr.notFound); // true +console.log(err instanceof httperr['404']); // true +console.log(err instanceof httperr.MethodNotAllowed); // false +console.log(err instanceof httperr.HttpError); // true +console.log(err instanceof Error); // true + + +// ---------------------------------------- +// Advanced usage: creating custom Error subclasses +var Custom404Error = httperr.createHttpError(404, 'Not Found', config => { + this.message = 'The resource was not found'; + this['some custom property'] = config.parameters['some custom parameter']; +}); +err = new Custom404Error(); + +var Custom500Error = httperr.createHttpError(500, 'Something went wrong'); +err = new Custom500Error(); + + +// ---------------------------------------- +// Advanced usage: returning a JSON serializable representation of an error +var err = httperr.notFound('File Not Found'); +console.log(err.toObject()); +/* +{ + name: 'NotFound', + code: 'NOT_FOUND', + title: 'Not Found', + statusCode: 404, + message: 'File Not Found', + stack: '…' +} +*/ +console.log(err.toObject('stack', /^title$/)); +/* +{ + name: 'NotFound', + code: 'NOT_FOUND', + statusCode: 404, + message: 'File Not Found' +} +*/ diff --git a/httperr/httperr.d.ts b/httperr/httperr.d.ts new file mode 100644 index 000000000..0bc54a650 --- /dev/null +++ b/httperr/httperr.d.ts @@ -0,0 +1,292 @@ +// Type definitions for httperr v1.0.0 +// Project: https://github.com/pluma/httperr +// Definitions by: Troy Gerwien +// Definitions: https://github.com/borisyankov/DefinitelyTyped + +declare module "httperr" { + + /** Overall module shape, expressed as an interface. */ + interface HttpErr { + + /** The base type for all httperr error types. You probably don't want to use this directly. */ + HttpError: HttpErrorStatic; + + /** + * Creates a new error type for the given HTTP error status. + * @param {number} status - The HTTP response status code for the HTTP error. + * @param {string} title - A human-readable title for the HTTP error. + * @param {Function} init - (optional) A function which will be invoked as a method of the + * new error with the config argument immediately after the error + * is created by the factory. Can be used to process additional + * error-specific configuration parameters. + */ + createHttpError(status: number, title: string, init?: (config: Config) => void): HttpErrorStatic; + + // Error builders by camel-cased name. + badRequest: ErrorBuilder; + unauthorized: ErrorBuilder; + paymentRequired: ErrorBuilder; + forbidden: ErrorBuilder; + notFound: ErrorBuilder; + methodNotAllowed: ErrorBuilder; + notAcceptable: ErrorBuilder; + proxyAuthenticationRequired: ErrorBuilder; + requestTimeout: ErrorBuilder; + conflict: ErrorBuilder; + gone: ErrorBuilder; + lengthRequired: ErrorBuilder; + preconditionFailed: ErrorBuilder; + requestEntityTooLarge: ErrorBuilder; + requestUriTooLong: ErrorBuilder; + unsupportedMediaType: ErrorBuilder; + requestedRangeNotSatisfiable: ErrorBuilder; + expectationFailed: ErrorBuilder; + imATeapot: ErrorBuilder; + authenticationTimeout: ErrorBuilder; + enhanceYourCalm: ErrorBuilder; + unprocessableEntity: ErrorBuilder; + locked: ErrorBuilder; + methodFailure: ErrorBuilder; + failedDependency: ErrorBuilder; + unorderedCollection: ErrorBuilder; + upgradeRequired: ErrorBuilder; + preconditionRequired: ErrorBuilder; + tooManyRequests: ErrorBuilder; + requestHeaderFieldsTooLarge: ErrorBuilder; + loginTimeout: ErrorBuilder; + noResponse: ErrorBuilder; + retryWith: ErrorBuilder; + blockedByWindowsParentalControls: ErrorBuilder; + redirect: ErrorBuilder; + unavailableForLegalReasons: ErrorBuilder; + requestHeaderTooLarge: ErrorBuilder; + certError: ErrorBuilder; + noCert: ErrorBuilder; + httpToHttps: ErrorBuilder; + clientClosedRequest: ErrorBuilder; + internalServerError: ErrorBuilder; + notImplemented: ErrorBuilder; + badGateway: ErrorBuilder; + serviceUnavailable: ErrorBuilder; + gatewayTimeout: ErrorBuilder; + httpVersionNotSupported: ErrorBuilder; + variantAlsoNegotiates: ErrorBuilder; + insufficientStorage: ErrorBuilder; + loopDetected: ErrorBuilder; + bandwidthLimitExceeded: ErrorBuilder; + notExtended: ErrorBuilder; + networkAuthenticationRequired: ErrorBuilder; + originError: ErrorBuilder; + connectionTimedOut: ErrorBuilder; + proxyDeclinedRequest: ErrorBuilder; + aTimeoutOccured: ErrorBuilder; + networkReadTimeoutError: ErrorBuilder; + networkConnectTimeoutError: ErrorBuilder; + + // Error builders by title-cased name. + BadRequest: ErrorBuilder; + Unauthorized: ErrorBuilder; + PaymentRequired: ErrorBuilder; + Forbidden: ErrorBuilder; + NotFound: ErrorBuilder; + MethodNotAllowed: ErrorBuilder; + NotAcceptable: ErrorBuilder; + ProxyAuthenticationRequired: ErrorBuilder; + RequestTimeout: ErrorBuilder; + Conflict: ErrorBuilder; + Gone: ErrorBuilder; + LengthRequired: ErrorBuilder; + PreconditionFailed: ErrorBuilder; + RequestEntityTooLarge: ErrorBuilder; + RequestUriTooLong: ErrorBuilder; + UnsupportedMediaType: ErrorBuilder; + RequestedRangeNotSatisfiable: ErrorBuilder; + ExpectationFailed: ErrorBuilder; + ImATeapot: ErrorBuilder; + AuthenticationTimeout: ErrorBuilder; + EnhanceYourCalm: ErrorBuilder; + UnprocessableEntity: ErrorBuilder; + Locked: ErrorBuilder; + MethodFailure: ErrorBuilder; + FailedDependency: ErrorBuilder; + UnorderedCollection: ErrorBuilder; + UpgradeRequired: ErrorBuilder; + PreconditionRequired: ErrorBuilder; + TooManyRequests: ErrorBuilder; + RequestHeaderFieldsTooLarge: ErrorBuilder; + LoginTimeout: ErrorBuilder; + NoResponse: ErrorBuilder; + RetryWith: ErrorBuilder; + BlockedByWindowsParentalControls: ErrorBuilder; + Redirect: ErrorBuilder; + UnavailableForLegalReasons: ErrorBuilder; + RequestHeaderTooLarge: ErrorBuilder; + CertError: ErrorBuilder; + NoCert: ErrorBuilder; + HttpToHttps: ErrorBuilder; + ClientClosedRequest: ErrorBuilder; + InternalServerError: ErrorBuilder; + NotImplemented: ErrorBuilder; + BadGateway: ErrorBuilder; + ServiceUnavailable: ErrorBuilder; + GatewayTimeout: ErrorBuilder; + HttpVersionNotSupported: ErrorBuilder; + VariantAlsoNegotiates: ErrorBuilder; + InsufficientStorage: ErrorBuilder; + LoopDetected: ErrorBuilder; + BandwidthLimitExceeded: ErrorBuilder; + NotExtended: ErrorBuilder; + NetworkAuthenticationRequired: ErrorBuilder; + OriginError: ErrorBuilder; + ConnectionTimedOut: ErrorBuilder; + ProxyDeclinedRequest: ErrorBuilder; + ATimeoutOccured: ErrorBuilder; + NetworkReadTimeoutError: ErrorBuilder; + NetworkConnectTimeoutError: ErrorBuilder; + + // Error builders by statusCode. + 400: ErrorBuilder; + 401: ErrorBuilder; + 402: ErrorBuilder; + 403: ErrorBuilder; + 404: ErrorBuilder; + 405: ErrorBuilder; + 406: ErrorBuilder; + 407: ErrorBuilder; + 408: ErrorBuilder; + 409: ErrorBuilder; + 410: ErrorBuilder; + 411: ErrorBuilder; + 412: ErrorBuilder; + 413: ErrorBuilder; + 414: ErrorBuilder; + 415: ErrorBuilder; + 416: ErrorBuilder; + 417: ErrorBuilder; + 418: ErrorBuilder; + 419: ErrorBuilder; + 420: ErrorBuilder; + 422: ErrorBuilder; + 423: ErrorBuilder; + 424: ErrorBuilder; + 425: ErrorBuilder; + 426: ErrorBuilder; + 428: ErrorBuilder; + 429: ErrorBuilder; + 431: ErrorBuilder; + 440: ErrorBuilder; + 444: ErrorBuilder; + 449: ErrorBuilder; + 450: ErrorBuilder; + 451: ErrorBuilder; + 494: ErrorBuilder; + 495: ErrorBuilder; + 496: ErrorBuilder; + 497: ErrorBuilder; + 499: ErrorBuilder; + 500: ErrorBuilder; + 501: ErrorBuilder; + 502: ErrorBuilder; + 503: ErrorBuilder; + 504: ErrorBuilder; + 505: ErrorBuilder; + 506: ErrorBuilder; + 507: ErrorBuilder; + 508: ErrorBuilder; + 509: ErrorBuilder; + 510: ErrorBuilder; + 511: ErrorBuilder; + 520: ErrorBuilder; + 522: ErrorBuilder; + 523: ErrorBuilder; + 524: ErrorBuilder; + 598: ErrorBuilder; + 599: ErrorBuilder; + } + + /** Constructor function for the HttpError class. */ + interface HttpErrorStatic { + new(config?: string | Error | Config, extra?: {}): HttpError; + } + + + /** An instance of the HttpError class. */ + interface HttpError extends Error { + + /** A human-readable title for the HTTP error. */ + title: string; + + code: string; + + /** The HTTP response status code for the HTTP error. */ + statusCode: number; + + toObject(...skip: (string|RegExp)[]): any; + } + + + /** Configuration object for constructing HttpErrors. */ + interface Config { + + /** A descriptive human-readable title describing the error's cause. */ + message?: string; + + /** The underlying exception that caused the HTTP error. */ + cause?: Error; + + /** A detailed human-readable description of the error's cause and possible solutions. */ + details?: string; + + /** + * The methods allowed for this URL. + * This property is only available for 405 Method Not Allowed errors + * and can be used to populate the Allow header. + */ + allowed?: string[]; + + /** + * The minimum delay before the request should be attempted again. + * This property is only available for 429 Too Many Requests and 420 Enhance Your Calm + * (Twitter API) errors and can be used to populate the Retry-After header. + */ + retryAfter?: any; + + /** + * The parameters with which the request should be retried. + * This property is only available for 449 Retry With (Microsoft) errors and can be + * used to populate the response status message. + */ + parameters?: any; + + /** + * The location for which the request should be repeated. + * This property is only available for 451 Redirect (Microsoft) errors and can be + * used to populate the proprietary X-MS-Location response header. + */ + location?: any; + } + + + /** Factory function for creating an Error object. */ + interface ErrorBuilder { + + /** + * Creates an Error object. The new keyword is optional. + * @param {string | Error | Config} config - If config is a string, it will be treated as config.message. + * If config is an Error object, it will be treated as config.cause. + */ + (config?: string | Error | Config): HttpError; + + /** + * Creates an Error object. The new keyword is optional. + * @param {string | Error | Config} config - If config is a string, it will be treated as config.message. + * If config is an Error object, it will be treated as config.cause. + */ + new (config?: string | Error | Config): HttpError; + } + + + // The module value satisfies the HttpErr interface. + var _: HttpErr; + export = _; +}