@prairielearn/error 1.0.15 → 1.1.1

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,18 @@
1
1
  # @prairielearn/error
2
2
 
3
+ ## 1.1.1
4
+
5
+ ### Patch Changes
6
+
7
+ - c7e6553: Upgrade all JavaScript dependencies
8
+
9
+ ## 1.1.0
10
+
11
+ ### Minor Changes
12
+
13
+ - 9550c19: Introduce `AugmentedError` and `HttpStatusError` classes
14
+ - 3f2beec: Add `augmentError` function
15
+
3
16
  ## 1.0.15
4
17
 
5
18
  ### Patch Changes
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { HtmlSafeString } from '@prairielearn/html';
1
2
  interface ErrorWithData extends Error {
2
3
  data: any;
3
4
  }
@@ -15,4 +16,35 @@ export declare function makeWithData(message: string, data: any): ErrorWithData;
15
16
  export declare function makeWithInfo(message: string, info: string): ErrorWithInfo;
16
17
  export declare function addData(err: any, data: any): ErrorWithData;
17
18
  export declare function newMessage(err: any, newMsg: string): ErrorWithData;
19
+ /**
20
+ * Create a new error based an existing one, optionally adding status, message,
21
+ * and/or data. The existing error will be set as the `cause` of the new error.
22
+ *
23
+ * @param err An existing error.
24
+ * @param param.status Status code to set on the new error.
25
+ * @param param.message Message to add to the new error.
26
+ * @param param.data Data to set on the new error.
27
+ * @returns The augmented error.
28
+ */
29
+ export declare function augmentError(err: any, { status, message, data }: {
30
+ status?: number;
31
+ message?: string;
32
+ data?: any;
33
+ }): ErrorWithStatusAndData;
34
+ export interface AugmentedErrorOptions {
35
+ status?: number;
36
+ data?: any;
37
+ info?: HtmlSafeString;
38
+ cause?: unknown;
39
+ }
40
+ export declare class AugmentedError extends Error {
41
+ status: number;
42
+ data?: any;
43
+ info?: string;
44
+ constructor(message: string, options: AugmentedErrorOptions);
45
+ }
46
+ export declare class HttpStatusError extends Error {
47
+ status: number;
48
+ constructor(status: number, message: string);
49
+ }
18
50
  export {};
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ 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.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 = void 0;
7
7
  const lodash_1 = __importDefault(require("lodash"));
8
8
  function make(status, message, data) {
9
9
  const err = new Error(message);
@@ -41,4 +41,48 @@ function newMessage(err, newMsg) {
41
41
  return newErr;
42
42
  }
43
43
  exports.newMessage = newMessage;
44
+ /**
45
+ * Create a new error based an existing one, optionally adding status, message,
46
+ * and/or data. The existing error will be set as the `cause` of the new error.
47
+ *
48
+ * @param err An existing error.
49
+ * @param param.status Status code to set on the new error.
50
+ * @param param.message Message to add to the new error.
51
+ * @param param.data Data to set on the new error.
52
+ * @returns The augmented error.
53
+ */
54
+ function augmentError(err, { status, message, data }) {
55
+ let newErr;
56
+ if (err instanceof Error) {
57
+ const combinedMessage = message ? `${message}: ${err.message}` : err.message;
58
+ newErr = new Error(combinedMessage, { cause: err });
59
+ }
60
+ else {
61
+ newErr = new Error(message ?? String(err));
62
+ }
63
+ newErr.status = status ?? 500;
64
+ newErr.data = data;
65
+ return newErr;
66
+ }
67
+ exports.augmentError = augmentError;
68
+ class AugmentedError extends Error {
69
+ status;
70
+ data;
71
+ info;
72
+ constructor(message, options) {
73
+ super(message, { cause: options.cause });
74
+ this.status = options.status ?? 500;
75
+ this.data = options.data;
76
+ this.info = options.info?.toString();
77
+ }
78
+ }
79
+ exports.AugmentedError = AugmentedError;
80
+ class HttpStatusError extends Error {
81
+ status;
82
+ constructor(status, message) {
83
+ super(message);
84
+ this.status = status;
85
+ }
86
+ }
87
+ exports.HttpStatusError = HttpStatusError;
44
88
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;AAAA,oDAAuB;AAqBvB,SAAgB,IAAI,CAAC,MAAc,EAAE,OAAe,EAAE,IAAU;IAC9D,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,OAAO,CAA2B,CAAC;IACzD,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC;IACpB,IAAI,IAAI;QAAE,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC;IAC1B,OAAO,GAAG,CAAC;AACb,CAAC;AALD,oBAKC;AAED,SAAgB,YAAY,CAAC,OAAe,EAAE,IAAS;IACrD,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,OAAO,CAAkB,CAAC;IAChD,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC;IAChB,OAAO,GAAG,CAAC;AACb,CAAC;AAJD,oCAIC;AAED,SAAgB,YAAY,CAAC,OAAe,EAAE,IAAY;IACxD,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,OAAO,CAAkB,CAAC;IAChD,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC;IAChB,OAAO,GAAG,CAAC;AACb,CAAC;AAJD,oCAIC;AAED,SAAgB,OAAO,CAAC,GAAQ,EAAE,IAAS;IACzC,MAAM,MAAM,GAAkB,IAAA,gBAAC,EAAC,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9E,MAAM,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;IAChC,gBAAC,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC5B,OAAO,MAAM,CAAC;AAChB,CAAC;AALD,0BAKC;AAED,SAAgB,UAAU,CAAC,GAAQ,EAAE,MAAc;IACjD,MAAM,MAAM,GAAkB,IAAA,gBAAC,EAAC,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9E,MAAM,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;IAChC,MAAM,CAAC,IAAI,CAAC,iBAAiB,GAAG,MAAM,CAAC,IAAI,CAAC,iBAAiB,IAAI,EAAE,CAAC;IACpE,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IAC3D,MAAM,CAAC,OAAO,GAAG,GAAG,MAAM,KAAK,MAAM,CAAC,OAAO,EAAE,CAAC;IAChD,OAAO,MAAM,CAAC;AAChB,CAAC;AAPD,gCAOC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -59,4 +59,15 @@ describe('newMessage', () => {
59
59
  chai_1.assert.equal(newErr.data._previousMessages[0], 'Not Found');
60
60
  });
61
61
  });
62
+ describe('augmentError', () => {
63
+ it('adds status, message, and data to an error', () => {
64
+ const err = new Error('Not Found');
65
+ const newErr = (0, index_1.augmentError)(err, { status: 404, message: 'Missing', data: { foo: 'bar' } });
66
+ chai_1.assert.equal(newErr.message, 'Missing: Not Found');
67
+ chai_1.assert.equal(newErr.status, 404);
68
+ chai_1.assert.equal(newErr.data.foo, 'bar');
69
+ chai_1.assert.equal(newErr.cause, err);
70
+ chai_1.assert.equal(newErr.cause.message, 'Not Found');
71
+ });
72
+ });
62
73
  //# sourceMappingURL=index.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.test.js","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.test.js","sourceRoot":"","sources":["../src/index.test.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.0.15",
3
+ "version": "1.1.1",
4
4
  "main": "./dist/index.js",
5
5
  "repository": {
6
6
  "type": "git",
@@ -13,9 +13,10 @@
13
13
  "test": "mocha --no-config --require tsx src/*.test.ts"
14
14
  },
15
15
  "devDependencies": {
16
+ "@prairielearn/html": "^3.1.7",
16
17
  "@prairielearn/tsconfig": "^0.0.0",
17
18
  "@types/mocha": "^10.0.6",
18
- "@types/node": "^20.11.30",
19
+ "@types/node": "^20.12.2",
19
20
  "chai": "^4.4.1",
20
21
  "mocha": "^10.4.0",
21
22
  "tsx": "^4.7.1",
package/src/index.test.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { assert } from 'chai';
2
2
 
3
- import { make, makeWithData, addData, newMessage, makeWithInfo } from './index';
3
+ import { make, makeWithData, addData, newMessage, makeWithInfo, augmentError } from './index';
4
4
 
5
5
  describe('make', () => {
6
6
  it('makes an error without data', () => {
@@ -68,3 +68,16 @@ describe('newMessage', () => {
68
68
  assert.equal(newErr.data._previousMessages[0], 'Not Found');
69
69
  });
70
70
  });
71
+
72
+ describe('augmentError', () => {
73
+ it('adds status, message, and data to an error', () => {
74
+ const err = new Error('Not Found');
75
+ const newErr = augmentError(err, { status: 404, message: 'Missing', data: { foo: 'bar' } });
76
+
77
+ assert.equal(newErr.message, 'Missing: Not Found');
78
+ assert.equal(newErr.status, 404);
79
+ assert.equal(newErr.data.foo, 'bar');
80
+ assert.equal(newErr.cause, err);
81
+ assert.equal((newErr.cause as any).message, 'Not Found');
82
+ });
83
+ });
package/src/index.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import _ from 'lodash';
2
+ import { HtmlSafeString } from '@prairielearn/html';
2
3
 
3
4
  interface ErrorWithData extends Error {
4
5
  data: any;
@@ -53,3 +54,58 @@ export function newMessage(err: any, newMsg: string): ErrorWithData {
53
54
  newErr.message = `${newMsg}: ${newErr.message}`;
54
55
  return newErr;
55
56
  }
57
+
58
+ /**
59
+ * Create a new error based an existing one, optionally adding status, message,
60
+ * and/or data. The existing error will be set as the `cause` of the new error.
61
+ *
62
+ * @param err An existing error.
63
+ * @param param.status Status code to set on the new error.
64
+ * @param param.message Message to add to the new error.
65
+ * @param param.data Data to set on the new error.
66
+ * @returns The augmented error.
67
+ */
68
+ export function augmentError(
69
+ err: any,
70
+ { status, message, data }: { status?: number; message?: string; data?: any },
71
+ ): ErrorWithStatusAndData {
72
+ let newErr: ErrorWithStatusAndData;
73
+ if (err instanceof Error) {
74
+ const combinedMessage = message ? `${message}: ${err.message}` : err.message;
75
+ newErr = new Error(combinedMessage, { cause: err }) as ErrorWithStatusAndData;
76
+ } else {
77
+ newErr = new Error(message ?? String(err)) as ErrorWithStatusAndData;
78
+ }
79
+ newErr.status = status ?? 500;
80
+ newErr.data = data;
81
+ return newErr;
82
+ }
83
+
84
+ export interface AugmentedErrorOptions {
85
+ status?: number;
86
+ data?: any;
87
+ info?: HtmlSafeString;
88
+ cause?: unknown;
89
+ }
90
+
91
+ export class AugmentedError extends Error {
92
+ status: number;
93
+ data?: any;
94
+ info?: string;
95
+
96
+ constructor(message: string, options: AugmentedErrorOptions) {
97
+ super(message, { cause: options.cause });
98
+ this.status = options.status ?? 500;
99
+ this.data = options.data;
100
+ this.info = options.info?.toString();
101
+ }
102
+ }
103
+
104
+ export class HttpStatusError extends Error {
105
+ status: number;
106
+
107
+ constructor(status: number, message: string) {
108
+ super(message);
109
+ this.status = status;
110
+ }
111
+ }