@prairielearn/error 1.1.0 → 1.2.0

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @prairielearn/error
2
2
 
3
+ ## 1.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 49a689e: Introduce `formatErrorStack` and `formatErrorStackSafe` functions
8
+
9
+ ## 1.1.1
10
+
11
+ ### Patch Changes
12
+
13
+ - c7e6553: Upgrade all JavaScript dependencies
14
+
3
15
  ## 1.1.0
4
16
 
5
17
  ### Minor Changes
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Recursively formats an error into a string. Correctly handles both the
3
+ * `.cause` property and `AggregateError` instances.
4
+ */
5
+ export declare function formatErrorStack(err: any, depth?: number, prefix?: string): string;
6
+ /**
7
+ * This is a version of {@link formatErrorStack} that won't error in the case
8
+ * of an unexpected error object. We'll use the original function if it works,
9
+ * but if it fails for any reason, we'll just return the plain stack, whatever
10
+ * it might be.
11
+ */
12
+ export declare function formatErrorStackSafe(err: any): string;
package/dist/format.js ADDED
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.formatErrorStackSafe = exports.formatErrorStack = void 0;
4
+ function indentString(stack, depth) {
5
+ if (depth === 0)
6
+ return stack;
7
+ const indent = ' '.repeat(depth);
8
+ return stack
9
+ .split('\n')
10
+ .map((line) => (indent + line).trimEnd())
11
+ .join('\n');
12
+ }
13
+ /**
14
+ * Recursively formats an error into a string. Correctly handles both the
15
+ * `.cause` property and `AggregateError` instances.
16
+ */
17
+ function formatErrorStack(err, depth = 0, prefix = '') {
18
+ // This will handle both circular references and unnecessarily deep chains.
19
+ if (depth > 10)
20
+ return '...';
21
+ let stack = indentString(prefix + err.stack, depth);
22
+ if (err.cause) {
23
+ stack += `\n\n${formatErrorStack(err.cause, depth + 1, 'Cause: ')}`;
24
+ }
25
+ if (err instanceof AggregateError) {
26
+ const indent = ' '.repeat(depth + 1);
27
+ stack += `\n\n${indent}Errors: [\n`;
28
+ err.errors.forEach((error, i) => {
29
+ stack += formatErrorStack(error, depth + 2);
30
+ if (i < err.errors.length - 1)
31
+ stack += '\n\n';
32
+ });
33
+ stack += `\n${indent}]`;
34
+ }
35
+ return stack;
36
+ }
37
+ exports.formatErrorStack = formatErrorStack;
38
+ /**
39
+ * This is a version of {@link formatErrorStack} that won't error in the case
40
+ * of an unexpected error object. We'll use the original function if it works,
41
+ * but if it fails for any reason, we'll just return the plain stack, whatever
42
+ * it might be.
43
+ */
44
+ function formatErrorStackSafe(err) {
45
+ try {
46
+ return formatErrorStack(err);
47
+ }
48
+ catch (e) {
49
+ return err.stack;
50
+ }
51
+ }
52
+ exports.formatErrorStackSafe = formatErrorStackSafe;
53
+ //# sourceMappingURL=format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":";;;AAAA,SAAS,YAAY,CAAC,KAAa,EAAE,KAAa;IAChD,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAE9B,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACpC,OAAO,KAAK;SACT,KAAK,CAAC,IAAI,CAAC;SACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;SACxC,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,SAAgB,gBAAgB,CAAC,GAAQ,EAAE,KAAK,GAAG,CAAC,EAAE,MAAM,GAAG,EAAE;IAC/D,2EAA2E;IAC3E,IAAI,KAAK,GAAG,EAAE;QAAE,OAAO,KAAK,CAAC;IAE7B,IAAI,KAAK,GAAG,YAAY,CAAC,MAAM,GAAG,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAEpD,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;QACd,KAAK,IAAI,OAAO,gBAAgB,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,GAAG,CAAC,EAAE,SAAS,CAAC,EAAE,CAAC;IACtE,CAAC;IAED,IAAI,GAAG,YAAY,cAAc,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;QACxC,KAAK,IAAI,OAAO,MAAM,aAAa,CAAC;QAEpC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE;YAC9B,KAAK,IAAI,gBAAgB,CAAC,KAAK,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;YAC5C,IAAI,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC;gBAAE,KAAK,IAAI,MAAM,CAAC;QACjD,CAAC,CAAC,CAAC;QAEH,KAAK,IAAI,KAAK,MAAM,GAAG,CAAC;IAC1B,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAvBD,4CAuBC;AAED;;;;;GAKG;AACH,SAAgB,oBAAoB,CAAC,GAAQ;IAC3C,IAAI,CAAC;QACH,OAAO,gBAAgB,CAAC,GAAG,CAAC,CAAC;IAC/B,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,GAAG,CAAC,KAAK,CAAC;IACnB,CAAC;AACH,CAAC;AAND,oDAMC"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { HtmlSafeString } from '@prairielearn/html';
2
+ export { formatErrorStack, formatErrorStackSafe } from './format';
2
3
  interface ErrorWithData extends Error {
3
4
  data: any;
4
5
  }
@@ -47,4 +48,3 @@ export declare class HttpStatusError extends Error {
47
48
  status: number;
48
49
  constructor(status: number, message: string);
49
50
  }
50
- export {};
package/dist/index.js CHANGED
@@ -3,8 +3,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.HttpStatusError = exports.AugmentedError = exports.augmentError = exports.newMessage = exports.addData = exports.makeWithInfo = exports.makeWithData = exports.make = void 0;
6
+ exports.HttpStatusError = exports.AugmentedError = exports.augmentError = exports.newMessage = exports.addData = exports.makeWithInfo = exports.makeWithData = exports.make = exports.formatErrorStackSafe = exports.formatErrorStack = void 0;
7
7
  const lodash_1 = __importDefault(require("lodash"));
8
+ var format_1 = require("./format");
9
+ Object.defineProperty(exports, "formatErrorStack", { enumerable: true, get: function () { return format_1.formatErrorStack; } });
10
+ Object.defineProperty(exports, "formatErrorStackSafe", { enumerable: true, get: function () { return format_1.formatErrorStackSafe; } });
8
11
  function make(status, message, data) {
9
12
  const err = new Error(message);
10
13
  err.status = status;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prairielearn/error",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "main": "./dist/index.js",
5
5
  "repository": {
6
6
  "type": "git",
@@ -13,10 +13,10 @@
13
13
  "test": "mocha --no-config --require tsx src/*.test.ts"
14
14
  },
15
15
  "devDependencies": {
16
- "@prairielearn/html": "^3.1.6",
16
+ "@prairielearn/html": "^3.1.7",
17
17
  "@prairielearn/tsconfig": "^0.0.0",
18
18
  "@types/mocha": "^10.0.6",
19
- "@types/node": "^20.11.30",
19
+ "@types/node": "^20.12.2",
20
20
  "chai": "^4.4.1",
21
21
  "mocha": "^10.4.0",
22
22
  "tsx": "^4.7.1",
package/src/format.ts ADDED
@@ -0,0 +1,52 @@
1
+ function indentString(stack: string, depth: number) {
2
+ if (depth === 0) return stack;
3
+
4
+ const indent = ' '.repeat(depth);
5
+ return stack
6
+ .split('\n')
7
+ .map((line) => (indent + line).trimEnd())
8
+ .join('\n');
9
+ }
10
+
11
+ /**
12
+ * Recursively formats an error into a string. Correctly handles both the
13
+ * `.cause` property and `AggregateError` instances.
14
+ */
15
+ export function formatErrorStack(err: any, depth = 0, prefix = ''): string {
16
+ // This will handle both circular references and unnecessarily deep chains.
17
+ if (depth > 10) return '...';
18
+
19
+ let stack = indentString(prefix + err.stack, depth);
20
+
21
+ if (err.cause) {
22
+ stack += `\n\n${formatErrorStack(err.cause, depth + 1, 'Cause: ')}`;
23
+ }
24
+
25
+ if (err instanceof AggregateError) {
26
+ const indent = ' '.repeat(depth + 1);
27
+ stack += `\n\n${indent}Errors: [\n`;
28
+
29
+ err.errors.forEach((error, i) => {
30
+ stack += formatErrorStack(error, depth + 2);
31
+ if (i < err.errors.length - 1) stack += '\n\n';
32
+ });
33
+
34
+ stack += `\n${indent}]`;
35
+ }
36
+
37
+ return stack;
38
+ }
39
+
40
+ /**
41
+ * This is a version of {@link formatErrorStack} that won't error in the case
42
+ * of an unexpected error object. We'll use the original function if it works,
43
+ * but if it fails for any reason, we'll just return the plain stack, whatever
44
+ * it might be.
45
+ */
46
+ export function formatErrorStackSafe(err: any): string {
47
+ try {
48
+ return formatErrorStack(err);
49
+ } catch (e) {
50
+ return err.stack;
51
+ }
52
+ }
package/src/index.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  import _ from 'lodash';
2
2
  import { HtmlSafeString } from '@prairielearn/html';
3
3
 
4
+ export { formatErrorStack, formatErrorStackSafe } from './format';
5
+
4
6
  interface ErrorWithData extends Error {
5
7
  data: any;
6
8
  }