@twin.org/api-models 0.0.3-next.5 → 0.0.3-next.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -18,25 +18,31 @@ export class HttpErrorHelper {
18
18
  // types then set the http response code accordingly
19
19
  const flattened = BaseError.flatten(error);
20
20
  let httpStatusCode = HttpStatusCode.internalServerError;
21
- if (flattened.some(e => BaseError.isErrorName(e, GuardError.CLASS_NAME)) ||
22
- flattened.some(e => BaseError.isErrorName(e, ValidationError.CLASS_NAME))) {
23
- httpStatusCode = HttpStatusCode.badRequest;
24
- }
25
- else if (flattened.some(e => BaseError.isErrorName(e, ConflictError.CLASS_NAME)) ||
26
- flattened.some(e => BaseError.isErrorName(e, AlreadyExistsError.CLASS_NAME))) {
27
- httpStatusCode = HttpStatusCode.conflict;
28
- }
29
- else if (flattened.some(e => BaseError.isErrorName(e, NotFoundError.CLASS_NAME))) {
30
- httpStatusCode = HttpStatusCode.notFound;
31
- }
32
- else if (flattened.some(e => BaseError.isErrorName(e, UnauthorizedError.CLASS_NAME))) {
33
- httpStatusCode = HttpStatusCode.unauthorized;
34
- }
35
- else if (flattened.some(e => BaseError.isErrorName(e, NotImplementedError.CLASS_NAME))) {
36
- httpStatusCode = HttpStatusCode.forbidden;
37
- }
38
- else if (flattened.some(e => BaseError.isErrorName(e, UnprocessableError.CLASS_NAME))) {
39
- httpStatusCode = HttpStatusCode.unprocessableEntity;
21
+ const errorTypeMap = {
22
+ [GuardError.CLASS_NAME]: HttpStatusCode.badRequest,
23
+ [ValidationError.CLASS_NAME]: HttpStatusCode.badRequest,
24
+ [ConflictError.CLASS_NAME]: HttpStatusCode.conflict,
25
+ [AlreadyExistsError.CLASS_NAME]: HttpStatusCode.conflict,
26
+ [NotFoundError.CLASS_NAME]: HttpStatusCode.notFound,
27
+ [UnauthorizedError.CLASS_NAME]: HttpStatusCode.unauthorized,
28
+ [NotImplementedError.CLASS_NAME]: HttpStatusCode.forbidden,
29
+ [UnprocessableError.CLASS_NAME]: HttpStatusCode.unprocessableEntity
30
+ };
31
+ // First check the primary error, as we don't want to override that with a sub error
32
+ if (flattened.length > 0) {
33
+ const primaryError = flattened[0];
34
+ if (errorTypeMap[primaryError.name]) {
35
+ httpStatusCode = errorTypeMap[primaryError.name];
36
+ }
37
+ // The primary error is still internal server error, check the sub errors
38
+ if (httpStatusCode === HttpStatusCode.internalServerError) {
39
+ for (const className in errorTypeMap) {
40
+ if (flattened.some(e => BaseError.isErrorName(e, className))) {
41
+ httpStatusCode = errorTypeMap[className];
42
+ break;
43
+ }
44
+ }
45
+ }
40
46
  }
41
47
  const returnError = error.toJsonObject(includeStack);
42
48
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"httpErrorHelper.js","sourceRoot":"","sources":["../../../src/helpers/httpErrorHelper.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport {\n\tAlreadyExistsError,\n\tBaseError,\n\tConflictError,\n\tGuardError,\n\ttype IError,\n\tNotFoundError,\n\tNotImplementedError,\n\tUnauthorizedError,\n\tUnprocessableError,\n\tValidationError\n} from \"@twin.org/core\";\nimport { HeaderTypes, HttpStatusCode, MimeTypes } from \"@twin.org/web\";\nimport type { IHttpResponse } from \"../models/protocol/IHttpResponse.js\";\n\n/**\n * Class to help with processing http errors.\n */\nexport class HttpErrorHelper {\n\t/**\n\t * Process the errors from the routes.\n\t * @param err The error to process.\n\t * @param includeStack Should the stack be included in the error.\n\t * @returns The status code and additional error data.\n\t */\n\tpublic static processError(\n\t\terr: unknown,\n\t\tincludeStack?: boolean\n\t): {\n\t\terror: IError;\n\t\thttpStatusCode: HttpStatusCode;\n\t} {\n\t\tconst error: BaseError = BaseError.fromError(err);\n\n\t\t// If the error or any of its sub errors are of the specific\n\t\t// types then set the http response code accordingly\n\t\tconst flattened = BaseError.flatten(error);\n\n\t\tlet httpStatusCode: HttpStatusCode = HttpStatusCode.internalServerError;\n\t\tif (\n\t\t\tflattened.some(e => BaseError.isErrorName(e, GuardError.CLASS_NAME)) ||\n\t\t\tflattened.some(e => BaseError.isErrorName(e, ValidationError.CLASS_NAME))\n\t\t) {\n\t\t\thttpStatusCode = HttpStatusCode.badRequest;\n\t\t} else if (\n\t\t\tflattened.some(e => BaseError.isErrorName(e, ConflictError.CLASS_NAME)) ||\n\t\t\tflattened.some(e => BaseError.isErrorName(e, AlreadyExistsError.CLASS_NAME))\n\t\t) {\n\t\t\thttpStatusCode = HttpStatusCode.conflict;\n\t\t} else if (flattened.some(e => BaseError.isErrorName(e, NotFoundError.CLASS_NAME))) {\n\t\t\thttpStatusCode = HttpStatusCode.notFound;\n\t\t} else if (flattened.some(e => BaseError.isErrorName(e, UnauthorizedError.CLASS_NAME))) {\n\t\t\thttpStatusCode = HttpStatusCode.unauthorized;\n\t\t} else if (flattened.some(e => BaseError.isErrorName(e, NotImplementedError.CLASS_NAME))) {\n\t\t\thttpStatusCode = HttpStatusCode.forbidden;\n\t\t} else if (flattened.some(e => BaseError.isErrorName(e, UnprocessableError.CLASS_NAME))) {\n\t\t\thttpStatusCode = HttpStatusCode.unprocessableEntity;\n\t\t}\n\n\t\tconst returnError = error.toJsonObject(includeStack);\n\n\t\treturn {\n\t\t\terror: returnError,\n\t\t\thttpStatusCode\n\t\t};\n\t}\n\n\t/**\n\t * Build an error response.\n\t * @param response The response to build the error into.\n\t * @param error The error to build the response for.\n\t * @param statusCode The status code to use for the error.\n\t */\n\tpublic static buildResponse(\n\t\tresponse: IHttpResponse,\n\t\terror: IError,\n\t\tstatusCode: HttpStatusCode\n\t): void {\n\t\tresponse.headers ??= {};\n\t\tresponse.headers[HeaderTypes.ContentType] = `${MimeTypes.Json}; charset=utf-8`;\n\t\tresponse.body = error;\n\t\tresponse.statusCode = statusCode;\n\t}\n}\n"]}
1
+ {"version":3,"file":"httpErrorHelper.js","sourceRoot":"","sources":["../../../src/helpers/httpErrorHelper.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,OAAO,EACN,kBAAkB,EAClB,SAAS,EACT,aAAa,EACb,UAAU,EAEV,aAAa,EACb,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,EACf,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAGvE;;GAEG;AACH,MAAM,OAAO,eAAe;IAC3B;;;;;OAKG;IACI,MAAM,CAAC,YAAY,CACzB,GAAY,EACZ,YAAsB;QAKtB,MAAM,KAAK,GAAc,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QAElD,4DAA4D;QAC5D,oDAAoD;QACpD,MAAM,SAAS,GAAG,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAE3C,IAAI,cAAc,GAAmB,cAAc,CAAC,mBAAmB,CAAC;QAExE,MAAM,YAAY,GAAqC;YACtD,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,cAAc,CAAC,UAAU;YAClD,CAAC,eAAe,CAAC,UAAU,CAAC,EAAE,cAAc,CAAC,UAAU;YACvD,CAAC,aAAa,CAAC,UAAU,CAAC,EAAE,cAAc,CAAC,QAAQ;YACnD,CAAC,kBAAkB,CAAC,UAAU,CAAC,EAAE,cAAc,CAAC,QAAQ;YACxD,CAAC,aAAa,CAAC,UAAU,CAAC,EAAE,cAAc,CAAC,QAAQ;YACnD,CAAC,iBAAiB,CAAC,UAAU,CAAC,EAAE,cAAc,CAAC,YAAY;YAC3D,CAAC,mBAAmB,CAAC,UAAU,CAAC,EAAE,cAAc,CAAC,SAAS;YAC1D,CAAC,kBAAkB,CAAC,UAAU,CAAC,EAAE,cAAc,CAAC,mBAAmB;SACnE,CAAC;QAEF,oFAAoF;QACpF,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1B,MAAM,YAAY,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;YAClC,IAAI,YAAY,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;gBACrC,cAAc,GAAG,YAAY,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;YAClD,CAAC;YAED,yEAAyE;YACzE,IAAI,cAAc,KAAK,cAAc,CAAC,mBAAmB,EAAE,CAAC;gBAC3D,KAAK,MAAM,SAAS,IAAI,YAAY,EAAE,CAAC;oBACtC,IAAI,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC;wBAC9D,cAAc,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC;wBACzC,MAAM;oBACP,CAAC;gBACF,CAAC;YACF,CAAC;QACF,CAAC;QAED,MAAM,WAAW,GAAG,KAAK,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC;QAErD,OAAO;YACN,KAAK,EAAE,WAAW;YAClB,cAAc;SACd,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACI,MAAM,CAAC,aAAa,CAC1B,QAAuB,EACvB,KAAa,EACb,UAA0B;QAE1B,QAAQ,CAAC,OAAO,KAAK,EAAE,CAAC;QACxB,QAAQ,CAAC,OAAO,CAAC,WAAW,CAAC,WAAW,CAAC,GAAG,GAAG,SAAS,CAAC,IAAI,iBAAiB,CAAC;QAC/E,QAAQ,CAAC,IAAI,GAAG,KAAK,CAAC;QACtB,QAAQ,CAAC,UAAU,GAAG,UAAU,CAAC;IAClC,CAAC;CACD","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport {\n\tAlreadyExistsError,\n\tBaseError,\n\tConflictError,\n\tGuardError,\n\ttype IError,\n\tNotFoundError,\n\tNotImplementedError,\n\tUnauthorizedError,\n\tUnprocessableError,\n\tValidationError\n} from \"@twin.org/core\";\nimport { HeaderTypes, HttpStatusCode, MimeTypes } from \"@twin.org/web\";\nimport type { IHttpResponse } from \"../models/protocol/IHttpResponse.js\";\n\n/**\n * Class to help with processing http errors.\n */\nexport class HttpErrorHelper {\n\t/**\n\t * Process the errors from the routes.\n\t * @param err The error to process.\n\t * @param includeStack Should the stack be included in the error.\n\t * @returns The status code and additional error data.\n\t */\n\tpublic static processError(\n\t\terr: unknown,\n\t\tincludeStack?: boolean\n\t): {\n\t\terror: IError;\n\t\thttpStatusCode: HttpStatusCode;\n\t} {\n\t\tconst error: BaseError = BaseError.fromError(err);\n\n\t\t// If the error or any of its sub errors are of the specific\n\t\t// types then set the http response code accordingly\n\t\tconst flattened = BaseError.flatten(error);\n\n\t\tlet httpStatusCode: HttpStatusCode = HttpStatusCode.internalServerError;\n\n\t\tconst errorTypeMap: { [id: string]: HttpStatusCode } = {\n\t\t\t[GuardError.CLASS_NAME]: HttpStatusCode.badRequest,\n\t\t\t[ValidationError.CLASS_NAME]: HttpStatusCode.badRequest,\n\t\t\t[ConflictError.CLASS_NAME]: HttpStatusCode.conflict,\n\t\t\t[AlreadyExistsError.CLASS_NAME]: HttpStatusCode.conflict,\n\t\t\t[NotFoundError.CLASS_NAME]: HttpStatusCode.notFound,\n\t\t\t[UnauthorizedError.CLASS_NAME]: HttpStatusCode.unauthorized,\n\t\t\t[NotImplementedError.CLASS_NAME]: HttpStatusCode.forbidden,\n\t\t\t[UnprocessableError.CLASS_NAME]: HttpStatusCode.unprocessableEntity\n\t\t};\n\n\t\t// First check the primary error, as we don't want to override that with a sub error\n\t\tif (flattened.length > 0) {\n\t\t\tconst primaryError = flattened[0];\n\t\t\tif (errorTypeMap[primaryError.name]) {\n\t\t\t\thttpStatusCode = errorTypeMap[primaryError.name];\n\t\t\t}\n\n\t\t\t// The primary error is still internal server error, check the sub errors\n\t\t\tif (httpStatusCode === HttpStatusCode.internalServerError) {\n\t\t\t\tfor (const className in errorTypeMap) {\n\t\t\t\t\tif (flattened.some(e => BaseError.isErrorName(e, className))) {\n\t\t\t\t\t\thttpStatusCode = errorTypeMap[className];\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst returnError = error.toJsonObject(includeStack);\n\n\t\treturn {\n\t\t\terror: returnError,\n\t\t\thttpStatusCode\n\t\t};\n\t}\n\n\t/**\n\t * Build an error response.\n\t * @param response The response to build the error into.\n\t * @param error The error to build the response for.\n\t * @param statusCode The status code to use for the error.\n\t */\n\tpublic static buildResponse(\n\t\tresponse: IHttpResponse,\n\t\terror: IError,\n\t\tstatusCode: HttpStatusCode\n\t): void {\n\t\tresponse.headers ??= {};\n\t\tresponse.headers[HeaderTypes.ContentType] = `${MimeTypes.Json}; charset=utf-8`;\n\t\tresponse.body = error;\n\t\tresponse.statusCode = statusCode;\n\t}\n}\n"]}
package/docs/changelog.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # @twin.org/api-models - Changelog
2
2
 
3
+ ## [0.0.3-next.7](https://github.com/twinfoundation/api/compare/api-models-v0.0.3-next.6...api-models-v0.0.3-next.7) (2025-11-26)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * error handling make sure primary error takes precedence ([84b61f2](https://github.com/twinfoundation/api/commit/84b61f27fe5e4919c0c9f9a1edc8ff46dc45c1f7))
9
+
10
+ ## [0.0.3-next.6](https://github.com/twinfoundation/api/compare/api-models-v0.0.3-next.5...api-models-v0.0.3-next.6) (2025-11-20)
11
+
12
+
13
+ ### Miscellaneous Chores
14
+
15
+ * **api-models:** Synchronize repo versions
16
+
3
17
  ## [0.0.3-next.5](https://github.com/twinfoundation/api/compare/api-models-v0.0.3-next.4...api-models-v0.0.3-next.5) (2025-11-14)
4
18
 
5
19
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@twin.org/api-models",
3
- "version": "0.0.3-next.5",
3
+ "version": "0.0.3-next.7",
4
4
  "description": "Contains models and classes for use with APIs",
5
5
  "repository": {
6
6
  "type": "git",