@visulima/error-handler 2.0.0-alpha.8 → 2.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 +463 -0
- package/LICENSE.md +701 -136
- package/README.md +38 -23
- package/dist/error-handler/fetch-utils.d.ts +3 -0
- package/dist/error-handler/fetch-utils.js +1 -0
- package/dist/error-handler/html-error-handler.d.ts +54 -12
- package/dist/error-handler/html-error-handler.js +50 -10
- package/dist/error-handler/json-error-handler.d.ts +13 -12
- package/dist/error-handler/json-error-handler.js +1 -1
- package/dist/error-handler/jsonapi-error-handler.d.ts +3 -2
- package/dist/error-handler/jsonapi-error-handler.js +1 -1
- package/dist/error-handler/jsonp-error-handler.d.ts +14 -13
- package/dist/error-handler/jsonp-error-handler.js +1 -1
- package/dist/error-handler/problem-error-handler.d.ts +6 -5
- package/dist/error-handler/problem-error-handler.js +1 -1
- package/dist/error-handler/text-error-handler.d.ts +12 -11
- package/dist/error-handler/text-error-handler.js +2 -2
- package/dist/error-handler/xml-error-handler.d.ts +24 -23
- package/dist/error-handler/xml-error-handler.js +1 -1
- package/dist/handler/cli-handler.d.ts +27 -4
- package/dist/handler/cli-handler.js +2 -2
- package/dist/handler/http/create-error-middleware.d.ts +31 -0
- package/dist/handler/http/create-error-middleware.js +1 -0
- package/dist/handler/http/fetch-handler.d.ts +9 -7
- package/dist/handler/http/fetch-handler.js +1 -1
- package/dist/handler/http/node-handler.d.ts +9 -8
- package/dist/handler/http/node-handler.js +1 -1
- package/dist/index.d.ts +20 -14
- package/dist/index.js +1 -1
- package/dist/packem_shared/add-status-code-to-response-DwELM1q2.js +1 -0
- package/dist/packem_shared/cliHandler-BGq-ckC0.js +35 -0
- package/dist/packem_shared/createNegotiatedErrorHandler-CcWOSpO5.js +1 -0
- package/dist/packem_shared/extractStatusCode-D0UOgNnr.js +1 -0
- package/dist/packem_shared/fetchCreateNegotiatedErrorHandler-D9YQ8pOH.js +1 -0
- package/dist/packem_shared/fetchHtmlErrorHandler-Cu50Zu5a.js +1 -0
- package/dist/packem_shared/get-file-source-By3_8e1o.js +1 -0
- package/dist/packem_shared/send-json-fz8r6NBW.js +1 -0
- package/dist/packem_shared/sendFetchJson-BNmfrMYp.js +1 -0
- package/dist/packem_shared/set-error-headers-g9hns3cZ.js +1 -0
- package/dist/packem_shared/types.d-Btzbxdod.d.ts +13 -0
- package/package.json +35 -30
- package/dist/error-handler/create-negotiated-error-handler.d.ts +0 -4
- package/dist/error-handler/fetch-create-negotiated-error-handler.d.ts +0 -3
- package/dist/error-handler/fetch-html-error-handler.d.ts +0 -3
- package/dist/error-handler/utils/add-status-code-to-response.d.ts +0 -2
- package/dist/error-handler/utils/send-json.d.ts +0 -8
- package/dist/error-handler/utils/set-error-headers.d.ts +0 -3
- package/dist/packem_shared/add-status-code-to-response-BE6paXjR.js +0 -1
- package/dist/packem_shared/cliHandler-CeQ8tsGj.js +0 -1
- package/dist/packem_shared/createNegotiatedErrorHandler-BLks0_Ak.js +0 -1
- package/dist/packem_shared/send-json-Cedv8-Bt.js +0 -1
- package/dist/packem_shared/set-error-headers-DT9rVGtW.js +0 -1
package/README.md
CHANGED
|
@@ -61,6 +61,9 @@ pnpm add @visulima/error-handler
|
|
|
61
61
|
|
|
62
62
|
### Node.js HTTP Server
|
|
63
63
|
|
|
64
|
+
`httpHandler(error, options?)` is synchronous and returns the `(req, res)`
|
|
65
|
+
request handler — there is no need to `await` it.
|
|
66
|
+
|
|
64
67
|
```ts
|
|
65
68
|
import { createServer } from "node:http";
|
|
66
69
|
import httpHandler from "@visulima/error-handler/handler/http/node";
|
|
@@ -70,10 +73,10 @@ const server = createServer(async (req, res) => {
|
|
|
70
73
|
// your app logic...
|
|
71
74
|
throw new Error("Boom!");
|
|
72
75
|
} catch (error) {
|
|
73
|
-
const handler =
|
|
76
|
+
const handler = httpHandler(error as Error, {
|
|
74
77
|
showTrace: process.env.NODE_ENV !== "production",
|
|
75
78
|
});
|
|
76
|
-
|
|
79
|
+
await handler(req, res);
|
|
77
80
|
}
|
|
78
81
|
});
|
|
79
82
|
|
|
@@ -82,27 +85,36 @@ server.listen(3000);
|
|
|
82
85
|
|
|
83
86
|
### Express Setup
|
|
84
87
|
|
|
88
|
+
Prefer the one-line error middleware instead of wrapping every route in
|
|
89
|
+
`try/catch`. Register `createErrorMiddleware` once and Express will route any
|
|
90
|
+
error (thrown synchronously or passed to `next(error)`) through it:
|
|
91
|
+
|
|
85
92
|
```ts
|
|
86
93
|
import express from "express";
|
|
87
|
-
import
|
|
94
|
+
import { createErrorMiddleware } from "@visulima/error-handler";
|
|
88
95
|
|
|
89
96
|
const app = express();
|
|
90
97
|
app.use(express.json());
|
|
91
98
|
|
|
92
|
-
app.get("/",
|
|
93
|
-
|
|
94
|
-
throw new Error("Example error");
|
|
95
|
-
} catch (error) {
|
|
96
|
-
const handler = await httpHandler(error as Error, {
|
|
97
|
-
showTrace: process.env.NODE_ENV !== "production",
|
|
98
|
-
});
|
|
99
|
-
return handler(req, res);
|
|
100
|
-
}
|
|
99
|
+
app.get("/", () => {
|
|
100
|
+
throw new Error("Example error");
|
|
101
101
|
});
|
|
102
102
|
|
|
103
|
+
// Must be registered last, after your routes.
|
|
104
|
+
app.use(
|
|
105
|
+
createErrorMiddleware({
|
|
106
|
+
showTrace: process.env.NODE_ENV !== "production",
|
|
107
|
+
}),
|
|
108
|
+
);
|
|
109
|
+
|
|
103
110
|
app.listen(3000);
|
|
104
111
|
```
|
|
105
112
|
|
|
113
|
+
> `createErrorMiddleware` is also available as a subpath import:
|
|
114
|
+
> `import createErrorMiddleware from "@visulima/error-handler/handler/middleware";`.
|
|
115
|
+
> If the response has already started streaming (`res.headersSent`) it delegates
|
|
116
|
+
> to `next(error)` so it never double-writes.
|
|
117
|
+
|
|
106
118
|
### Hono (Fetch Runtime)
|
|
107
119
|
|
|
108
120
|
```ts
|
|
@@ -118,7 +130,7 @@ app.get("/error", () => {
|
|
|
118
130
|
});
|
|
119
131
|
|
|
120
132
|
app.onError(async (error, c) => {
|
|
121
|
-
const handler =
|
|
133
|
+
const handler = fetchHandler(error as Error, {
|
|
122
134
|
showTrace: process.env.NODE_ENV !== "production",
|
|
123
135
|
});
|
|
124
136
|
return handler(c.req.raw);
|
|
@@ -138,7 +150,7 @@ export default {
|
|
|
138
150
|
try {
|
|
139
151
|
throw new Error("Boom");
|
|
140
152
|
} catch (error) {
|
|
141
|
-
const handler =
|
|
153
|
+
const handler = fetchHandler(error as Error, {
|
|
142
154
|
showTrace: process.env.NODE_ENV !== "production",
|
|
143
155
|
});
|
|
144
156
|
return handler(request);
|
|
@@ -155,7 +167,7 @@ Deno.serve(async (request: Request) => {
|
|
|
155
167
|
try {
|
|
156
168
|
throw new Error("Boom");
|
|
157
169
|
} catch (error) {
|
|
158
|
-
const handler =
|
|
170
|
+
const handler = fetchHandler(error as Error, {
|
|
159
171
|
showTrace: process.env.NODE_ENV !== "production",
|
|
160
172
|
});
|
|
161
173
|
return handler(request);
|
|
@@ -181,7 +193,7 @@ Add custom handlers for specific content types:
|
|
|
181
193
|
```ts
|
|
182
194
|
import httpHandler from "@visulima/error-handler/handler/http/node";
|
|
183
195
|
|
|
184
|
-
const handler =
|
|
196
|
+
const handler = httpHandler(error, {
|
|
185
197
|
extraHandlers: [
|
|
186
198
|
{
|
|
187
199
|
regex: /application\/yaml/u,
|
|
@@ -196,9 +208,11 @@ const handler = await httpHandler(error, {
|
|
|
196
208
|
|
|
197
209
|
## API
|
|
198
210
|
|
|
199
|
-
### httpHandler(error, options?) =>
|
|
211
|
+
### httpHandler(error, options?) => (req, res) => Promise<void>
|
|
200
212
|
|
|
201
213
|
Node.js HTTP handler for Express, Connect, Fastify, Koa, and similar frameworks.
|
|
214
|
+
The factory is synchronous and returns the `(req, res)` request handler — do not
|
|
215
|
+
`await` it.
|
|
202
216
|
|
|
203
217
|
**Parameters:**
|
|
204
218
|
|
|
@@ -207,15 +221,16 @@ Node.js HTTP handler for Express, Connect, Fastify, Koa, and similar frameworks.
|
|
|
207
221
|
|
|
208
222
|
**Options:**
|
|
209
223
|
|
|
210
|
-
- `showTrace?: boolean` - Include stack trace in responses (default: `
|
|
224
|
+
- `showTrace?: boolean` - Include stack trace in responses (default: `process.env.NODE_ENV !== "production"`)
|
|
211
225
|
- `extraHandlers?: ErrorHandlers` - Custom handlers for specific Accept headers
|
|
212
226
|
- `errorPage?: string | ((params) => string | Promise<string>)` - Custom HTML error page
|
|
213
227
|
- `cspNonce?: string` - Content Security Policy nonce for inline styles
|
|
214
228
|
- `onError?: (error, request, response) => void | Promise<void>` - Callback for custom error logging
|
|
215
229
|
|
|
216
|
-
### fetchHandler(error, options?) =>
|
|
230
|
+
### fetchHandler(error, options?) => (request) => Promise<Response>
|
|
217
231
|
|
|
218
232
|
Fetch API handler for Cloudflare Workers, Deno, Bun, and other Fetch-based runtimes.
|
|
233
|
+
Like `httpHandler`, the factory is synchronous — do not `await` it.
|
|
219
234
|
|
|
220
235
|
**Parameters:**
|
|
221
236
|
|
|
@@ -267,7 +282,7 @@ const server = createServer(async (req, res) => {
|
|
|
267
282
|
try {
|
|
268
283
|
throw new Error("Test error");
|
|
269
284
|
} catch (error) {
|
|
270
|
-
const handler =
|
|
285
|
+
const handler = httpHandler(error as Error, {
|
|
271
286
|
showTrace: process.env.NODE_ENV !== "production",
|
|
272
287
|
});
|
|
273
288
|
return handler(req, res);
|
|
@@ -280,7 +295,7 @@ const server = createServer(async (req, res) => {
|
|
|
280
295
|
```ts
|
|
281
296
|
import httpHandler from "@visulima/error-handler/handler/http/node";
|
|
282
297
|
|
|
283
|
-
const handler =
|
|
298
|
+
const handler = httpHandler(error, {
|
|
284
299
|
errorPage: ({ error, statusCode }) =>
|
|
285
300
|
`<!DOCTYPE html>
|
|
286
301
|
<html>
|
|
@@ -299,7 +314,7 @@ const handler = await httpHandler(error, {
|
|
|
299
314
|
```ts
|
|
300
315
|
import httpHandler from "@visulima/error-handler/handler/http/node";
|
|
301
316
|
|
|
302
|
-
const handler =
|
|
317
|
+
const handler = httpHandler(error, {
|
|
303
318
|
cspNonce: "nonce-abc123", // Will be added to <style> tags
|
|
304
319
|
showTrace: process.env.NODE_ENV !== "production",
|
|
305
320
|
});
|
|
@@ -310,7 +325,7 @@ const handler = await httpHandler(error, {
|
|
|
310
325
|
```ts
|
|
311
326
|
import httpHandler from "@visulima/error-handler/handler/http/node";
|
|
312
327
|
|
|
313
|
-
const handler =
|
|
328
|
+
const handler = httpHandler(error, {
|
|
314
329
|
onError: (error, request, response) => {
|
|
315
330
|
// Log to your preferred logging service
|
|
316
331
|
console.error(`[${new Date().toISOString()}] ${request.method} ${request.url} - ${error.message}`);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{default as a}from"../packem_shared/extractStatusCode-D0UOgNnr.js";import{default as r}from"../packem_shared/sendFetchJson-BNmfrMYp.js";export{a as extractStatusCode,r as sendFetchJson};
|
|
@@ -1,13 +1,55 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
import { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
+
import { E as ErrorHandler } from "../packem_shared/types.d-Btzbxdod.js";
|
|
3
|
+
import { SolutionFinder } from '@visulima/error/solution';
|
|
4
|
+
/**
|
|
5
|
+
* Options that influence how the development HTML error inspector is rendered.
|
|
6
|
+
*/
|
|
7
|
+
type HtmlErrorInspectorOptions = {
|
|
8
|
+
/**
|
|
9
|
+
* Permit the underlying code-frame reader to fetch `http(s):`/`data:`
|
|
10
|
+
* stack-frame URLs over the network. Off by default to avoid an SSRF
|
|
11
|
+
* surface; only enable when frame URLs are known to be trusted.
|
|
12
|
+
* @default false
|
|
13
|
+
*/
|
|
14
|
+
allowRemoteSources?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Number of source lines rendered above the offending line in the code frame.
|
|
17
|
+
* @default 4
|
|
18
|
+
*/
|
|
19
|
+
linesAbove?: number;
|
|
20
|
+
/**
|
|
21
|
+
* Number of source lines rendered below the offending line in the code frame.
|
|
22
|
+
* @default 4
|
|
23
|
+
*/
|
|
24
|
+
linesBelow?: number;
|
|
25
|
+
/**
|
|
26
|
+
* Extra solution finders to run before the built-in rule-based and
|
|
27
|
+
* error-hint finders. The first finder (sorted by descending priority)
|
|
28
|
+
* that returns a hint wins. Matches the CLI handler's behaviour.
|
|
29
|
+
*/
|
|
30
|
+
solutionFinders?: SolutionFinder[];
|
|
12
31
|
};
|
|
13
|
-
|
|
32
|
+
/**
|
|
33
|
+
* Builds the inner HTML for the development error inspector: error name +
|
|
34
|
+
* message, a syntax-free code frame for the offending source line, the parsed
|
|
35
|
+
* stack trace (one entry per cause), and a possible-solution hint.
|
|
36
|
+
*
|
|
37
|
+
* All dynamic content is HTML-escaped. This is intended for development output
|
|
38
|
+
* only — callers must keep it off the production path so stack/source are not
|
|
39
|
+
* leaked.
|
|
40
|
+
* @param error The error to render.
|
|
41
|
+
* @param options Inspector rendering options.
|
|
42
|
+
* @returns The escaped inner HTML for the inspector.
|
|
43
|
+
*/
|
|
44
|
+
declare const htmlErrorHandler: (options?: HtmlErrorHandlerOptions) => ErrorHandler;
|
|
45
|
+
type HtmlErrorHandlerOptions = HtmlErrorInspectorOptions & {
|
|
46
|
+
cspNonce?: string;
|
|
47
|
+
errorPage?: string | ((parameters: {
|
|
48
|
+
error: Error;
|
|
49
|
+
reasonPhrase: string;
|
|
50
|
+
request: IncomingMessage;
|
|
51
|
+
response: ServerResponse;
|
|
52
|
+
statusCode: number;
|
|
53
|
+
}) => string | Promise<string>);
|
|
54
|
+
};
|
|
55
|
+
export { HtmlErrorHandlerOptions, htmlErrorHandler };
|
|
@@ -1,35 +1,75 @@
|
|
|
1
|
-
|
|
1
|
+
import{getReasonPhrase as x}from"http-status-codes";import{a as u}from"../packem_shared/add-status-code-to-response-DwELM1q2.js";import{codeFrame as v}from"@visulima/error/code-frame";import{getErrorCauses as w}from"@visulima/error/error";import{ruleBasedFinder as k,errorHintFinder as S}from"@visulima/error/solution";import{parseStacktrace as $}from"@visulima/error/stacktrace";import{h as j,a as C}from"../packem_shared/get-file-source-By3_8e1o.js";const A=/^\s*#+\s*/,l=e=>e.replaceAll("&","&").replaceAll("<","<").replaceAll(">",">").replaceAll('"',""").replaceAll("'","'"),z=e=>e.replace(A,"").trim(),M=async(e,r,t,o)=>{const n=[...r,k,S].toSorted((i,s)=>i.priority-s.priority);for(const i of n){if(typeof i.handle!="function")continue;const s=await i.handle(e,{file:t.file??"",language:C(t.file??""),line:t.line??0,snippet:o});if(s)return s}},N=e=>{if(!e.file)return l(e.raw);let r=l(e.file);return e.line!==void 0&&(r+=`:${String(e.line)}`,e.column!==void 0&&(r+=`:${String(e.column)}`)),r},E=e=>{if(e.length===0)return"";const r=e.map(t=>{const o=l(t.methodName??"<anonymous>"),n=N(t);return String.raw`<li class="vis-frame"><span class="vis-frame-method">${o}</span><span class="vis-frame-loc">${n}</span></li>`}).join("");return String.raw`<ol class="vis-frames">${r}</ol>`},B=e=>{if(!e)return"";const r=l(z(e.header??"A possible solution to this error")),t=l(e.body);return String.raw`
|
|
2
|
+
<section class="vis-card vis-solution">
|
|
3
|
+
<h2 class="vis-card-title">💡 ${r}</h2>
|
|
4
|
+
<pre class="vis-solution-body">${t}</pre>
|
|
5
|
+
</section>`},F=async(e,r={})=>{const{allowRemoteSources:t=!1,linesAbove:o=4,linesBelow:n=4,solutionFinders:i=[]}=r,s=w(e)[0]??e,c=$(s),a=c.find(d=>!!d.file)??c[0]??{};let m="",g="";if(a.file&&a.line!==void 0){const d=await j(a.file,{allowRemote:t});if(d){g=d;const h=v(d,{start:{column:a.column,line:a.line}},{linesAbove:o,linesBelow:n});m=String.raw`
|
|
6
|
+
<section class="vis-card">
|
|
7
|
+
<h2 class="vis-card-title">${l(`${a.file}:${String(a.line)}`)}</h2>
|
|
8
|
+
<pre class="vis-codeframe"><code>${l(h)}</code></pre>
|
|
9
|
+
</section>`}}const p=await M(e,i,a,g),f=l(e.name||"Error"),b=l(e.message||""),y=c.length>0?String.raw`
|
|
10
|
+
<section class="vis-card">
|
|
11
|
+
<h2 class="vis-card-title">Stack trace</h2>
|
|
12
|
+
${E(c)}
|
|
13
|
+
</section>`:"";return String.raw`
|
|
14
|
+
<div class="vis-inspector max-w-6xl mx-auto px-6 mt-8">
|
|
15
|
+
<section class="vis-card vis-headline">
|
|
16
|
+
<span class="vis-error-name">${f}</span>
|
|
17
|
+
<p class="vis-error-message">${b}</p>
|
|
18
|
+
</section>${m}${B(p)}${y}
|
|
19
|
+
</div>`},I=String.raw`
|
|
20
|
+
.vis-inspector { display: flex; flex-direction: column; gap: 1rem; }
|
|
21
|
+
.vis-card { background: #fff; border-radius: .5rem; box-shadow: 0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px 0 rgba(0,0,0,.06); overflow: hidden; }
|
|
22
|
+
.vis-card-title { margin: 0; padding: .75rem 1.5rem; font-size: .8125rem; font-weight: 600; color: #1a202c; border-bottom: 1px solid #edf2f7; word-break: break-word; }
|
|
23
|
+
.vis-headline { padding: 1rem 1.5rem; }
|
|
24
|
+
.vis-error-name { display: inline-block; font-size: .75rem; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: #e53e3e; }
|
|
25
|
+
.vis-error-message { margin: .5rem 0 0; font-size: 1rem; color: #1a202c; word-break: break-word; }
|
|
26
|
+
.vis-codeframe, .vis-solution-body { margin: 0; padding: 1rem 1.5rem; font-family: Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; font-size: .8125rem; line-height: 1.6; color: #2d3748; white-space: pre; overflow-x: auto; }
|
|
27
|
+
.vis-solution-body { white-space: pre-wrap; word-break: break-word; }
|
|
28
|
+
.vis-frames { margin: 0; padding: 0; list-style: none; }
|
|
29
|
+
.vis-frame { display: flex; flex-direction: column; padding: .5rem 1.5rem; border-bottom: 1px solid #edf2f7; font-family: Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; font-size: .8125rem; }
|
|
30
|
+
.vis-frame:last-child { border-bottom: 0; }
|
|
31
|
+
.vis-frame-method { color: #1a202c; font-weight: 600; }
|
|
32
|
+
.vis-frame-loc { color: #718096; word-break: break-word; }
|
|
33
|
+
@media (prefers-color-scheme: dark) {
|
|
34
|
+
.vis-card { background: #2d3748; }
|
|
35
|
+
.vis-card-title { color: #fff; border-bottom-color: #4a5568; }
|
|
36
|
+
.vis-error-message, .vis-codeframe, .vis-solution-body, .vis-frame-method { color: #e2e8f0; }
|
|
37
|
+
.vis-frame { border-bottom-color: #4a5568; }
|
|
38
|
+
.vis-frame-loc { color: #a0aec0; }
|
|
39
|
+
}`,D=(e={})=>async(r,t,o)=>{u(o,r),o.setHeader("content-type","text/html; charset=utf-8");const n=x(o.statusCode)||"Error",i=e.cspNonce?` nonce="${e.cspNonce}"`:"",{expose:s}=r,c=s?await F(r,{allowRemoteSources:e.allowRemoteSources,linesAbove:e.linesAbove,linesBelow:e.linesBelow,solutionFinders:e.solutionFinders}):"";if(e.errorPage){const a=typeof e.errorPage=="function"?await e.errorPage({error:r,reasonPhrase:n,request:t,response:o,statusCode:o.statusCode}):e.errorPage;if(a){o.end(a);return}}o.end(String.raw`<!DOCTYPE html>
|
|
2
40
|
<html lang="en">
|
|
3
41
|
<head>
|
|
4
42
|
<meta charset="utf-8">
|
|
5
43
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
44
|
|
|
7
|
-
<title>${
|
|
45
|
+
<title>${n}</title>
|
|
8
46
|
<meta name="robots" content="noindex">
|
|
9
47
|
|
|
10
|
-
<style${
|
|
48
|
+
<style${i}>
|
|
11
49
|
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}a{background-color:transparent}code{font-family:monospace,monospace;font-size:1em}[hidden]{display:none}html{font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5}*,:after,:before{box-sizing:border-box;border:0 solid #e2e8f0}a{color:inherit;text-decoration:inherit}code{font-family:Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}svg,video{display:block;vertical-align:middle}video{max-width:100%;height:auto}.bg-white{--bg-opacity:1;background-color:#fff;background-color:rgba(255,255,255,var(--bg-opacity))}.bg-gray-100{--bg-opacity:1;background-color:#f7fafc;background-color:rgba(247,250,252,var(--bg-opacity))}.border-gray-200{--border-opacity:1;border-color:#edf2f7;border-color:rgba(237,242,247,var(--border-opacity))}.border-gray-400{--border-opacity:1;border-color:#cbd5e0;border-color:rgba(203,213,224,var(--border-opacity))}.border-r{border-right-width:1px}.flex{display:flex}.grid{display:grid}.hidden{display:none}.items-center{align-items:center}.justify-center{justify-content:center}.font-semibold{font-weight:600}.h-5{height:1.25rem}.h-8{height:2rem}.h-16{height:4rem}.text-sm{font-size:.875rem}.text-lg{font-size:1.125rem}.leading-7{line-height:1.75rem}.mx-auto{margin-left:auto;margin-right:auto}.ml-1{margin-left:.25rem}.mt-2{margin-top:.5rem}.mr-2{margin-right:.5rem}.ml-2{margin-left:.5rem}.mt-4{margin-top:1rem}.ml-4{margin-left:1rem}.mt-8{margin-top:2rem}.ml-12{margin-left:3rem}.-mt-px{margin-top:-1px}.max-w-xl{max-width:36rem}.max-w-6xl{max-width:72rem}.min-h-screen{min-height:100vh}.overflow-hidden{overflow:hidden}.p-6{padding:1.5rem}.py-4{padding-top:1rem;padding-bottom:1rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.pt-8{padding-top:2rem}.fixed{position:fixed}.relative{position:relative}.top-0{top:0}.right-0{right:0}.shadow{box-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px 0 rgba(0,0,0,.06)}.text-center{text-align:center}.text-gray-200{--text-opacity:1;color:#edf2f7;color:rgba(237,242,247,var(--text-opacity))}.text-gray-300{--text-opacity:1;color:#e2e8f0;color:rgba(226,232,240,var(--text-opacity))}.text-gray-400{--text-opacity:1;color:#cbd5e0;color:rgba(203,213,224,var(--text-opacity))}.text-gray-500{--text-opacity:1;color:#a0aec0;color:rgba(160,174,192,var(--text-opacity))}.text-gray-600{--text-opacity:1;color:#718096;color:rgba(113,128,150,var(--text-opacity))}.text-gray-700{--text-opacity:1;color:#4a5568;color:rgba(74,85,104,var(--text-opacity))}.text-gray-900{--text-opacity:1;color:#1a202c;color:rgba(26,32,44,var(--text-opacity))}.uppercase{text-transform:uppercase}.underline{text-decoration:underline}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.tracking-wider{letter-spacing:.05em}.w-5{width:1.25rem}.w-8{width:2rem}.w-auto{width:auto}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}@media (min-width:640px){.sm\:rounded-lg{border-radius:.5rem}.sm\:block{display:block}.sm\:items-center{align-items:center}.sm\:justify-start{justify-content:flex-start}.sm\:justify-between{justify-content:space-between}.sm\:h-20{height:5rem}.sm\:ml-0{margin-left:0}.sm\:px-6{padding-left:1.5rem;padding-right:1.5rem}.sm\:pt-0{padding-top:0}.sm\:text-left{text-align:left}.sm\:text-right{text-align:right}}@media (min-width:768px){.md\:border-t-0{border-top-width:0}.md\:border-l{border-left-width:1px}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (min-width:1024px){.lg\:px-8{padding-left:2rem;padding-right:2rem}}@media (prefers-color-scheme:dark){.dark\:bg-gray-800{--bg-opacity:1;background-color:#2d3748;background-color:rgba(45,55,72,var(--bg-opacity))}.dark\:bg-gray-900{--bg-opacity:1;background-color:#1a202c;background-color:rgba(26,32,44,var(--bg-opacity))}.dark\:border-gray-700{--border-opacity:1;border-color:#4a5568;border-color:rgba(74,85,104,var(--border-opacity))}.dark\:text-white{--text-opacity:1;color:#fff;color:rgba(255,255,255,var(--text-opacity))}.dark\:text-gray-400{--text-opacity:1;color:#cbd5e0;color:rgba(203,213,224,var(--text-opacity))}}
|
|
12
50
|
</style>
|
|
13
51
|
|
|
14
|
-
<style${
|
|
52
|
+
<style${i}>
|
|
15
53
|
body {
|
|
16
54
|
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
|
17
55
|
}
|
|
18
|
-
</style
|
|
56
|
+
</style>${s?`
|
|
57
|
+
<style${i}>${I}
|
|
58
|
+
</style>`:""}
|
|
19
59
|
</head>
|
|
20
60
|
<body class="antialiased">
|
|
21
|
-
<div class="relative flex items-center justify-center min-h-screen bg-gray-100 dark:bg-gray-900">
|
|
61
|
+
<div class="relative flex items-center justify-center ${s?"pt-8":"min-h-screen"} bg-gray-100 dark:bg-gray-900">
|
|
22
62
|
<div class="max-w-xl mx-auto sm:px-6 lg:px-8">
|
|
23
63
|
<div class="flex items-center justify-center">
|
|
24
64
|
<div class="px-6 text-lg text-gray-600 dark:text-gray-400 border-r border-gray-400 dark:border-gray-700 tracking-wider font-semibold">
|
|
25
|
-
${
|
|
65
|
+
${o.statusCode}
|
|
26
66
|
</div>
|
|
27
67
|
|
|
28
68
|
<div class="ml-4 text-lg text-gray-600 dark:text-gray-400 uppercase tracking-wider">
|
|
29
|
-
${
|
|
69
|
+
${n}
|
|
30
70
|
</div>
|
|
31
71
|
</div>
|
|
32
72
|
</div>
|
|
33
|
-
</div
|
|
73
|
+
</div>${c}
|
|
34
74
|
</body>
|
|
35
|
-
</html>`)}
|
|
75
|
+
</html>`)};export{D as htmlErrorHandler};
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
import { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
+
import { E as ErrorHandler } from "../packem_shared/types.d-Btzbxdod.js";
|
|
3
|
+
type JsonErrorBody = Record<string, unknown> | unknown[];
|
|
4
|
+
type JsonErrorFormatter = (parameters: {
|
|
5
|
+
error: Error;
|
|
6
|
+
reasonPhrase: string;
|
|
7
|
+
request: IncomingMessage;
|
|
8
|
+
response: ServerResponse;
|
|
9
|
+
statusCode: number;
|
|
10
10
|
}) => JsonErrorBody | Promise<JsonErrorBody>;
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
type JsonErrorHandlerOptions = {
|
|
12
|
+
formatter?: JsonErrorFormatter;
|
|
13
13
|
};
|
|
14
|
-
|
|
14
|
+
declare const jsonErrorHandler: (options?: JsonErrorHandlerOptions) => ErrorHandler;
|
|
15
|
+
export { JsonErrorBody, JsonErrorFormatter, JsonErrorHandlerOptions, jsonErrorHandler };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
import{getReasonPhrase as p}from"http-status-codes";import{a as f}from"../packem_shared/add-status-code-to-response-DwELM1q2.js";import{o as a}from"../packem_shared/send-json-fz8r6NBW.js";import{o as i}from"../packem_shared/set-error-headers-g9hns3cZ.js";const h=(t={})=>async(r,m,e)=>{f(e,r),i(e,r);const{statusCode:s}=e,o=p(s)||"An error occurred";if(t.formatter){const c=await t.formatter({error:r,reasonPhrase:o,request:m,response:e,statusCode:s});a(e,c);return}const{expose:n}=r;a(e,{message:r.message||o,error:o,statusCode:s,...n?{stack:r.stack}:{}})};export{h as jsonErrorHandler};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { E as ErrorHandler } from "../packem_shared/types.d-Btzbxdod.js";
|
|
2
|
+
import 'node:http';
|
|
2
3
|
declare const jsonapiErrorHandler: ErrorHandler;
|
|
3
|
-
export default
|
|
4
|
+
export { jsonapiErrorHandler as default };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
import{isHttpError as f}from"http-errors";import{getReasonPhrase as m}from"http-status-codes";import i from"ts-japi";import{a as p}from"../packem_shared/add-status-code-to-response-DwELM1q2.js";import{o as t}from"../packem_shared/send-json-fz8r6NBW.js";import{o as l}from"../packem_shared/set-error-headers-g9hns3cZ.js";const u=(e,a)=>"statusCode"in e&&typeof e.statusCode=="number"?e.statusCode:"status"in e&&typeof e.status=="number"?e.status:a,J=(e,a,r)=>{if(p(r,e),l(r,e),e instanceof i.JapiError||i.JapiError.isLikeJapiError(e)){const o=new i.ErrorSerializer;t(r,o.serialize(e))}else if(f(e)){const o=u(e,r.statusCode),s="title"in e&&typeof e.title=="string"?e.title:void 0,n="message"in e&&typeof e.message=="string"?e.message:"";t(r,{errors:[{code:o,title:s??m(o),detail:n}]})}else{const{message:o}=e,{statusCode:s}=r;t(r,{errors:[{code:s,title:m(s),detail:o}]})}};export{J as default};
|
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
import { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
+
import { E as ErrorHandler } from "../packem_shared/types.d-Btzbxdod.js";
|
|
3
|
+
declare const jsonpErrorHandler: (options?: JsonpErrorHandlerOptions) => ErrorHandler;
|
|
4
|
+
type JsonpErrorBody = Record<string, unknown> | unknown[];
|
|
5
|
+
type JsonpErrorFormatter = (parameters: {
|
|
6
|
+
error: Error;
|
|
7
|
+
reasonPhrase: string;
|
|
8
|
+
request: IncomingMessage;
|
|
9
|
+
response: ServerResponse;
|
|
10
|
+
statusCode: number;
|
|
10
11
|
}) => JsonpErrorBody | Promise<JsonpErrorBody>;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
type JsonpErrorHandlerOptions = {
|
|
13
|
+
callbackParamName?: string;
|
|
14
|
+
formatter?: JsonpErrorFormatter;
|
|
14
15
|
};
|
|
15
|
-
export
|
|
16
|
+
export { JsonpErrorBody, JsonpErrorFormatter, JsonpErrorHandlerOptions, jsonpErrorHandler };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
import{getReasonPhrase as f}from"http-status-codes";import{a as h}from"../packem_shared/add-status-code-to-response-DwELM1q2.js";import{o as d}from"../packem_shared/set-error-headers-g9hns3cZ.js";const c="callback",g=/^[A-Za-z_$][\w$.]*$/u,k=(s={})=>async(e,l,t)=>{h(t,e),d(t,e);const{statusCode:o}=t,r=f(o),p=new URL(l.url??"http://localhost","http://localhost"),i=s.callbackParamName??c;let a=p.searchParams.get(i)??c,n;if(s.formatter)n=await s.formatter({error:e,reasonPhrase:r,request:l,response:t,statusCode:o});else{const{expose:u}=e;n={message:e.message||r,error:r,statusCode:o,...u?{stack:e.stack}:{}}}(a.length>64||!g.test(a))&&(a=c),t.setHeader("content-type","application/javascript; charset=utf-8"),t.setHeader("x-content-type-options","nosniff");const m=JSON.stringify(n).replaceAll("\u2028",String.raw`\u2028`).replaceAll("\u2029",String.raw`\u2029`);t.end(`/**/ typeof ${a} === 'function' && ${a}(${m});`)};export{k as jsonpErrorHandler};
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { E as ErrorHandler } from "../packem_shared/types.d-Btzbxdod.js";
|
|
2
|
+
import 'node:http';
|
|
2
3
|
/**
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
* Normalizes errors according to the API Problem spec (RFC 7807).
|
|
5
|
+
* @see https://tools.ietf.org/html/rfc7807
|
|
6
|
+
*/
|
|
6
7
|
declare const problemErrorHandler: ErrorHandler;
|
|
7
|
-
export default
|
|
8
|
+
export { problemErrorHandler as default };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
import{isHttpError as d}from"http-errors";import{getReasonPhrase as p}from"http-status-codes";import{a as f}from"../packem_shared/add-status-code-to-response-DwELM1q2.js";import{o as r}from"../packem_shared/send-json-fz8r6NBW.js";import{o as c}from"../packem_shared/set-error-headers-g9hns3cZ.js";const n="about:blank",y=(t,s)=>"statusCode"in t&&typeof t.statusCode=="number"?t.statusCode:"status"in t&&typeof t.status=="number"?t.status:s,$=(t,s,e)=>{const{message:a,stack:i}=t;if(d(t)){const m="expose"in t?t.expose:void 0,o=y(t,e.statusCode),u="title"in t&&typeof t.title=="string"?t.title:void 0,l="type"in t&&typeof t.type=="string"?t.type:void 0;e.statusCode=o,c(e,t),r(e,{type:l??n,title:u??p(o),status:o,detail:a,...m?{trace:i}:{}},"application/problem+json")}else f(e,t),r(e,{type:n,title:p(e.statusCode),status:e.statusCode,detail:a,...t.expose?{trace:i}:{}},"application/problem+json")};export{$ as default};
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
import { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
+
import { E as ErrorHandler } from "../packem_shared/types.d-Btzbxdod.js";
|
|
3
|
+
type TextErrorFormatter = (parameters: {
|
|
4
|
+
error: Error;
|
|
5
|
+
reasonPhrase: string;
|
|
6
|
+
request: IncomingMessage;
|
|
7
|
+
response: ServerResponse;
|
|
8
|
+
statusCode: number;
|
|
9
9
|
}) => string | Promise<string>;
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
type TextErrorHandlerOptions = {
|
|
11
|
+
formatter?: TextErrorFormatter;
|
|
12
12
|
};
|
|
13
|
-
|
|
13
|
+
declare const textErrorHandler: (options?: TextErrorHandlerOptions) => ErrorHandler;
|
|
14
|
+
export { TextErrorFormatter, TextErrorHandlerOptions, textErrorHandler };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
|
|
1
|
+
import{getReasonPhrase as i}from"http-status-codes";import{a as d}from"../packem_shared/add-status-code-to-response-DwELM1q2.js";import{o as f}from"../packem_shared/set-error-headers-g9hns3cZ.js";const h=(o={})=>async(e,m,t)=>{d(t,e),f(t,e);const{statusCode:r}=t,s=i(r)||"Error";if(t.setHeader("content-type","text/plain; charset=utf-8"),o.formatter){const c=await o.formatter({error:e,reasonPhrase:s,request:m,response:t,statusCode:r});t.end(c);return}const a=e.message||s,{expose:p}=e,n=p?e.stack:void 0;t.end(n?`${a}
|
|
2
2
|
|
|
3
|
-
${n}`:
|
|
3
|
+
${n}`:a)};export{h as textErrorHandler};
|
|
@@ -1,26 +1,27 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
import { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
+
import { E as ErrorHandler } from "../packem_shared/types.d-Btzbxdod.js";
|
|
3
|
+
type XmlErrorBody = Record<string, unknown> | unknown[];
|
|
4
|
+
type XmlErrorFormatter = (parameters: {
|
|
5
|
+
error: Error;
|
|
6
|
+
reasonPhrase: string;
|
|
7
|
+
request: IncomingMessage;
|
|
8
|
+
response: ServerResponse;
|
|
9
|
+
statusCode: number;
|
|
10
10
|
}) => XmlErrorBody | Promise<XmlErrorBody>;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
11
|
+
type ToXmlOptions = {
|
|
12
|
+
attributeExplicitTrue?: boolean;
|
|
13
|
+
attributeFilter?: (key: string, value: unknown) => boolean;
|
|
14
|
+
attributeReplacements?: Record<string, string>;
|
|
15
|
+
contentMap?: (content: string) => string;
|
|
16
|
+
contentReplacements?: Record<string, string>;
|
|
17
|
+
header?: string | boolean;
|
|
18
|
+
indent?: string;
|
|
19
|
+
selfCloseTags?: boolean;
|
|
20
20
|
};
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
type XmlErrorHandlerOptions = {
|
|
22
|
+
formatter?: XmlErrorFormatter;
|
|
23
|
+
toXml?: ToXmlOptions;
|
|
24
|
+
xmlHeader?: boolean;
|
|
25
25
|
};
|
|
26
|
-
|
|
26
|
+
declare const xmlErrorHandler: (options?: XmlErrorHandlerOptions) => ErrorHandler;
|
|
27
|
+
export { ToXmlOptions, XmlErrorBody, XmlErrorFormatter, XmlErrorHandlerOptions, xmlErrorHandler };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
import{getReasonPhrase as i}from"http-status-codes";import{toXML as c}from"jstoxml";import{a as p}from"../packem_shared/add-status-code-to-response-DwELM1q2.js";import{o as u}from"../packem_shared/set-error-headers-g9hns3cZ.js";const x=(t={})=>async(e,l,o)=>{p(o,e),u(o,e);const{statusCode:r}=o,a=i(r)||"An error occurred";let s;if(t.formatter)s=await t.formatter({error:e,reasonPhrase:a,request:l,response:o,statusCode:r});else{const{expose:m}=e;s={error:{statusCode:r,name:a,message:e.message||a,...m?{stack:e.stack}:{}}}}const n=c(s,{header:t.toXml?.header??t.xmlHeader??!0,indent:t.toXml?.indent??" ",...t.toXml?.attributeReplacements?{attributeReplacements:t.toXml.attributeReplacements}:{},...t.toXml?.attributeFilter?{attributeFilter:t.toXml.attributeFilter}:{},...t.toXml?.attributeExplicitTrue===void 0?{}:{attributeExplicitTrue:t.toXml.attributeExplicitTrue},...t.toXml?.contentMap?{contentMap:t.toXml.contentMap}:{},...t.toXml?.contentReplacements?{contentReplacements:t.toXml.contentReplacements}:{},...t.toXml?.selfCloseTags===void 0?{}:{selfCloseTags:t.toXml.selfCloseTags}});o.setHeader("content-type","application/xml; charset=utf-8"),o.end(n)};export{x as xmlErrorHandler};
|
|
@@ -1,4 +1,27 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { RenderErrorOptions } from '@visulima/error/error';
|
|
2
|
+
import { SolutionFinder } from '@visulima/error/solution';
|
|
3
|
+
type CliLogger = {
|
|
4
|
+
error: (...arguments_: unknown[]) => void;
|
|
5
|
+
log: (...arguments_: unknown[]) => void;
|
|
6
|
+
};
|
|
7
|
+
type ColorizeMethod = (value: string) => string;
|
|
8
|
+
type BaseCliOptions = {
|
|
9
|
+
solutionTitle?: string;
|
|
10
|
+
solutionFinders?: SolutionFinder[];
|
|
11
|
+
debug?: boolean;
|
|
12
|
+
} & Partial<Omit<RenderErrorOptions, "color">> & {
|
|
13
|
+
color?: {
|
|
14
|
+
codeFrame?: RenderErrorOptions["color"];
|
|
15
|
+
boxen?: {
|
|
16
|
+
headerTextColor?: ColorizeMethod;
|
|
17
|
+
textColor?: ColorizeMethod;
|
|
18
|
+
borderColor?: ColorizeMethod;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
type CliHandlerOptions = BaseCliOptions & {
|
|
23
|
+
logger?: CliLogger;
|
|
24
|
+
};
|
|
25
|
+
declare const terminalOutput: (error: Error, options?: CliHandlerOptions) => Promise<void>;
|
|
26
|
+
declare const ansiHandler: (error: Error, options?: BaseCliOptions) => Promise<string>;
|
|
27
|
+
export { type BaseCliOptions, type CliHandlerOptions, ansiHandler, terminalOutput as cliHandler };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
|
|
1
|
+
import{buildOutput as n}from"../packem_shared/cliHandler-BGq-ckC0.js";import{terminalOutput as l}from"../packem_shared/cliHandler-BGq-ckC0.js";const e=async(o,i={})=>{const{errorAnsi:r,solutionBox:t}=await n(o,i);return t===void 0?r:`${r}
|
|
2
2
|
|
|
3
|
-
${
|
|
3
|
+
${t}`};export{e as ansiHandler,l as cliHandler};
|