@prairielearn/error 2.0.23 → 3.0.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 +12 -0
- package/dist/format.d.ts.map +1 -1
- package/dist/format.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.test.d.ts.map +1 -1
- package/dist/index.test.js.map +1 -1
- package/package.json +11 -7
package/CHANGELOG.md
CHANGED
package/dist/format.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"AAUA;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,SAAI,EAAE,MAAM,SAAK,GAAG,MAAM,CAuBzE;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,CAMrD"}
|
|
1
|
+
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"AAUA;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,SAAI,EAAE,MAAM,SAAK,GAAG,MAAM,CAuBzE;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,CAMrD","sourcesContent":["function indentString(stack: string, depth: number) {\n if (depth === 0) return stack;\n\n const indent = ' '.repeat(depth);\n return stack\n .split('\\n')\n .map((line) => (indent + line).trimEnd())\n .join('\\n');\n}\n\n/**\n * Recursively formats an error into a string. Correctly handles both the\n * `.cause` property and `AggregateError` instances.\n */\nexport function formatErrorStack(err: any, depth = 0, prefix = ''): string {\n // This will handle both circular references and unnecessarily deep chains.\n if (depth > 10) return '...';\n\n let stack = indentString(prefix + err.stack, depth);\n\n if (err.cause) {\n stack += `\\n\\n${formatErrorStack(err.cause, depth + 1, 'Cause: ')}`;\n }\n\n if (err instanceof AggregateError) {\n const indent = ' '.repeat(depth + 1);\n stack += `\\n\\n${indent}Errors: [\\n`;\n\n err.errors.forEach((error, i) => {\n stack += formatErrorStack(error, depth + 2);\n if (i < err.errors.length - 1) stack += '\\n\\n';\n });\n\n stack += `\\n${indent}]`;\n }\n\n return stack;\n}\n\n/**\n * This is a version of {@link formatErrorStack} that won't error in the case\n * of an unexpected error object. We'll use the original function if it works,\n * but if it fails for any reason, we'll just return the plain stack, whatever\n * it might be.\n */\nexport function formatErrorStackSafe(err: any): string {\n try {\n return formatErrorStack(err);\n } catch {\n return err.stack;\n }\n}\n"]}
|
package/dist/format.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format.js","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"AAAA,SAAS,YAAY,CAAC,KAAa,EAAE,KAAa;
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"AAAA,SAAS,YAAY,CAAC,KAAa,EAAE,KAAa,EAAE;IAClD,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;AAAA,CACf;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAQ,EAAE,KAAK,GAAG,CAAC,EAAE,MAAM,GAAG,EAAE,EAAU;IACzE,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,CAAC;YAC/B,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;QAAA,CAChD,CAAC,CAAC;QAEH,KAAK,IAAI,KAAK,MAAM,GAAG,CAAC;IAC1B,CAAC;IAED,OAAO,KAAK,CAAC;AAAA,CACd;AAED;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,GAAQ,EAAU;IACrD,IAAI,CAAC;QACH,OAAO,gBAAgB,CAAC,GAAG,CAAC,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,GAAG,CAAC,KAAK,CAAC;IACnB,CAAC;AAAA,CACF","sourcesContent":["function indentString(stack: string, depth: number) {\n if (depth === 0) return stack;\n\n const indent = ' '.repeat(depth);\n return stack\n .split('\\n')\n .map((line) => (indent + line).trimEnd())\n .join('\\n');\n}\n\n/**\n * Recursively formats an error into a string. Correctly handles both the\n * `.cause` property and `AggregateError` instances.\n */\nexport function formatErrorStack(err: any, depth = 0, prefix = ''): string {\n // This will handle both circular references and unnecessarily deep chains.\n if (depth > 10) return '...';\n\n let stack = indentString(prefix + err.stack, depth);\n\n if (err.cause) {\n stack += `\\n\\n${formatErrorStack(err.cause, depth + 1, 'Cause: ')}`;\n }\n\n if (err instanceof AggregateError) {\n const indent = ' '.repeat(depth + 1);\n stack += `\\n\\n${indent}Errors: [\\n`;\n\n err.errors.forEach((error, i) => {\n stack += formatErrorStack(error, depth + 2);\n if (i < err.errors.length - 1) stack += '\\n\\n';\n });\n\n stack += `\\n${indent}]`;\n }\n\n return stack;\n}\n\n/**\n * This is a version of {@link formatErrorStack} that won't error in the case\n * of an unexpected error object. We'll use the original function if it works,\n * but if it fails for any reason, we'll just return the plain stack, whatever\n * it might be.\n */\nexport function formatErrorStackSafe(err: any): string {\n try {\n return formatErrorStack(err);\n } catch {\n return err.stack;\n }\n}\n"]}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzD,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAErE,UAAU,aAAc,SAAQ,KAAK;IACnC,IAAI,EAAE,GAAG,CAAC;CACX;AAED,UAAU,aAAc,SAAQ,KAAK;IACnC,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,eAAgB,SAAQ,KAAK;IACrC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,sBAAuB,SAAQ,aAAa,EAAE,eAAe;CAAG;AAK1E,wBAAgB,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,eAAe,CAAC;AACvE,wBAAgB,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG,sBAAsB,CAAC;AAQzF,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG,aAAa,CAItE;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,aAAa,CAIzE;AAED,wBAAgB,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,GAAG,aAAa,CAK1D;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAG,aAAa,CAOlE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,GAAG,EACR,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,GAAG,CAAA;CAAE,GAC3E,sBAAsB,CAWxB;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,qBAAa,cAAe,SAAQ,KAAK;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzD,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAErE,UAAU,aAAc,SAAQ,KAAK;IACnC,IAAI,EAAE,GAAG,CAAC;CACX;AAED,UAAU,aAAc,SAAQ,KAAK;IACnC,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,eAAgB,SAAQ,KAAK;IACrC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,sBAAuB,SAAQ,aAAa,EAAE,eAAe;CAAG;AAK1E,wBAAgB,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,eAAe,CAAC;AACvE,wBAAgB,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG,sBAAsB,CAAC;AAQzF,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG,aAAa,CAItE;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,aAAa,CAIzE;AAED,wBAAgB,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,GAAG,aAAa,CAK1D;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAG,aAAa,CAOlE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,GAAG,EACR,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,GAAG,CAAA;CAAE,GAC3E,sBAAsB,CAWxB;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,qBAAa,cAAe,SAAQ,KAAK;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,YAAY,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,qBAAqB,EAK1D;CACF;AAED,qBAAa,eAAgB,SAAQ,KAAK;IACxC,MAAM,EAAE,MAAM,CAAC;IAEf,YAAY,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAG1C;CACF","sourcesContent":["import _ from 'lodash';\n\nimport { type HtmlSafeString } from '@prairielearn/html';\n\nexport { formatErrorStack, formatErrorStackSafe } from './format.js';\n\ninterface ErrorWithData extends Error {\n data: any;\n}\n\ninterface ErrorWithInfo extends Error {\n info: string;\n}\n\ninterface ErrorWithStatus extends Error {\n status: number;\n}\n\ninterface ErrorWithStatusAndData extends ErrorWithData, ErrorWithStatus {}\n\n// TODO: rename all functions include \"error\" in the name so that they can\n// be more easily imported as named imports.\n\nexport function make(status: number, message: string): ErrorWithStatus;\nexport function make(status: number, message: string, data: any): ErrorWithStatusAndData;\nexport function make(status: number, message: string, data?: any): ErrorWithStatusAndData {\n const err = new Error(message) as ErrorWithStatusAndData;\n err.status = status;\n if (data) err.data = data;\n return err;\n}\n\nexport function makeWithData(message: string, data: any): ErrorWithData {\n const err = new Error(message) as ErrorWithData;\n err.data = data;\n return err;\n}\n\nexport function makeWithInfo(message: string, info: string): ErrorWithInfo {\n const err = new Error(message) as ErrorWithInfo;\n err.info = info;\n return err;\n}\n\nexport function addData(err: any, data: any): ErrorWithData {\n const newErr = (_.isError(err) ? err : new Error(String(err))) as ErrorWithData;\n newErr.data = newErr.data || {};\n Object.assign(newErr.data, data);\n return newErr;\n}\n\nexport function newMessage(err: any, newMsg: string): ErrorWithData {\n const newErr = (_.isError(err) ? err : new Error(String(err))) as ErrorWithData;\n newErr.data = newErr.data || {};\n newErr.data._previousMessages = newErr.data._previousMessages || [];\n newErr.data._previousMessages.splice(0, 0, newErr.message);\n newErr.message = `${newMsg}: ${newErr.message}`;\n return newErr;\n}\n\n/**\n * Create a new error based an existing one, optionally adding status, message,\n * and/or data. The existing error will be set as the `cause` of the new error.\n *\n * @param err An existing error.\n * @param param\n * @param param.status Status code to set on the new error.\n * @param param.message Message to add to the new error.\n * @param param.data Data to set on the new error.\n * @returns The augmented error.\n */\nexport function augmentError(\n err: any,\n { status, message, data }: { status?: number; message?: string; data?: any },\n): ErrorWithStatusAndData {\n let newErr: ErrorWithStatusAndData;\n if (err instanceof Error) {\n const combinedMessage = message ? `${message}: ${err.message}` : err.message;\n newErr = new Error(combinedMessage, { cause: err }) as ErrorWithStatusAndData;\n } else {\n newErr = new Error(message ?? String(err)) as ErrorWithStatusAndData;\n }\n newErr.status = status ?? 500;\n newErr.data = data;\n return newErr;\n}\n\nexport interface AugmentedErrorOptions {\n status?: number;\n data?: any;\n info?: HtmlSafeString;\n cause?: unknown;\n}\n\nexport class AugmentedError extends Error {\n status: number;\n data?: any;\n info?: string;\n\n constructor(message: string, options: AugmentedErrorOptions) {\n super(message, { cause: options.cause });\n this.status = options.status ?? 500;\n this.data = options.data;\n this.info = options.info?.toString();\n }\n}\n\nexport class HttpStatusError extends Error {\n status: number;\n\n constructor(status: number, message: string) {\n super(message);\n this.status = status;\n }\n}\n"]}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,QAAQ,CAAC;AAEvB,OAAO,EAAuB,MAAM,oBAAoB,CAAC;AAEzD,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAqBrE,MAAM,UAAU,IAAI,CAAC,MAAc,EAAE,OAAe,EAAE,IAAU;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import _ from 'lodash';\n\nimport { type HtmlSafeString } from '@prairielearn/html';\n\nexport { formatErrorStack, formatErrorStackSafe } from './format.js';\n\ninterface ErrorWithData extends Error {\n data: any;\n}\n\ninterface ErrorWithInfo extends Error {\n info: string;\n}\n\ninterface ErrorWithStatus extends Error {\n status: number;\n}\n\ninterface ErrorWithStatusAndData extends ErrorWithData, ErrorWithStatus {}\n\n// TODO: rename all functions include \"error\" in the name so that they can\n// be more easily imported as named imports.\n\nexport function make(status: number, message: string): ErrorWithStatus;\nexport function make(status: number, message: string, data: any): ErrorWithStatusAndData;\nexport function make(status: number, message: string, data?: any): ErrorWithStatusAndData {\n const err = new Error(message) as ErrorWithStatusAndData;\n err.status = status;\n if (data) err.data = data;\n return err;\n}\n\nexport function makeWithData(message: string, data: any): ErrorWithData {\n const err = new Error(message) as ErrorWithData;\n err.data = data;\n return err;\n}\n\nexport function makeWithInfo(message: string, info: string): ErrorWithInfo {\n const err = new Error(message) as ErrorWithInfo;\n err.info = info;\n return err;\n}\n\nexport function addData(err: any, data: any): ErrorWithData {\n const newErr = (_.isError(err) ? err : new Error(String(err))) as ErrorWithData;\n newErr.data = newErr.data || {};\n Object.assign(newErr.data, data);\n return newErr;\n}\n\nexport function newMessage(err: any, newMsg: string): ErrorWithData {\n const newErr = (_.isError(err) ? err : new Error(String(err))) as ErrorWithData;\n newErr.data = newErr.data || {};\n newErr.data._previousMessages = newErr.data._previousMessages || [];\n newErr.data._previousMessages.splice(0, 0, newErr.message);\n newErr.message = `${newMsg}: ${newErr.message}`;\n return newErr;\n}\n\n/**\n * Create a new error based an existing one, optionally adding status, message,\n * and/or data. The existing error will be set as the `cause` of the new error.\n *\n * @param err An existing error.\n * @param param\n * @param param.status Status code to set on the new error.\n * @param param.message Message to add to the new error.\n * @param param.data Data to set on the new error.\n * @returns The augmented error.\n */\nexport function augmentError(\n err: any,\n { status, message, data }: { status?: number; message?: string; data?: any },\n): ErrorWithStatusAndData {\n let newErr: ErrorWithStatusAndData;\n if (err instanceof Error) {\n const combinedMessage = message ? `${message}: ${err.message}` : err.message;\n newErr = new Error(combinedMessage, { cause: err }) as ErrorWithStatusAndData;\n } else {\n newErr = new Error(message ?? String(err)) as ErrorWithStatusAndData;\n }\n newErr.status = status ?? 500;\n newErr.data = data;\n return newErr;\n}\n\nexport interface AugmentedErrorOptions {\n status?: number;\n data?: any;\n info?: HtmlSafeString;\n cause?: unknown;\n}\n\nexport class AugmentedError extends Error {\n status: number;\n data?: any;\n info?: string;\n\n constructor(message: string, options: AugmentedErrorOptions) {\n super(message, { cause: options.cause });\n this.status = options.status ?? 500;\n this.data = options.data;\n this.info = options.info?.toString();\n }\n}\n\nexport class HttpStatusError extends Error {\n status: number;\n\n constructor(status: number, message: string) {\n super(message);\n this.status = status;\n }\n}\n"]}
|
package/dist/index.test.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"","sourcesContent":["import { assert, describe, it } from 'vitest';\n\nimport { addData, augmentError, make, makeWithData, makeWithInfo, newMessage } from './index.js';\n\ndescribe('make', () => {\n it('makes an error without data', () => {\n const err = make(404, 'Not Found');\n assert.equal(err.status, 404);\n assert.equal(err.message, 'Not Found');\n });\n\n it('makes an error with data', () => {\n const err = make(404, 'Not Found', { foo: 'bar' });\n assert.equal(err.status, 404);\n assert.equal(err.message, 'Not Found');\n assert.equal(err.data.foo, 'bar');\n });\n});\n\ndescribe('makeWithData', () => {\n it('makes an error with the expected properties', () => {\n const err = makeWithData('Not Found', { foo: 'bar' });\n assert.equal(err.message, 'Not Found');\n assert.equal(err.data.foo, 'bar');\n });\n});\n\ndescribe('makeWithInfo', () => {\n it('makes an error with the expected properties', () => {\n const err = makeWithInfo('Not Found', 'bar');\n assert.equal(err.message, 'Not Found');\n assert.equal(err.info, 'bar');\n });\n});\n\ndescribe('addData', () => {\n it('adds data to an error', () => {\n const err = new Error('Not Found');\n const newErr = addData(err, { foo: 'bar' });\n\n assert.equal(err.message, 'Not Found');\n assert.equal((err as any).data.foo, 'bar');\n assert.equal(newErr.message, 'Not Found');\n assert.equal(newErr.data.foo, 'bar');\n });\n\n it('coerces a non-error to a string', () => {\n const newErr = addData('Not Found', { foo: 'bar' });\n assert.equal(newErr.message, 'Not Found');\n assert.equal(newErr.data.foo, 'bar');\n });\n});\n\ndescribe('newMessage', () => {\n it('adds a new message to an error', () => {\n const err = new Error('Not Found');\n const newErr = newMessage(err, '404');\n\n assert.equal(err.message, '404: Not Found');\n assert.equal((err as any).data._previousMessages[0], 'Not Found');\n assert.equal(newErr.message, '404: Not Found');\n assert.equal(newErr.data._previousMessages[0], 'Not Found');\n });\n\n it('coerces a non-error to a string', () => {\n const newErr = newMessage('Not Found', '404');\n assert.equal(newErr.message, '404: Not Found');\n assert.equal(newErr.data._previousMessages[0], 'Not Found');\n });\n});\n\ndescribe('augmentError', () => {\n it('adds status, message, and data to an error', () => {\n const err = new Error('Not Found');\n const newErr = augmentError(err, { status: 404, message: 'Missing', data: { foo: 'bar' } });\n\n assert.equal(newErr.message, 'Missing: Not Found');\n assert.equal(newErr.status, 404);\n assert.equal(newErr.data.foo, 'bar');\n assert.equal(newErr.cause, err);\n assert.equal((newErr.cause as any).message, 'Not Found');\n });\n});\n"]}
|
package/dist/index.test.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.test.js","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEjG,QAAQ,CAAC,MAAM,EAAE,GAAG,EAAE;
|
|
1
|
+
{"version":3,"file":"index.test.js","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { assert, describe, it } from 'vitest';\n\nimport { addData, augmentError, make, makeWithData, makeWithInfo, newMessage } from './index.js';\n\ndescribe('make', () => {\n it('makes an error without data', () => {\n const err = make(404, 'Not Found');\n assert.equal(err.status, 404);\n assert.equal(err.message, 'Not Found');\n });\n\n it('makes an error with data', () => {\n const err = make(404, 'Not Found', { foo: 'bar' });\n assert.equal(err.status, 404);\n assert.equal(err.message, 'Not Found');\n assert.equal(err.data.foo, 'bar');\n });\n});\n\ndescribe('makeWithData', () => {\n it('makes an error with the expected properties', () => {\n const err = makeWithData('Not Found', { foo: 'bar' });\n assert.equal(err.message, 'Not Found');\n assert.equal(err.data.foo, 'bar');\n });\n});\n\ndescribe('makeWithInfo', () => {\n it('makes an error with the expected properties', () => {\n const err = makeWithInfo('Not Found', 'bar');\n assert.equal(err.message, 'Not Found');\n assert.equal(err.info, 'bar');\n });\n});\n\ndescribe('addData', () => {\n it('adds data to an error', () => {\n const err = new Error('Not Found');\n const newErr = addData(err, { foo: 'bar' });\n\n assert.equal(err.message, 'Not Found');\n assert.equal((err as any).data.foo, 'bar');\n assert.equal(newErr.message, 'Not Found');\n assert.equal(newErr.data.foo, 'bar');\n });\n\n it('coerces a non-error to a string', () => {\n const newErr = addData('Not Found', { foo: 'bar' });\n assert.equal(newErr.message, 'Not Found');\n assert.equal(newErr.data.foo, 'bar');\n });\n});\n\ndescribe('newMessage', () => {\n it('adds a new message to an error', () => {\n const err = new Error('Not Found');\n const newErr = newMessage(err, '404');\n\n assert.equal(err.message, '404: Not Found');\n assert.equal((err as any).data._previousMessages[0], 'Not Found');\n assert.equal(newErr.message, '404: Not Found');\n assert.equal(newErr.data._previousMessages[0], 'Not Found');\n });\n\n it('coerces a non-error to a string', () => {\n const newErr = newMessage('Not Found', '404');\n assert.equal(newErr.message, '404: Not Found');\n assert.equal(newErr.data._previousMessages[0], 'Not Found');\n });\n});\n\ndescribe('augmentError', () => {\n it('adds status, message, and data to an error', () => {\n const err = new Error('Not Found');\n const newErr = augmentError(err, { status: 404, message: 'Missing', data: { foo: 'bar' } });\n\n assert.equal(newErr.message, 'Missing: Not Found');\n assert.equal(newErr.status, 404);\n assert.equal(newErr.data.foo, 'bar');\n assert.equal(newErr.cause, err);\n assert.equal((newErr.cause as any).message, 'Not Found');\n });\n});\n"]}
|
package/package.json
CHANGED
|
@@ -1,28 +1,32 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prairielearn/error",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "https://github.com/PrairieLearn/PrairieLearn.git",
|
|
8
8
|
"directory": "packages/error"
|
|
9
9
|
},
|
|
10
|
+
"engines": {
|
|
11
|
+
"node": ">=24.0.0"
|
|
12
|
+
},
|
|
10
13
|
"main": "./dist/index.js",
|
|
11
14
|
"scripts": {
|
|
12
|
-
"build": "
|
|
13
|
-
"dev": "
|
|
15
|
+
"build": "tsgo",
|
|
16
|
+
"dev": "tsgo --watch --preserveWatchOutput",
|
|
14
17
|
"test": "vitest run --coverage"
|
|
15
18
|
},
|
|
16
19
|
"dependencies": {
|
|
17
20
|
"lodash": "^4.17.21"
|
|
18
21
|
},
|
|
19
22
|
"devDependencies": {
|
|
20
|
-
"@prairielearn/html": "^
|
|
23
|
+
"@prairielearn/html": "^5.0.0",
|
|
21
24
|
"@prairielearn/tsconfig": "^0.0.0",
|
|
22
|
-
"@types/node": "^
|
|
23
|
-
"@
|
|
25
|
+
"@types/node": "^24.10.9",
|
|
26
|
+
"@typescript/native-preview": "^7.0.0-dev.20260106.1",
|
|
27
|
+
"@vitest/coverage-v8": "^4.0.17",
|
|
24
28
|
"tsx": "^4.21.0",
|
|
25
29
|
"typescript": "^5.9.3",
|
|
26
|
-
"vitest": "^4.0.
|
|
30
|
+
"vitest": "^4.0.17"
|
|
27
31
|
}
|
|
28
32
|
}
|