@twin.org/core 0.0.3-next.45 → 0.0.3-next.46

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.
@@ -11,23 +11,27 @@ export class ErrorHelper {
11
11
  /**
12
12
  * Format Errors and returns just their messages.
13
13
  * @param error The error to format.
14
- * @param includeDetails Whether to include error details, defaults to false.
14
+ * @param options Options for formatting the error.
15
+ * @param options.includeStack Whether to include the stack trace in the output, defaults to false.
16
+ * @param options.includeAdditional Whether to include additional error information in the output, defaults to false.
15
17
  * @returns The error formatted including any causes errors.
16
18
  */
17
- static formatErrors(error, includeDetails) {
19
+ static formatErrors(error, options) {
18
20
  const localizedErrors = ErrorHelper.localizeErrors(error);
19
- if (includeDetails ?? false) {
20
- const output = [];
21
- for (const err of localizedErrors) {
22
- let detailedError = err.message;
23
- if (Is.stringValue(err.stack)) {
24
- detailedError += `\n${err.stack}`;
25
- }
26
- output.push(detailedError);
21
+ const output = [];
22
+ const includeAdditional = options?.includeAdditional ?? false;
23
+ const includeStack = options?.includeStack ?? false;
24
+ for (const err of localizedErrors) {
25
+ let detailedError = err.message;
26
+ if (includeAdditional && Is.arrayValue(err.additional)) {
27
+ detailedError += `\n${err.additional.join("\n")}`;
28
+ }
29
+ if (includeStack && Is.stringValue(err.stack)) {
30
+ detailedError += `\n${err.stack}`;
27
31
  }
28
- return output;
32
+ output.push(detailedError);
29
33
  }
30
- return localizedErrors.map(e => e.message);
34
+ return output;
31
35
  }
32
36
  /**
33
37
  * Localize the content of an error and any causes.
@@ -62,7 +66,7 @@ export class ErrorHelper {
62
66
  localizedError.stack = lines.join("\n");
63
67
  }
64
68
  const additional = ErrorHelper.formatValidationErrors(err);
65
- if (Is.stringValue(additional)) {
69
+ if (Is.arrayValue(additional)) {
66
70
  localizedError.additional = additional;
67
71
  }
68
72
  formattedErrors.push(localizedError);
@@ -93,7 +97,7 @@ export class ErrorHelper {
93
97
  }
94
98
  validationErrors.push(v);
95
99
  }
96
- return validationErrors.join("\n");
100
+ return validationErrors;
97
101
  }
98
102
  }
99
103
  }
@@ -1 +1 @@
1
- {"version":3,"file":"errorHelper.js","sourceRoot":"","sources":["../../../src/helpers/errorHelper.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { StringHelper } from \"./stringHelper.js\";\nimport { BaseError } from \"../errors/baseError.js\";\nimport type { IError } from \"../models/IError.js\";\nimport type { IValidationFailure } from \"../models/IValidationFailure.js\";\nimport { I18n } from \"../utils/i18n.js\";\nimport { Is } from \"../utils/is.js\";\n\n/**\n * Error helper functions.\n */\nexport class ErrorHelper {\n\t/**\n\t * Format Errors and returns just their messages.\n\t * @param error The error to format.\n\t * @param includeDetails Whether to include error details, defaults to false.\n\t * @returns The error formatted including any causes errors.\n\t */\n\tpublic static formatErrors(error: unknown, includeDetails?: boolean): string[] {\n\t\tconst localizedErrors = ErrorHelper.localizeErrors(error);\n\t\tif (includeDetails ?? false) {\n\t\t\tconst output: string[] = [];\n\t\t\tfor (const err of localizedErrors) {\n\t\t\t\tlet detailedError = err.message;\n\t\t\t\tif (Is.stringValue(err.stack)) {\n\t\t\t\t\tdetailedError += `\\n${err.stack}`;\n\t\t\t\t}\n\t\t\t\toutput.push(detailedError);\n\t\t\t}\n\t\t\treturn output;\n\t\t}\n\t\treturn localizedErrors.map(e => e.message);\n\t}\n\n\t/**\n\t * Localize the content of an error and any causes.\n\t * @param error The error to format.\n\t * @returns The localized version of the errors flattened.\n\t */\n\tpublic static localizeErrors(error: unknown): IError[] {\n\t\tconst formattedErrors: IError[] = [];\n\n\t\tif (Is.notEmpty(error)) {\n\t\t\tconst errors = BaseError.flatten(error);\n\n\t\t\tfor (const err of errors) {\n\t\t\t\tconst errorNameKey = `errorNames.${StringHelper.camelCase(err.name)}`;\n\t\t\t\tconst errorMessageKey = `error.${err.message}`;\n\n\t\t\t\t// If there is no error message then it is probably\n\t\t\t\t// from a 3rd party lib, so don't format it just display\n\t\t\t\tconst hasErrorName = I18n.hasMessage(errorNameKey);\n\t\t\t\tconst hasErrorMessage = I18n.hasMessage(errorMessageKey);\n\n\t\t\t\tconst localizedError: IError & { additional?: string } = {\n\t\t\t\t\tname: I18n.formatMessage(hasErrorName ? errorNameKey : \"errorNames.error\"),\n\t\t\t\t\tmessage: hasErrorMessage\n\t\t\t\t\t\t? I18n.formatMessage(errorMessageKey, err.properties)\n\t\t\t\t\t\t: err.message\n\t\t\t\t};\n\n\t\t\t\tif (Is.stringValue(err.source)) {\n\t\t\t\t\tlocalizedError.source = err.source;\n\t\t\t\t}\n\t\t\t\tif (Is.stringValue(err.stack)) {\n\t\t\t\t\t// Remove the first line from the stack traces as they\n\t\t\t\t\t// just have the error type and message duplicated\n\t\t\t\t\tconst lines = err.stack.split(\"\\n\");\n\t\t\t\t\tlines.shift();\n\t\t\t\t\tlocalizedError.stack = lines.join(\"\\n\");\n\t\t\t\t}\n\n\t\t\t\tconst additional = ErrorHelper.formatValidationErrors(err);\n\t\t\t\tif (Is.stringValue(additional)) {\n\t\t\t\t\tlocalizedError.additional = additional;\n\t\t\t\t}\n\n\t\t\t\tformattedErrors.push(localizedError);\n\t\t\t}\n\t\t}\n\n\t\treturn formattedErrors;\n\t}\n\n\t/**\n\t * Localize the content of an error and any causes.\n\t * @param error The error to format.\n\t * @returns The localized version of the errors flattened.\n\t */\n\tpublic static formatValidationErrors(error: IError): string | undefined {\n\t\tif (\n\t\t\tIs.object(error.properties) &&\n\t\t\tObject.keys(error.properties).length > 0 &&\n\t\t\tIs.object<{ validationFailures: IValidationFailure[] }>(error.properties) &&\n\t\t\tIs.arrayValue(error.properties.validationFailures)\n\t\t) {\n\t\t\tconst validationErrors = [];\n\t\t\tfor (const validationFailure of error.properties.validationFailures) {\n\t\t\t\tconst errorI18n = `error.${validationFailure.reason}`;\n\t\t\t\tconst errorMessage = I18n.hasMessage(errorI18n)\n\t\t\t\t\t? I18n.formatMessage(errorI18n, validationFailure.properties)\n\t\t\t\t\t: errorI18n;\n\n\t\t\t\tlet v = `${validationFailure.property}: ${errorMessage}`;\n\t\t\t\tif (\n\t\t\t\t\tIs.object<{ value: unknown }>(validationFailure.properties) &&\n\t\t\t\t\tIs.notEmpty(validationFailure.properties.value)\n\t\t\t\t) {\n\t\t\t\t\tv += ` = ${JSON.stringify(validationFailure.properties.value)}`;\n\t\t\t\t}\n\t\t\t\tvalidationErrors.push(v);\n\t\t\t}\n\t\t\treturn validationErrors.join(\"\\n\");\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"errorHelper.js","sourceRoot":"","sources":["../../../src/helpers/errorHelper.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAGnD,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,OAAO,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAC;AAEpC;;GAEG;AACH,MAAM,OAAO,WAAW;IACvB;;;;;;;OAOG;IACI,MAAM,CAAC,YAAY,CACzB,KAAc,EACd,OAGC;QAED,MAAM,eAAe,GAAG,WAAW,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;QAE1D,MAAM,MAAM,GAAa,EAAE,CAAC;QAE5B,MAAM,iBAAiB,GAAG,OAAO,EAAE,iBAAiB,IAAI,KAAK,CAAC;QAC9D,MAAM,YAAY,GAAG,OAAO,EAAE,YAAY,IAAI,KAAK,CAAC;QAEpD,KAAK,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;YACnC,IAAI,aAAa,GAAG,GAAG,CAAC,OAAO,CAAC;YAChC,IAAI,iBAAiB,IAAI,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;gBACxD,aAAa,IAAI,KAAK,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACnD,CAAC;YACD,IAAI,YAAY,IAAI,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC/C,aAAa,IAAI,KAAK,GAAG,CAAC,KAAK,EAAE,CAAC;YACnC,CAAC;YACD,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAC5B,CAAC;QAED,OAAO,MAAM,CAAC;IACf,CAAC;IAED;;;;OAIG;IACI,MAAM,CAAC,cAAc,CAAC,KAAc;QAC1C,MAAM,eAAe,GAA2C,EAAE,CAAC;QAEnE,IAAI,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACxB,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YAExC,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;gBAC1B,MAAM,YAAY,GAAG,cAAc,YAAY,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBACtE,MAAM,eAAe,GAAG,SAAS,GAAG,CAAC,OAAO,EAAE,CAAC;gBAE/C,mDAAmD;gBACnD,wDAAwD;gBACxD,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;gBACnD,MAAM,eAAe,GAAG,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;gBAEzD,MAAM,cAAc,GAAuC;oBAC1D,IAAI,EAAE,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,kBAAkB,CAAC;oBAC1E,OAAO,EAAE,eAAe;wBACvB,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,eAAe,EAAE,GAAG,CAAC,UAAU,CAAC;wBACrD,CAAC,CAAC,GAAG,CAAC,OAAO;iBACd,CAAC;gBAEF,IAAI,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;oBAChC,cAAc,CAAC,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC;gBACpC,CAAC;gBACD,IAAI,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;oBAC/B,sDAAsD;oBACtD,kDAAkD;oBAClD,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;oBACpC,KAAK,CAAC,KAAK,EAAE,CAAC;oBACd,cAAc,CAAC,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACzC,CAAC;gBAED,MAAM,UAAU,GAAG,WAAW,CAAC,sBAAsB,CAAC,GAAG,CAAC,CAAC;gBAC3D,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;oBAC/B,cAAc,CAAC,UAAU,GAAG,UAAU,CAAC;gBACxC,CAAC;gBAED,eAAe,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YACtC,CAAC;QACF,CAAC;QAED,OAAO,eAAe,CAAC;IACxB,CAAC;IAED;;;;OAIG;IACI,MAAM,CAAC,sBAAsB,CAAC,KAAa;QACjD,IACC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC;YAC3B,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,MAAM,GAAG,CAAC;YACxC,EAAE,CAAC,MAAM,CAA+C,KAAK,CAAC,UAAU,CAAC;YACzE,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,kBAAkB,CAAC,EACjD,CAAC;YACF,MAAM,gBAAgB,GAAa,EAAE,CAAC;YACtC,KAAK,MAAM,iBAAiB,IAAI,KAAK,CAAC,UAAU,CAAC,kBAAkB,EAAE,CAAC;gBACrE,MAAM,SAAS,GAAG,SAAS,iBAAiB,CAAC,MAAM,EAAE,CAAC;gBACtD,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;oBAC9C,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,SAAS,EAAE,iBAAiB,CAAC,UAAU,CAAC;oBAC7D,CAAC,CAAC,SAAS,CAAC;gBAEb,IAAI,CAAC,GAAG,GAAG,iBAAiB,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;gBACzD,IACC,EAAE,CAAC,MAAM,CAAqB,iBAAiB,CAAC,UAAU,CAAC;oBAC3D,EAAE,CAAC,QAAQ,CAAC,iBAAiB,CAAC,UAAU,CAAC,KAAK,CAAC,EAC9C,CAAC;oBACF,CAAC,IAAI,MAAM,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;gBACjE,CAAC;gBACD,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAC1B,CAAC;YACD,OAAO,gBAAgB,CAAC;QACzB,CAAC;IACF,CAAC;CACD","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { StringHelper } from \"./stringHelper.js\";\nimport { BaseError } from \"../errors/baseError.js\";\nimport type { IError } from \"../models/IError.js\";\nimport type { IValidationFailure } from \"../models/IValidationFailure.js\";\nimport { I18n } from \"../utils/i18n.js\";\nimport { Is } from \"../utils/is.js\";\n\n/**\n * Error helper functions.\n */\nexport class ErrorHelper {\n\t/**\n\t * Format Errors and returns just their messages.\n\t * @param error The error to format.\n\t * @param options Options for formatting the error.\n\t * @param options.includeStack Whether to include the stack trace in the output, defaults to false.\n\t * @param options.includeAdditional Whether to include additional error information in the output, defaults to false.\n\t * @returns The error formatted including any causes errors.\n\t */\n\tpublic static formatErrors(\n\t\terror: unknown,\n\t\toptions?: {\n\t\t\tincludeStack?: boolean;\n\t\t\tincludeAdditional?: boolean;\n\t\t}\n\t): string[] {\n\t\tconst localizedErrors = ErrorHelper.localizeErrors(error);\n\n\t\tconst output: string[] = [];\n\n\t\tconst includeAdditional = options?.includeAdditional ?? false;\n\t\tconst includeStack = options?.includeStack ?? false;\n\n\t\tfor (const err of localizedErrors) {\n\t\t\tlet detailedError = err.message;\n\t\t\tif (includeAdditional && Is.arrayValue(err.additional)) {\n\t\t\t\tdetailedError += `\\n${err.additional.join(\"\\n\")}`;\n\t\t\t}\n\t\t\tif (includeStack && Is.stringValue(err.stack)) {\n\t\t\t\tdetailedError += `\\n${err.stack}`;\n\t\t\t}\n\t\t\toutput.push(detailedError);\n\t\t}\n\n\t\treturn output;\n\t}\n\n\t/**\n\t * Localize the content of an error and any causes.\n\t * @param error The error to format.\n\t * @returns The localized version of the errors flattened.\n\t */\n\tpublic static localizeErrors(error: unknown): (IError & { additional?: string[] })[] {\n\t\tconst formattedErrors: (IError & { additional?: string[] })[] = [];\n\n\t\tif (Is.notEmpty(error)) {\n\t\t\tconst errors = BaseError.flatten(error);\n\n\t\t\tfor (const err of errors) {\n\t\t\t\tconst errorNameKey = `errorNames.${StringHelper.camelCase(err.name)}`;\n\t\t\t\tconst errorMessageKey = `error.${err.message}`;\n\n\t\t\t\t// If there is no error message then it is probably\n\t\t\t\t// from a 3rd party lib, so don't format it just display\n\t\t\t\tconst hasErrorName = I18n.hasMessage(errorNameKey);\n\t\t\t\tconst hasErrorMessage = I18n.hasMessage(errorMessageKey);\n\n\t\t\t\tconst localizedError: IError & { additional?: string[] } = {\n\t\t\t\t\tname: I18n.formatMessage(hasErrorName ? errorNameKey : \"errorNames.error\"),\n\t\t\t\t\tmessage: hasErrorMessage\n\t\t\t\t\t\t? I18n.formatMessage(errorMessageKey, err.properties)\n\t\t\t\t\t\t: err.message\n\t\t\t\t};\n\n\t\t\t\tif (Is.stringValue(err.source)) {\n\t\t\t\t\tlocalizedError.source = err.source;\n\t\t\t\t}\n\t\t\t\tif (Is.stringValue(err.stack)) {\n\t\t\t\t\t// Remove the first line from the stack traces as they\n\t\t\t\t\t// just have the error type and message duplicated\n\t\t\t\t\tconst lines = err.stack.split(\"\\n\");\n\t\t\t\t\tlines.shift();\n\t\t\t\t\tlocalizedError.stack = lines.join(\"\\n\");\n\t\t\t\t}\n\n\t\t\t\tconst additional = ErrorHelper.formatValidationErrors(err);\n\t\t\t\tif (Is.arrayValue(additional)) {\n\t\t\t\t\tlocalizedError.additional = additional;\n\t\t\t\t}\n\n\t\t\t\tformattedErrors.push(localizedError);\n\t\t\t}\n\t\t}\n\n\t\treturn formattedErrors;\n\t}\n\n\t/**\n\t * Localize the content of an error and any causes.\n\t * @param error The error to format.\n\t * @returns The localized version of the errors flattened.\n\t */\n\tpublic static formatValidationErrors(error: IError): string[] | undefined {\n\t\tif (\n\t\t\tIs.object(error.properties) &&\n\t\t\tObject.keys(error.properties).length > 0 &&\n\t\t\tIs.object<{ validationFailures: IValidationFailure[] }>(error.properties) &&\n\t\t\tIs.arrayValue(error.properties.validationFailures)\n\t\t) {\n\t\t\tconst validationErrors: string[] = [];\n\t\t\tfor (const validationFailure of error.properties.validationFailures) {\n\t\t\t\tconst errorI18n = `error.${validationFailure.reason}`;\n\t\t\t\tconst errorMessage = I18n.hasMessage(errorI18n)\n\t\t\t\t\t? I18n.formatMessage(errorI18n, validationFailure.properties)\n\t\t\t\t\t: errorI18n;\n\n\t\t\t\tlet v = `${validationFailure.property}: ${errorMessage}`;\n\t\t\t\tif (\n\t\t\t\t\tIs.object<{ value: unknown }>(validationFailure.properties) &&\n\t\t\t\t\tIs.notEmpty(validationFailure.properties.value)\n\t\t\t\t) {\n\t\t\t\t\tv += ` = ${JSON.stringify(validationFailure.properties.value)}`;\n\t\t\t\t}\n\t\t\t\tvalidationErrors.push(v);\n\t\t\t}\n\t\t\treturn validationErrors;\n\t\t}\n\t}\n}\n"]}
@@ -6,20 +6,27 @@ export declare class ErrorHelper {
6
6
  /**
7
7
  * Format Errors and returns just their messages.
8
8
  * @param error The error to format.
9
- * @param includeDetails Whether to include error details, defaults to false.
9
+ * @param options Options for formatting the error.
10
+ * @param options.includeStack Whether to include the stack trace in the output, defaults to false.
11
+ * @param options.includeAdditional Whether to include additional error information in the output, defaults to false.
10
12
  * @returns The error formatted including any causes errors.
11
13
  */
12
- static formatErrors(error: unknown, includeDetails?: boolean): string[];
14
+ static formatErrors(error: unknown, options?: {
15
+ includeStack?: boolean;
16
+ includeAdditional?: boolean;
17
+ }): string[];
13
18
  /**
14
19
  * Localize the content of an error and any causes.
15
20
  * @param error The error to format.
16
21
  * @returns The localized version of the errors flattened.
17
22
  */
18
- static localizeErrors(error: unknown): IError[];
23
+ static localizeErrors(error: unknown): (IError & {
24
+ additional?: string[];
25
+ })[];
19
26
  /**
20
27
  * Localize the content of an error and any causes.
21
28
  * @param error The error to format.
22
29
  * @returns The localized version of the errors flattened.
23
30
  */
24
- static formatValidationErrors(error: IError): string | undefined;
31
+ static formatValidationErrors(error: IError): string[] | undefined;
25
32
  }
package/docs/changelog.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.0.3-next.46](https://github.com/iotaledger/twin-framework/compare/core-v0.0.3-next.45...core-v0.0.3-next.46) (2026-05-22)
4
+
5
+
6
+ ### Features
7
+
8
+ * improve error formatting ([#313](https://github.com/iotaledger/twin-framework/issues/313)) ([5a19623](https://github.com/iotaledger/twin-framework/commit/5a196231bcbf088bf9ba92a93b7478d3b8c5593f))
9
+
10
+
11
+ ### Dependencies
12
+
13
+ * The following workspace dependencies were updated
14
+ * dependencies
15
+ * @twin.org/nameof bumped from 0.0.3-next.45 to 0.0.3-next.46
16
+ * devDependencies
17
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.45 to 0.0.3-next.46
18
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.45 to 0.0.3-next.46
19
+
3
20
  ## [0.0.3-next.45](https://github.com/iotaledger/twin-framework/compare/core-v0.0.3-next.44...core-v0.0.3-next.45) (2026-05-21)
4
21
 
5
22
 
@@ -16,7 +16,7 @@ Error helper functions.
16
16
 
17
17
  ### formatErrors() {#formaterrors}
18
18
 
19
- > `static` **formatErrors**(`error`, `includeDetails?`): `string`[]
19
+ > `static` **formatErrors**(`error`, `options?`): `string`[]
20
20
 
21
21
  Format Errors and returns just their messages.
22
22
 
@@ -28,11 +28,21 @@ Format Errors and returns just their messages.
28
28
 
29
29
  The error to format.
30
30
 
31
- ##### includeDetails?
31
+ ##### options?
32
+
33
+ Options for formatting the error.
34
+
35
+ ###### includeStack?
36
+
37
+ `boolean`
38
+
39
+ Whether to include the stack trace in the output, defaults to false.
40
+
41
+ ###### includeAdditional?
32
42
 
33
43
  `boolean`
34
44
 
35
- Whether to include error details, defaults to false.
45
+ Whether to include additional error information in the output, defaults to false.
36
46
 
37
47
  #### Returns
38
48
 
@@ -44,7 +54,7 @@ The error formatted including any causes errors.
44
54
 
45
55
  ### localizeErrors() {#localizeerrors}
46
56
 
47
- > `static` **localizeErrors**(`error`): [`IError`](../interfaces/IError.md)[]
57
+ > `static` **localizeErrors**(`error`): [`IError`](../interfaces/IError.md) & `object`[]
48
58
 
49
59
  Localize the content of an error and any causes.
50
60
 
@@ -58,7 +68,7 @@ The error to format.
58
68
 
59
69
  #### Returns
60
70
 
61
- [`IError`](../interfaces/IError.md)[]
71
+ [`IError`](../interfaces/IError.md) & `object`[]
62
72
 
63
73
  The localized version of the errors flattened.
64
74
 
@@ -66,7 +76,7 @@ The localized version of the errors flattened.
66
76
 
67
77
  ### formatValidationErrors() {#formatvalidationerrors}
68
78
 
69
- > `static` **formatValidationErrors**(`error`): `string` \| `undefined`
79
+ > `static` **formatValidationErrors**(`error`): `string`[] \| `undefined`
70
80
 
71
81
  Localize the content of an error and any causes.
72
82
 
@@ -80,6 +90,6 @@ The error to format.
80
90
 
81
91
  #### Returns
82
92
 
83
- `string` \| `undefined`
93
+ `string`[] \| `undefined`
84
94
 
85
95
  The localized version of the errors flattened.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@twin.org/core",
3
- "version": "0.0.3-next.45",
3
+ "version": "0.0.3-next.46",
4
4
  "description": "Helper methods/classes for data type checking/validation/guarding/error handling",
5
5
  "repository": {
6
6
  "type": "git",
@@ -14,7 +14,7 @@
14
14
  "node": ">=20.0.0"
15
15
  },
16
16
  "dependencies": {
17
- "@twin.org/nameof": "0.0.3-next.45",
17
+ "@twin.org/nameof": "0.0.3-next.46",
18
18
  "intl-messageformat": "11.2.6",
19
19
  "rfc6902": "5.2.0"
20
20
  },