From 3562fe02fe231065acdc5993ed83273559b336a7 Mon Sep 17 00:00:00 2001 From: electrovir Date: Mon, 6 Jan 2025 23:33:45 +0000 Subject: [PATCH] [minor] add errorHttpStatusCategories,ErrorHttpStatusCategories,SuccessHttpStatusCategories,isErrorHttpStatus,HttpStatusToCategory,httpStatusToCategory --- package-lock.json | 48 +++---- package.json | 2 +- packages/assert/package.json | 4 +- packages/common/package.json | 6 +- packages/core/package.json | 2 +- .../src/augments/http/http-status.test.ts | 53 +++++++ .../core/src/augments/http/http-status.ts | 135 +++++++++++++++++- packages/node/package.json | 8 +- packages/scripts/package.json | 10 +- packages/test/package.json | 6 +- packages/web/package.json | 8 +- 11 files changed, 234 insertions(+), 48 deletions(-) create mode 100644 packages/core/src/augments/http/http-status.test.ts diff --git a/package-lock.json b/package-lock.json index 89f0e6829..e57e9bb59 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@augment-vir/mono-repo-root", - "version": "31.5.0", + "version": "31.6.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@augment-vir/mono-repo-root", - "version": "31.5.0", + "version": "31.6.0", "hasInstallScript": true, "license": "(MIT or CC0 1.0)", "workspaces": [ @@ -16312,10 +16312,10 @@ }, "packages/assert": { "name": "@augment-vir/assert", - "version": "31.5.0", + "version": "31.6.0", "license": "(MIT or CC0 1.0)", "dependencies": { - "@augment-vir/core": "^31.5.0", + "@augment-vir/core": "^31.6.0", "@date-vir/duration": "^7.1.1", "deep-eql": "^5.0.2", "expect-type": "^1.1.0", @@ -16350,11 +16350,11 @@ }, "packages/common": { "name": "@augment-vir/common", - "version": "31.5.0", + "version": "31.6.0", "license": "(MIT or CC0 1.0)", "dependencies": { - "@augment-vir/assert": "^31.5.0", - "@augment-vir/core": "^31.5.0", + "@augment-vir/assert": "^31.6.0", + "@augment-vir/core": "^31.6.0", "@date-vir/duration": "^7.1.1", "ansi-styles": "^6.2.1", "json5": "^2.2.3", @@ -16390,7 +16390,7 @@ }, "packages/core": { "name": "@augment-vir/core", - "version": "31.5.0", + "version": "31.6.0", "license": "(MIT or CC0 1.0)", "dependencies": { "@date-vir/duration": "^7.1.1", @@ -16422,11 +16422,11 @@ }, "packages/node": { "name": "@augment-vir/node", - "version": "31.5.0", + "version": "31.6.0", "license": "(MIT or CC0 1.0)", "dependencies": { - "@augment-vir/assert": "^31.5.0", - "@augment-vir/common": "^31.5.0", + "@augment-vir/assert": "^31.6.0", + "@augment-vir/common": "^31.6.0", "@date-vir/duration": "^7.1.1", "ansi-styles": "^6.2.1", "terminate": "^2.8.0", @@ -16434,7 +16434,7 @@ "typed-event-target": "^4.0.2" }, "devDependencies": { - "@augment-vir/test": "^31.5.0", + "@augment-vir/test": "^31.6.0", "@prisma/client": "^6.1.0", "@types/node": "^22.10.5", "@web/dev-server-esbuild": "^1.0.3", @@ -16469,18 +16469,18 @@ }, "packages/scripts": { "name": "@augment-vir/scripts", - "version": "31.5.0", + "version": "31.6.0", "license": "(MIT or CC0 1.0)", "dependencies": { - "@augment-vir/assert": "^31.5.0", - "@augment-vir/common": "^31.5.0", - "@augment-vir/node": "^31.5.0", + "@augment-vir/assert": "^31.6.0", + "@augment-vir/common": "^31.6.0", + "@augment-vir/node": "^31.6.0", "@virmator/docs": "^13.11.1", "jsdom": "^25.0.1", "typedoc": "^0.27.6" }, "devDependencies": { - "@augment-vir/test": "^31.5.0", + "@augment-vir/test": "^31.6.0", "@types/jsdom": "^21.1.7", "@types/node": "^22.10.5", "typescript": "^5.7.2" @@ -16491,11 +16491,11 @@ }, "packages/test": { "name": "@augment-vir/test", - "version": "31.5.0", + "version": "31.6.0", "license": "(MIT or CC0 1.0)", "dependencies": { - "@augment-vir/assert": "^31.5.0", - "@augment-vir/common": "^31.5.0", + "@augment-vir/assert": "^31.6.0", + "@augment-vir/common": "^31.6.0", "@open-wc/testing-helpers": "^3.0.1", "@virmator/test": "^13.11.1", "type-fest": "^4.31.0" @@ -16529,17 +16529,17 @@ }, "packages/web": { "name": "@augment-vir/web", - "version": "31.5.0", + "version": "31.6.0", "license": "(MIT or CC0 1.0)", "dependencies": { - "@augment-vir/assert": "^31.5.0", - "@augment-vir/common": "^31.5.0", + "@augment-vir/assert": "^31.6.0", + "@augment-vir/common": "^31.6.0", "@date-vir/duration": "^7.1.1", "html-spec-tags": "^2.2.2", "type-fest": "^4.31.0" }, "devDependencies": { - "@augment-vir/test": "^31.5.0", + "@augment-vir/test": "^31.6.0", "bowser": "^2.11.0", "typescript": "^5.7.2" }, diff --git a/package.json b/package.json index 14cfcb3b7..dddd694a0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@augment-vir/mono-repo-root", - "version": "31.5.0", + "version": "31.6.0", "private": true, "homepage": "https://github.com/electrovir/augment-vir", "bugs": { diff --git a/packages/assert/package.json b/packages/assert/package.json index 1993e5d6c..cecd8922d 100644 --- a/packages/assert/package.json +++ b/packages/assert/package.json @@ -1,6 +1,6 @@ { "name": "@augment-vir/assert", - "version": "31.5.0", + "version": "31.6.0", "description": "A collection of assertions for test and production code alike.", "keywords": [ "augment", @@ -41,7 +41,7 @@ "test:update": "npm test" }, "dependencies": { - "@augment-vir/core": "^31.5.0", + "@augment-vir/core": "^31.6.0", "@date-vir/duration": "^7.1.1", "deep-eql": "^5.0.2", "expect-type": "^1.1.0", diff --git a/packages/common/package.json b/packages/common/package.json index 71a4da093..5e1c3ee4a 100644 --- a/packages/common/package.json +++ b/packages/common/package.json @@ -1,6 +1,6 @@ { "name": "@augment-vir/common", - "version": "31.5.0", + "version": "31.6.0", "description": "A collection of augments, helpers types, functions, and classes for any JavaScript environment.", "keywords": [ "augment", @@ -39,8 +39,8 @@ "test:web": "virmator --no-deps test web" }, "dependencies": { - "@augment-vir/assert": "^31.5.0", - "@augment-vir/core": "^31.5.0", + "@augment-vir/assert": "^31.6.0", + "@augment-vir/core": "^31.6.0", "@date-vir/duration": "^7.1.1", "ansi-styles": "^6.2.1", "json5": "^2.2.3", diff --git a/packages/core/package.json b/packages/core/package.json index fb6417577..fec77f8d2 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@augment-vir/core", - "version": "31.5.0", + "version": "31.6.0", "description": "Core augment-vir augments. Use @augment-vir/common instead.", "homepage": "https://github.com/electrovir/augment-vir", "bugs": { diff --git a/packages/core/src/augments/http/http-status.test.ts b/packages/core/src/augments/http/http-status.test.ts new file mode 100644 index 000000000..55968f7cf --- /dev/null +++ b/packages/core/src/augments/http/http-status.test.ts @@ -0,0 +1,53 @@ +import {assert} from '@augment-vir/assert'; +import {describe, it, itCases} from '@augment-vir/test'; +import {ArrayElement} from '../array/array.js'; +import { + ErrorHttpStatusCategories, + HttpStatus, + httpStatusByCategory, + isErrorHttpStatus, + SuccessHttpStatusCategories, +} from './http-status.js'; + +describe(isErrorHttpStatus.name, () => { + itCases(isErrorHttpStatus, [ + { + it: 'passes a client error', + input: HttpStatus.BadRequest, + expect: true, + }, + { + it: 'passes a server error', + input: HttpStatus.InternalServerError, + expect: true, + }, + { + it: 'rejects an info status', + input: HttpStatus.Continue, + expect: false, + }, + { + it: 'rejects a redirect', + input: HttpStatus.MultipleChoices, + expect: false, + }, + { + it: 'rejects a success', + input: HttpStatus.Ok, + expect: false, + }, + ]); + it('type guards the input', () => { + const status: HttpStatus = HttpStatus.Accepted as HttpStatus; + + if (isErrorHttpStatus(status)) { + assert + .tsType(status) + .equals>(); + } else { + assert + .tsType(status) + .equals>(); + } + }); +}); diff --git a/packages/core/src/augments/http/http-status.ts b/packages/core/src/augments/http/http-status.ts index cb568a376..ddc8d8938 100644 --- a/packages/core/src/augments/http/http-status.ts +++ b/packages/core/src/augments/http/http-status.ts @@ -1,4 +1,5 @@ import type {ArrayElement} from '../array/array.js'; +import type {ExtractKeysWithMatchingValues} from '../object/object-keys.js'; /** * All standardized HTTP status codes. @@ -510,6 +511,138 @@ export enum HttpStatusCategory { ServerError = 'serverError', } +/** + * All {@link HttpStatusCategory} entries that indicate a failed response as a runtime value that can + * be used to check actual response statuses. + * + * @category HTTP + * @category Package : @augment-vir/common + * @package [`@augment-vir/common`](https://www.npmjs.com/package/@augment-vir/common) + */ +export const errorHttpStatusCategories = [ + HttpStatusCategory.ClientError, + HttpStatusCategory.ServerError, +] as const; + +/** + * All {@link HttpStatusCategory} entries that indicate a failed response. + * + * @category HTTP + * @category Package : @augment-vir/common + * @package [`@augment-vir/common`](https://www.npmjs.com/package/@augment-vir/common) + */ +export type ErrorHttpStatusCategories = ArrayElement; +/** + * All {@link HttpStatusCategory} entries that indicate a successful response. + * + * @category HTTP + * @category Package : @augment-vir/common + * @package [`@augment-vir/common`](https://www.npmjs.com/package/@augment-vir/common) + */ +export type SuccessHttpStatusCategories = Exclude; + +/** + * Checks if the given HTTP status is an error status. Type guards the input. + * + * @category HTTP + * @category Package : @augment-vir/common + * @package [`@augment-vir/common`](https://www.npmjs.com/package/@augment-vir/common) + */ +export function isErrorHttpStatus( + input: HttpStatus, +): input is ExtractKeysWithMatchingValues { + return (errorHttpStatusCategories as ReadonlyArray).includes( + httpStatusToCategory[input], + ); +} + +/** + * A type that maps the given {@link HttpStatus} type parameter to its respective + * {@link HttpStatusCategory}. + * + * @category HTTP + * @category Package : @augment-vir/common + * @package [`@augment-vir/common`](https://www.npmjs.com/package/@augment-vir/common) + */ +export type HttpStatusToCategory = (typeof httpStatusToCategory)[Status]; + +/** + * All standardized HTTP statuses mapped to their respective category. + * + * @category HTTP + * @category Package : @augment-vir/common + * @package [`@augment-vir/common`](https://www.npmjs.com/package/@augment-vir/common) + */ +export const httpStatusToCategory = { + [HttpStatus.Continue]: HttpStatusCategory.Information, + [HttpStatus.SwitchingProtocols]: HttpStatusCategory.Information, + [HttpStatus.Processing]: HttpStatusCategory.Information, + [HttpStatus.EarlyHints]: HttpStatusCategory.Information, + + [HttpStatus.Ok]: HttpStatusCategory.Success, + [HttpStatus.Created]: HttpStatusCategory.Success, + [HttpStatus.Accepted]: HttpStatusCategory.Success, + [HttpStatus.NonAuthoritativeInformation]: HttpStatusCategory.Success, + [HttpStatus.NoContent]: HttpStatusCategory.Success, + [HttpStatus.ResetContent]: HttpStatusCategory.Success, + [HttpStatus.PartialContent]: HttpStatusCategory.Success, + [HttpStatus.MultiStatus]: HttpStatusCategory.Success, + [HttpStatus.AlreadyReported]: HttpStatusCategory.Success, + [HttpStatus.ImUsed]: HttpStatusCategory.Success, + + [HttpStatus.MultipleChoices]: HttpStatusCategory.Redirect, + [HttpStatus.MovedPermanently]: HttpStatusCategory.Redirect, + [HttpStatus.Found]: HttpStatusCategory.Redirect, + [HttpStatus.SeeOther]: HttpStatusCategory.Redirect, + [HttpStatus.NotModified]: HttpStatusCategory.Redirect, + [HttpStatus.UseProxy]: HttpStatusCategory.Redirect, + [HttpStatus.Unused]: HttpStatusCategory.Redirect, + [HttpStatus.TemporaryRedirect]: HttpStatusCategory.Redirect, + [HttpStatus.PermanentRedirect]: HttpStatusCategory.Redirect, + + [HttpStatus.BadRequest]: HttpStatusCategory.ClientError, + [HttpStatus.Unauthorized]: HttpStatusCategory.ClientError, + [HttpStatus.PaymentRequired]: HttpStatusCategory.ClientError, + [HttpStatus.Forbidden]: HttpStatusCategory.ClientError, + [HttpStatus.NotFound]: HttpStatusCategory.ClientError, + [HttpStatus.MethodNotAllowed]: HttpStatusCategory.ClientError, + [HttpStatus.NotAcceptable]: HttpStatusCategory.ClientError, + [HttpStatus.ProxyAuthenticationRequired]: HttpStatusCategory.ClientError, + [HttpStatus.RequestTimeout]: HttpStatusCategory.ClientError, + [HttpStatus.Conflict]: HttpStatusCategory.ClientError, + [HttpStatus.Gone]: HttpStatusCategory.ClientError, + [HttpStatus.LengthRequired]: HttpStatusCategory.ClientError, + [HttpStatus.PreconditionFailed]: HttpStatusCategory.ClientError, + [HttpStatus.PayloadTooLarge]: HttpStatusCategory.ClientError, + [HttpStatus.UriTooLong]: HttpStatusCategory.ClientError, + [HttpStatus.UnsupportedMediaType]: HttpStatusCategory.ClientError, + [HttpStatus.RangeNotSatisfiable]: HttpStatusCategory.ClientError, + [HttpStatus.ExpectationFailed]: HttpStatusCategory.ClientError, + [HttpStatus.ImATeapot]: HttpStatusCategory.ClientError, + [HttpStatus.MisdirectedRequest]: HttpStatusCategory.ClientError, + [HttpStatus.UnprocessableContent]: HttpStatusCategory.ClientError, + [HttpStatus.Locked]: HttpStatusCategory.ClientError, + [HttpStatus.FailedDependency]: HttpStatusCategory.ClientError, + [HttpStatus.TooEarly]: HttpStatusCategory.ClientError, + [HttpStatus.UpgradeRequired]: HttpStatusCategory.ClientError, + [HttpStatus.PreconditionRequired]: HttpStatusCategory.ClientError, + [HttpStatus.TooManyRequests]: HttpStatusCategory.ClientError, + [HttpStatus.RequestHeaderFieldsTooLarge]: HttpStatusCategory.ClientError, + [HttpStatus.UnavailableForLegalReasons]: HttpStatusCategory.ClientError, + + [HttpStatus.InternalServerError]: HttpStatusCategory.ServerError, + [HttpStatus.NotImplemented]: HttpStatusCategory.ServerError, + [HttpStatus.BadGateway]: HttpStatusCategory.ServerError, + [HttpStatus.ServiceUnavailable]: HttpStatusCategory.ServerError, + [HttpStatus.GatewayTimeout]: HttpStatusCategory.ServerError, + [HttpStatus.HttpVersionNotSupported]: HttpStatusCategory.ServerError, + [HttpStatus.VariantAlsoNegotiates]: HttpStatusCategory.ServerError, + [HttpStatus.InsufficientStorage]: HttpStatusCategory.ServerError, + [HttpStatus.LoopDetected]: HttpStatusCategory.ServerError, + [HttpStatus.NotExtended]: HttpStatusCategory.ServerError, + [HttpStatus.NetworkAuthenticationRequired]: HttpStatusCategory.ServerError, +} as const satisfies Record; + /** * All standardized HTTP status codes grouped into their respective categories. * @@ -591,7 +724,7 @@ export const httpStatusByCategory = { HttpStatus.NotExtended, HttpStatus.NetworkAuthenticationRequired, ], -} as const; +} as const satisfies Record; /** * All possible HTTP status codes for the given {@link HttpStatusCategory}. diff --git a/packages/node/package.json b/packages/node/package.json index 9f0f1ee1c..e39777896 100644 --- a/packages/node/package.json +++ b/packages/node/package.json @@ -1,6 +1,6 @@ { "name": "@augment-vir/node", - "version": "31.5.0", + "version": "31.6.0", "description": "A collection of augments, helpers types, functions, and classes only for Node.js (backend) JavaScript environments.", "keywords": [ "augment", @@ -37,8 +37,8 @@ "test:update": "npm test" }, "dependencies": { - "@augment-vir/assert": "^31.5.0", - "@augment-vir/common": "^31.5.0", + "@augment-vir/assert": "^31.6.0", + "@augment-vir/common": "^31.6.0", "@date-vir/duration": "^7.1.1", "ansi-styles": "^6.2.1", "terminate": "^2.8.0", @@ -46,7 +46,7 @@ "typed-event-target": "^4.0.2" }, "devDependencies": { - "@augment-vir/test": "^31.5.0", + "@augment-vir/test": "^31.6.0", "@prisma/client": "^6.1.0", "@types/node": "^22.10.5", "@web/dev-server-esbuild": "^1.0.3", diff --git a/packages/scripts/package.json b/packages/scripts/package.json index 754ba7391..cf5e30979 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -1,6 +1,6 @@ { "name": "@augment-vir/scripts", - "version": "31.5.0", + "version": "31.6.0", "private": true, "homepage": "https://github.com/electrovir/augment-vir", "bugs": { @@ -24,15 +24,15 @@ "test:update": "npm test" }, "dependencies": { - "@augment-vir/assert": "^31.5.0", - "@augment-vir/common": "^31.5.0", - "@augment-vir/node": "^31.5.0", + "@augment-vir/assert": "^31.6.0", + "@augment-vir/common": "^31.6.0", + "@augment-vir/node": "^31.6.0", "@virmator/docs": "^13.11.1", "jsdom": "^25.0.1", "typedoc": "^0.27.6" }, "devDependencies": { - "@augment-vir/test": "^31.5.0", + "@augment-vir/test": "^31.6.0", "@types/jsdom": "^21.1.7", "@types/node": "^22.10.5", "typescript": "^5.7.2" diff --git a/packages/test/package.json b/packages/test/package.json index 0d158434a..496c3f484 100644 --- a/packages/test/package.json +++ b/packages/test/package.json @@ -1,6 +1,6 @@ { "name": "@augment-vir/test", - "version": "31.5.0", + "version": "31.6.0", "description": "A universal testing suite that works with Mocha style test runners _and_ Node.js's built-in test runner.", "keywords": [ "test", @@ -42,8 +42,8 @@ "test:web": "virmator test --no-deps web 'src/test-web/**/*.test.ts' 'src/augments/universal-testing-suite/**/*.test.ts'" }, "dependencies": { - "@augment-vir/assert": "^31.5.0", - "@augment-vir/common": "^31.5.0", + "@augment-vir/assert": "^31.6.0", + "@augment-vir/common": "^31.6.0", "@open-wc/testing-helpers": "^3.0.1", "@virmator/test": "^13.11.1", "type-fest": "^4.31.0" diff --git a/packages/web/package.json b/packages/web/package.json index cbc4e22fc..58f6544df 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -1,6 +1,6 @@ { "name": "@augment-vir/web", - "version": "31.5.0", + "version": "31.6.0", "description": "A collection of augments, helpers types, functions, and classes only for web (frontend) JavaScript environments.", "keywords": [ "augment", @@ -35,14 +35,14 @@ "test:update": "npm test" }, "dependencies": { - "@augment-vir/assert": "^31.5.0", - "@augment-vir/common": "^31.5.0", + "@augment-vir/assert": "^31.6.0", + "@augment-vir/common": "^31.6.0", "@date-vir/duration": "^7.1.1", "html-spec-tags": "^2.2.2", "type-fest": "^4.31.0" }, "devDependencies": { - "@augment-vir/test": "^31.5.0", + "@augment-vir/test": "^31.6.0", "bowser": "^2.11.0", "typescript": "^5.7.2" },