@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.
- package/CHANGELOG.md +9 -0
- package/LICENSE.md +193 -0
- package/README.md +388 -0
- package/dist/error-handler/html-error-handler.d.ts +16 -0
- package/dist/error-handler/html-error-handler.js +63 -0
- package/dist/error-handler/json-error-handler.d.ts +17 -0
- package/dist/error-handler/json-error-handler.js +31 -0
- package/dist/error-handler/jsonapi-error-handler.d.ts +6 -0
- package/dist/error-handler/jsonapi-error-handler.js +46 -0
- package/dist/error-handler/jsonp-error-handler.d.ts +18 -0
- package/dist/error-handler/jsonp-error-handler.js +36 -0
- package/dist/error-handler/problem-error-handler.d.ts +6 -0
- package/dist/error-handler/problem-error-handler.js +53 -0
- package/dist/error-handler/text-error-handler.d.ts +16 -0
- package/dist/error-handler/text-error-handler.js +28 -0
- package/dist/error-handler/xml-error-handler.d.ts +29 -0
- package/dist/error-handler/xml-error-handler.js +45 -0
- package/dist/handler/cli-handler.d.ts +30 -0
- package/dist/handler/cli-handler.js +173 -0
- package/dist/handler/http/fetch-handler.d.ts +11 -0
- package/dist/handler/http/fetch-handler.js +267 -0
- package/dist/handler/http/node-handler.d.ts +11 -0
- package/dist/handler/http/node-handler.js +17 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +8 -0
- package/dist/packem_shared/add-status-code-to-response-DdfxTQsK.js +17 -0
- package/dist/packem_shared/createNegotiatedErrorHandler-Cd7yj67Z.js +52 -0
- package/dist/packem_shared/send-json-o-t1rNfw.js +8 -0
- package/dist/packem_shared/set-error-headers-B6ZeX5k4.js +10 -0
- package/dist/packem_shared/types.d-DLy8CCca.d.ts +26 -0
- 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,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,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 };
|