@visulima/error-handler 1.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.
Files changed (31) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/LICENSE.md +193 -0
  3. package/README.md +388 -0
  4. package/dist/error-handler/html-error-handler.d.ts +16 -0
  5. package/dist/error-handler/html-error-handler.js +63 -0
  6. package/dist/error-handler/json-error-handler.d.ts +17 -0
  7. package/dist/error-handler/json-error-handler.js +31 -0
  8. package/dist/error-handler/jsonapi-error-handler.d.ts +6 -0
  9. package/dist/error-handler/jsonapi-error-handler.js +46 -0
  10. package/dist/error-handler/jsonp-error-handler.d.ts +18 -0
  11. package/dist/error-handler/jsonp-error-handler.js +36 -0
  12. package/dist/error-handler/problem-error-handler.d.ts +6 -0
  13. package/dist/error-handler/problem-error-handler.js +53 -0
  14. package/dist/error-handler/text-error-handler.d.ts +16 -0
  15. package/dist/error-handler/text-error-handler.js +28 -0
  16. package/dist/error-handler/xml-error-handler.d.ts +29 -0
  17. package/dist/error-handler/xml-error-handler.js +45 -0
  18. package/dist/handler/cli-handler.d.ts +30 -0
  19. package/dist/handler/cli-handler.js +173 -0
  20. package/dist/handler/http/fetch-handler.d.ts +11 -0
  21. package/dist/handler/http/fetch-handler.js +267 -0
  22. package/dist/handler/http/node-handler.d.ts +11 -0
  23. package/dist/handler/http/node-handler.js +17 -0
  24. package/dist/index.d.ts +14 -0
  25. package/dist/index.js +8 -0
  26. package/dist/packem_shared/add-status-code-to-response-DdfxTQsK.js +17 -0
  27. package/dist/packem_shared/createNegotiatedErrorHandler-Cd7yj67Z.js +52 -0
  28. package/dist/packem_shared/send-json-o-t1rNfw.js +8 -0
  29. package/dist/packem_shared/set-error-headers-B6ZeX5k4.js +10 -0
  30. package/dist/packem_shared/types.d-DLy8CCca.d.ts +26 -0
  31. package/package.json +151 -0
@@ -0,0 +1,17 @@
1
+ import { IncomingMessage, ServerResponse } from 'node:http';
2
+ import { a as ErrorHandler } from '../packem_shared/types.d-DLy8CCca.js';
3
+
4
+ type JsonErrorBody = Record<string, unknown> | unknown[];
5
+ type JsonErrorFormatter = (params: {
6
+ error: Error;
7
+ request: IncomingMessage;
8
+ response: ServerResponse;
9
+ reasonPhrase: string;
10
+ statusCode: number;
11
+ }) => JsonErrorBody | Promise<JsonErrorBody>;
12
+ type JsonErrorHandlerOptions = {
13
+ formatter?: JsonErrorFormatter;
14
+ };
15
+ declare const jsonErrorHandler: (options?: JsonErrorHandlerOptions) => ErrorHandler;
16
+
17
+ export { type JsonErrorBody, type JsonErrorFormatter, type JsonErrorHandlerOptions, jsonErrorHandler };
@@ -0,0 +1,31 @@
1
+ import { getReasonPhrase } from 'http-status-codes';
2
+ import { a as addStatusCodeToResponse } from '../packem_shared/add-status-code-to-response-DdfxTQsK.js';
3
+ import { s as sendJson } from '../packem_shared/send-json-o-t1rNfw.js';
4
+ import { s as setErrorHeaders } from '../packem_shared/set-error-headers-B6ZeX5k4.js';
5
+
6
+ var __defProp = Object.defineProperty;
7
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
8
+ const jsonErrorHandler = /* @__PURE__ */ __name((options = {}) => {
9
+ return async (error, request, response) => {
10
+ addStatusCodeToResponse(response, error);
11
+ setErrorHeaders(response, error);
12
+ const statusCode = response.statusCode;
13
+ const reasonPhrase = getReasonPhrase(statusCode) || "An error occurred";
14
+ if (options.formatter) {
15
+ const body = await options.formatter({ error, request, response, reasonPhrase, statusCode });
16
+ sendJson(response, body);
17
+ return;
18
+ }
19
+ const expose = error.expose;
20
+ sendJson(response, {
21
+ statusCode,
22
+ // eslint-disable-next-line perfectionist/sort-objects
23
+ error: reasonPhrase,
24
+ // eslint-disable-next-line perfectionist/sort-objects
25
+ message: error.message || reasonPhrase,
26
+ ...expose ? { stack: error.stack } : {}
27
+ });
28
+ };
29
+ }, "jsonErrorHandler");
30
+
31
+ export { jsonErrorHandler };
@@ -0,0 +1,6 @@
1
+ import { a as ErrorHandler } from '../packem_shared/types.d-DLy8CCca.js';
2
+ import 'node:http';
3
+
4
+ declare const jsonapiErrorHandler: ErrorHandler;
5
+
6
+ export { jsonapiErrorHandler as default };
@@ -0,0 +1,46 @@
1
+ import { isHttpError } from 'http-errors';
2
+ import { getReasonPhrase } from 'http-status-codes';
3
+ import tsJapi from 'ts-japi';
4
+ import { a as addStatusCodeToResponse } from '../packem_shared/add-status-code-to-response-DdfxTQsK.js';
5
+ import { s as sendJson } from '../packem_shared/send-json-o-t1rNfw.js';
6
+ import { s as setErrorHeaders } from '../packem_shared/set-error-headers-B6ZeX5k4.js';
7
+
8
+ var __defProp = Object.defineProperty;
9
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
10
+ const defaultTitle = "An error occurred";
11
+ const jsonapiErrorHandler = /* @__PURE__ */ __name((error, _request, response) => {
12
+ addStatusCodeToResponse(response, error);
13
+ setErrorHeaders(response, error);
14
+ if (error instanceof tsJapi.JapiError || tsJapi.JapiError.isLikeJapiError(error)) {
15
+ const serializer = new tsJapi.ErrorSerializer();
16
+ sendJson(response, serializer.serialize(error));
17
+ } else if (isHttpError(error)) {
18
+ const statusCode = "statusCode" in error && typeof error.statusCode === "number" ? error.statusCode : "status" in error && typeof error.status === "number" ? error.status : response.statusCode;
19
+ const title = "title" in error && typeof error.title === "string" ? error.title : void 0;
20
+ const message = "message" in error && typeof error.message === "string" ? error.message : "";
21
+ sendJson(response, {
22
+ errors: [
23
+ {
24
+ code: statusCode ?? response.statusCode,
25
+ title: title || getReasonPhrase(statusCode) || defaultTitle,
26
+ // eslint-disable-next-line perfectionist/sort-objects
27
+ detail: message
28
+ }
29
+ ]
30
+ });
31
+ } else {
32
+ const { message } = error;
33
+ sendJson(response, {
34
+ errors: [
35
+ {
36
+ code: "500",
37
+ title: getReasonPhrase(response.statusCode) || defaultTitle,
38
+ // eslint-disable-next-line perfectionist/sort-objects
39
+ detail: message
40
+ }
41
+ ]
42
+ });
43
+ }
44
+ }, "jsonapiErrorHandler");
45
+
46
+ export { jsonapiErrorHandler as default };
@@ -0,0 +1,18 @@
1
+ import { IncomingMessage, ServerResponse } from 'node:http';
2
+ import { a as ErrorHandler } from '../packem_shared/types.d-DLy8CCca.js';
3
+
4
+ type JsonpErrorBody = Record<string, unknown> | unknown[];
5
+ type JsonpErrorFormatter = (params: {
6
+ error: Error;
7
+ request: IncomingMessage;
8
+ response: ServerResponse;
9
+ reasonPhrase: string;
10
+ statusCode: number;
11
+ }) => JsonpErrorBody | Promise<JsonpErrorBody>;
12
+ type JsonpErrorHandlerOptions = {
13
+ callbackParamName?: string;
14
+ formatter?: JsonpErrorFormatter;
15
+ };
16
+ declare const jsonpErrorHandler: (options?: JsonpErrorHandlerOptions) => ErrorHandler;
17
+
18
+ export { type JsonpErrorBody, type JsonpErrorFormatter, type JsonpErrorHandlerOptions, jsonpErrorHandler };
@@ -0,0 +1,36 @@
1
+ import { getReasonPhrase } from 'http-status-codes';
2
+ import { a as addStatusCodeToResponse } from '../packem_shared/add-status-code-to-response-DdfxTQsK.js';
3
+ import { s as setErrorHeaders } from '../packem_shared/set-error-headers-B6ZeX5k4.js';
4
+
5
+ var __defProp = Object.defineProperty;
6
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
7
+ const defaultCallbackParam = "callback";
8
+ const jsonpErrorHandler = /* @__PURE__ */ __name((options = {}) => {
9
+ return async (error, request, response) => {
10
+ addStatusCodeToResponse(response, error);
11
+ setErrorHeaders(response, error);
12
+ const statusCode = response.statusCode;
13
+ const reasonPhrase = getReasonPhrase(statusCode) || "An error occurred";
14
+ const url = new URL(request.url ?? "http://localhost", "http://localhost");
15
+ const callbackParamName = options.callbackParamName || defaultCallbackParam;
16
+ const callbackName = url.searchParams.get(callbackParamName) || "callback";
17
+ let payload;
18
+ if (options.formatter) {
19
+ payload = await options.formatter({ error, request, response, reasonPhrase, statusCode });
20
+ } else {
21
+ const expose = error.expose;
22
+ payload = {
23
+ statusCode,
24
+ // eslint-disable-next-line perfectionist/sort-objects
25
+ error: reasonPhrase,
26
+ // eslint-disable-next-line perfectionist/sort-objects
27
+ message: error.message || reasonPhrase,
28
+ ...expose ? { stack: error.stack } : {}
29
+ };
30
+ }
31
+ response.setHeader("content-type", "application/javascript; charset=utf-8");
32
+ response.end(`${callbackName}(${JSON.stringify(payload)});`);
33
+ };
34
+ }, "jsonpErrorHandler");
35
+
36
+ export { jsonpErrorHandler };
@@ -0,0 +1,6 @@
1
+ import { a as ErrorHandler } from '../packem_shared/types.d-DLy8CCca.js';
2
+ import 'node:http';
3
+
4
+ declare const problemErrorHandler: ErrorHandler;
5
+
6
+ export { problemErrorHandler as default };
@@ -0,0 +1,53 @@
1
+ import { isHttpError } from 'http-errors';
2
+ import { getReasonPhrase } from 'http-status-codes';
3
+ import { a as addStatusCodeToResponse } from '../packem_shared/add-status-code-to-response-DdfxTQsK.js';
4
+ import { s as sendJson } from '../packem_shared/send-json-o-t1rNfw.js';
5
+ import { s as setErrorHeaders } from '../packem_shared/set-error-headers-B6ZeX5k4.js';
6
+
7
+ var __defProp = Object.defineProperty;
8
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
9
+ const defaultType = "about:blank";
10
+ const defaultTitle = "An error occurred";
11
+ const problemErrorHandler = /* @__PURE__ */ __name((error, _request, response) => {
12
+ const { message, stack } = error;
13
+ if (isHttpError(error)) {
14
+ const expose = "expose" in error ? error.expose : void 0;
15
+ const statusCode = "statusCode" in error && typeof error.statusCode === "number" ? error.statusCode : "status" in error && typeof error.status === "number" ? error.status : response.statusCode;
16
+ const title = "title" in error && typeof error.title === "string" ? error.title : void 0;
17
+ const type = "type" in error && typeof error.type === "string" ? error.type : void 0;
18
+ response.statusCode = statusCode;
19
+ setErrorHeaders(response, error);
20
+ sendJson(
21
+ response,
22
+ {
23
+ type: type || defaultType,
24
+ // eslint-disable-next-line perfectionist/sort-objects
25
+ title: title || getReasonPhrase(statusCode) || defaultTitle,
26
+ // eslint-disable-next-line perfectionist/sort-objects
27
+ status: statusCode,
28
+ // eslint-disable-next-line perfectionist/sort-objects
29
+ detail: message,
30
+ ...expose ? { trace: stack } : {}
31
+ },
32
+ "application/problem+json"
33
+ );
34
+ } else {
35
+ addStatusCodeToResponse(response, error);
36
+ sendJson(
37
+ response,
38
+ {
39
+ type: defaultType,
40
+ // eslint-disable-next-line perfectionist/sort-objects
41
+ title: getReasonPhrase(response.statusCode) || defaultTitle,
42
+ // eslint-disable-next-line perfectionist/sort-objects
43
+ status: response.statusCode,
44
+ // eslint-disable-next-line perfectionist/sort-objects
45
+ detail: message,
46
+ ...error.expose ? { trace: stack } : {}
47
+ },
48
+ "application/problem+json"
49
+ );
50
+ }
51
+ }, "problemErrorHandler");
52
+
53
+ export { problemErrorHandler as default };
@@ -0,0 +1,16 @@
1
+ import { IncomingMessage, ServerResponse } from 'node:http';
2
+ import { a as ErrorHandler } from '../packem_shared/types.d-DLy8CCca.js';
3
+
4
+ type TextErrorFormatter = (params: {
5
+ error: Error;
6
+ request: IncomingMessage;
7
+ response: ServerResponse;
8
+ reasonPhrase: string;
9
+ statusCode: number;
10
+ }) => string | Promise<string>;
11
+ type TextErrorHandlerOptions = {
12
+ formatter?: TextErrorFormatter;
13
+ };
14
+ declare const textErrorHandler: (options?: TextErrorHandlerOptions) => ErrorHandler;
15
+
16
+ export { type TextErrorFormatter, type TextErrorHandlerOptions, textErrorHandler };
@@ -0,0 +1,28 @@
1
+ import { getReasonPhrase } from 'http-status-codes';
2
+ import { a as addStatusCodeToResponse } from '../packem_shared/add-status-code-to-response-DdfxTQsK.js';
3
+ import { s as setErrorHeaders } from '../packem_shared/set-error-headers-B6ZeX5k4.js';
4
+
5
+ var __defProp = Object.defineProperty;
6
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
7
+ const textErrorHandler = /* @__PURE__ */ __name((options = {}) => {
8
+ return async (error, request, response) => {
9
+ addStatusCodeToResponse(response, error);
10
+ setErrorHeaders(response, error);
11
+ const statusCode = response.statusCode;
12
+ const reasonPhrase = getReasonPhrase(statusCode) || "Error";
13
+ response.setHeader("content-type", "text/plain; charset=utf-8");
14
+ if (options.formatter) {
15
+ const text = await options.formatter({ error, request, response, reasonPhrase, statusCode });
16
+ response.end(text);
17
+ return;
18
+ }
19
+ const message = error.message || reasonPhrase;
20
+ const expose = error.expose;
21
+ const stack = expose ? error.stack : void 0;
22
+ response.end(stack ? `${message}
23
+
24
+ ${stack}` : message);
25
+ };
26
+ }, "textErrorHandler");
27
+
28
+ export { textErrorHandler };
@@ -0,0 +1,29 @@
1
+ import { IncomingMessage, ServerResponse } from 'node:http';
2
+ import { a as ErrorHandler } from '../packem_shared/types.d-DLy8CCca.js';
3
+
4
+ type XmlErrorBody = Record<string, unknown> | unknown[];
5
+ type XmlErrorFormatter = (params: {
6
+ error: Error;
7
+ request: IncomingMessage;
8
+ response: ServerResponse;
9
+ reasonPhrase: string;
10
+ statusCode: number;
11
+ }) => XmlErrorBody | Promise<XmlErrorBody>;
12
+ type ToXmlOptions = {
13
+ indent?: string;
14
+ header?: string | boolean;
15
+ attributeReplacements?: Record<string, string>;
16
+ attributeFilter?: (key: string, value: unknown) => boolean;
17
+ attributeExplicitTrue?: boolean;
18
+ contentMap?: (content: string) => string;
19
+ contentReplacements?: Record<string, string>;
20
+ selfCloseTags?: boolean;
21
+ };
22
+ type XmlErrorHandlerOptions = {
23
+ formatter?: XmlErrorFormatter;
24
+ xmlHeader?: boolean;
25
+ toXml?: ToXmlOptions;
26
+ };
27
+ declare const xmlErrorHandler: (options?: XmlErrorHandlerOptions) => ErrorHandler;
28
+
29
+ export { type ToXmlOptions, type XmlErrorBody, type XmlErrorFormatter, type XmlErrorHandlerOptions, xmlErrorHandler };
@@ -0,0 +1,45 @@
1
+ import { getReasonPhrase } from 'http-status-codes';
2
+ import { toXML } from 'jstoxml';
3
+ import { a as addStatusCodeToResponse } from '../packem_shared/add-status-code-to-response-DdfxTQsK.js';
4
+ import { s as setErrorHeaders } from '../packem_shared/set-error-headers-B6ZeX5k4.js';
5
+
6
+ var __defProp = Object.defineProperty;
7
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
8
+ const xmlErrorHandler = /* @__PURE__ */ __name((options = {}) => {
9
+ return async (error, request, response) => {
10
+ addStatusCodeToResponse(response, error);
11
+ setErrorHeaders(response, error);
12
+ const statusCode = response.statusCode;
13
+ const reasonPhrase = getReasonPhrase(statusCode) || "An error occurred";
14
+ let payload;
15
+ if (options.formatter) {
16
+ payload = await options.formatter({ error, request, response, reasonPhrase, statusCode });
17
+ } else {
18
+ const expose = error.expose;
19
+ payload = {
20
+ error: {
21
+ statusCode,
22
+ // eslint-disable-next-line perfectionist/sort-objects
23
+ name: reasonPhrase,
24
+ // eslint-disable-next-line perfectionist/sort-objects
25
+ message: error.message || reasonPhrase,
26
+ ...expose ? { stack: error.stack } : {}
27
+ }
28
+ };
29
+ }
30
+ const xml = toXML(payload, {
31
+ header: options.toXml?.header ?? options.xmlHeader ?? true,
32
+ indent: options.toXml?.indent ?? " ",
33
+ ...options.toXml?.attributeReplacements ? { attributeReplacements: options.toXml.attributeReplacements } : {},
34
+ ...options.toXml?.attributeFilter ? { attributeFilter: options.toXml.attributeFilter } : {},
35
+ ...options.toXml?.attributeExplicitTrue !== void 0 ? { attributeExplicitTrue: options.toXml.attributeExplicitTrue } : {},
36
+ ...options.toXml?.contentMap ? { contentMap: options.toXml.contentMap } : {},
37
+ ...options.toXml?.contentReplacements ? { contentReplacements: options.toXml.contentReplacements } : {},
38
+ ...options.toXml?.selfCloseTags !== void 0 ? { selfCloseTags: options.toXml.selfCloseTags } : {}
39
+ });
40
+ response.setHeader("content-type", "application/xml; charset=utf-8");
41
+ response.end(xml);
42
+ };
43
+ }, "xmlErrorHandler");
44
+
45
+ export { xmlErrorHandler };
@@ -0,0 +1,30 @@
1
+ import { RenderErrorOptions } from '@visulima/error/error';
2
+ import { SolutionFinder } from '@visulima/error/solution';
3
+
4
+ type CliLogger = {
5
+ error: (...arguments_: unknown[]) => void;
6
+ log: (...arguments_: unknown[]) => void;
7
+ };
8
+ type ColorizeMethod = (value: string) => string;
9
+ type BaseCliOptions = {
10
+ solutionTitle?: string;
11
+ solutionFinders?: SolutionFinder[];
12
+ debug?: boolean;
13
+ } & Partial<Omit<RenderErrorOptions, "color">> & {
14
+ color?: {
15
+ codeFrame?: RenderErrorOptions["color"];
16
+ boxen?: {
17
+ headerTextColor?: ColorizeMethod;
18
+ textColor?: ColorizeMethod;
19
+ borderColor?: ColorizeMethod;
20
+ };
21
+ };
22
+ };
23
+ type CliHandlerOptions = BaseCliOptions & {
24
+ logger?: CliLogger;
25
+ };
26
+
27
+ declare const ansiHandler: (error: Error, options?: BaseCliOptions) => Promise<string>;
28
+ declare const cliHandler: (error: Error, options?: CliHandlerOptions) => Promise<void>;
29
+
30
+ export { type BaseCliOptions, type CliHandlerOptions, ansiHandler, cliHandler };
@@ -0,0 +1,173 @@
1
+ import { parseStacktrace } from '@visulima/error/stacktrace';
2
+ import { boxen } from '@visulima/boxen';
3
+ import { renderError } from '@visulima/error/error';
4
+ import { readFile } from 'node:fs/promises';
5
+ import { fileURLToPath } from 'node:url';
6
+ import { ruleBasedFinder, errorHintFinder } from '@visulima/error/solution';
7
+
8
+ var __defProp$3 = Object.defineProperty;
9
+ var __name$3 = (target, value) => __defProp$3(target, "name", { value, configurable: true });
10
+ const ALTERNATIVE_JS_EXTS = ["cjs", "mjs"];
11
+ const ALTERNATIVE_MD_EXTS = ["mdoc"];
12
+ const findLanguageBasedOnExtension = /* @__PURE__ */ __name$3((file) => {
13
+ const cleaned = file.split("?")[0] ?? file;
14
+ const extension = cleaned.split(".").pop()?.toLowerCase();
15
+ if (!extension) {
16
+ return "javascript";
17
+ }
18
+ if (ALTERNATIVE_JS_EXTS.includes(extension)) {
19
+ return "javascript";
20
+ }
21
+ if (ALTERNATIVE_MD_EXTS.includes(extension)) {
22
+ return "markdown";
23
+ }
24
+ switch (extension) {
25
+ case "js": {
26
+ return "javascript";
27
+ }
28
+ case "json": {
29
+ return "json";
30
+ }
31
+ case "json5": {
32
+ return "json5";
33
+ }
34
+ case "jsonc": {
35
+ return "jsonc";
36
+ }
37
+ case "jsx": {
38
+ return "jsx";
39
+ }
40
+ case "sql": {
41
+ return "sql";
42
+ }
43
+ case "ts": {
44
+ return "typescript";
45
+ }
46
+ case "tsx": {
47
+ return "tsx";
48
+ }
49
+ case "xml": {
50
+ return "xml";
51
+ }
52
+ case "md": {
53
+ return "markdown";
54
+ }
55
+ case "mdx": {
56
+ return "mdx";
57
+ }
58
+ default: {
59
+ return "javascript";
60
+ }
61
+ }
62
+ }, "findLanguageBasedOnExtension");
63
+
64
+ var __defProp$2 = Object.defineProperty;
65
+ var __name$2 = (target, value) => __defProp$2(target, "name", { value, configurable: true });
66
+ const cache = /* @__PURE__ */ new Map();
67
+ const getFileSource = /* @__PURE__ */ __name$2(async (file) => {
68
+ if (!/^(?:http|https|file|data):/.test(file)) {
69
+ return void 0;
70
+ }
71
+ if (cache.has(file)) {
72
+ return cache.get(file);
73
+ }
74
+ if (file.startsWith("file:")) {
75
+ try {
76
+ const path = fileURLToPath(file);
77
+ const source = await readFile(path, "utf8");
78
+ cache.set(file, source);
79
+ return source;
80
+ } catch (error) {
81
+ console.log(error);
82
+ return void 0;
83
+ }
84
+ }
85
+ try {
86
+ const response = await fetch(file);
87
+ if (!response.ok) {
88
+ return void 0;
89
+ }
90
+ const source = await response.text();
91
+ cache.set(file, source);
92
+ return source;
93
+ } catch (error) {
94
+ console.log(error);
95
+ return void 0;
96
+ }
97
+ }, "getFileSource");
98
+
99
+ var __defProp$1 = Object.defineProperty;
100
+ var __name$1 = (target, value) => __defProp$1(target, "name", { value, configurable: true });
101
+ const sanitizeTitle = /* @__PURE__ */ __name$1((title) => title.replace(/^\s*#+\s*/, "").trim(), "sanitizeTitle");
102
+ const runSolutionFinders = /* @__PURE__ */ __name$1(async (error, solutionFinders, debug = false) => {
103
+ const candidates = [...solutionFinders, ruleBasedFinder, errorHintFinder];
104
+ const firstTrace = parseStacktrace(error, { frameLimit: 1 })[0] ?? {};
105
+ for await (const handler of candidates.sort((a, b) => a.priority - b.priority)) {
106
+ const { handle, name } = handler;
107
+ if (debug) {
108
+ console.debug(`Running solution finder: ${name}`);
109
+ }
110
+ if (typeof handle !== "function") {
111
+ continue;
112
+ }
113
+ const hint = await handle(error, {
114
+ file: firstTrace.file ?? "",
115
+ language: findLanguageBasedOnExtension(firstTrace.file ?? ""),
116
+ line: firstTrace.line ?? 0,
117
+ snippet: firstTrace.file ? await getFileSource(firstTrace.file) : ""
118
+ });
119
+ if (hint) {
120
+ return hint;
121
+ }
122
+ }
123
+ return void 0;
124
+ }, "runSolutionFinders");
125
+ const buildOutput = /* @__PURE__ */ __name$1(async (error, options) => {
126
+ const { solutionFinders = [], solutionTitle, color, debug = false, ...renderOptions } = options;
127
+ const errorAnsi = renderError(error, {
128
+ ...renderOptions,
129
+ ...color?.codeFrame
130
+ });
131
+ const hint = await runSolutionFinders(error, solutionFinders, debug);
132
+ if (!hint) {
133
+ return { errorAnsi, solutionBox: void 0 };
134
+ }
135
+ const header = sanitizeTitle(hint.header ?? solutionTitle ?? "A possible solution to this error");
136
+ const solutionBox = boxen(hint.body, {
137
+ borderStyle: "round",
138
+ padding: { top: 1, right: 2, bottom: 1, left: 2 },
139
+ margin: { top: 0, right: 0, bottom: 0, left: 0 },
140
+ headerText: `💡 ${header}`,
141
+ headerAlignment: "left",
142
+ textAlignment: "left",
143
+ ...color?.boxen
144
+ });
145
+ return {
146
+ errorAnsi,
147
+ solutionBox
148
+ };
149
+ }, "buildOutput");
150
+ const terminalOutput = /* @__PURE__ */ __name$1(async (error, options = {}) => {
151
+ const { logger = console, ...rest } = options;
152
+ const { errorAnsi, solutionBox } = await buildOutput(error, rest);
153
+ logger.error(errorAnsi);
154
+ if (solutionBox) {
155
+ logger.log("");
156
+ logger.log(solutionBox);
157
+ }
158
+ }, "terminalOutput");
159
+
160
+ var __defProp = Object.defineProperty;
161
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
162
+ const ansiHandler = /* @__PURE__ */ __name(async (error, options = {}) => {
163
+ const { errorAnsi, solutionBox } = await buildOutput(error, options);
164
+ if (solutionBox === void 0) {
165
+ return errorAnsi;
166
+ }
167
+ return `${errorAnsi}
168
+
169
+ ${solutionBox}`;
170
+ }, "ansiHandler");
171
+ const cliHandler = terminalOutput;
172
+
173
+ export { ansiHandler, cliHandler };
@@ -0,0 +1,11 @@
1
+ import { HtmlErrorHandlerOptions } from '../../error-handler/html-error-handler.js';
2
+ import { F as FetchErrorHandlers } from '../../packem_shared/types.d-DLy8CCca.js';
3
+ import 'node:http';
4
+
5
+ declare const fetchHandler: (error: Error, options?: HtmlErrorHandlerOptions & {
6
+ showTrace?: boolean;
7
+ extraHandlers?: FetchErrorHandlers;
8
+ onError?: (error: Error, request: Request) => void | Promise<void>;
9
+ }) => Promise<(request: Request) => Promise<Response>>;
10
+
11
+ export { fetchHandler as default };