h3 0.7.10 → 0.7.13

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/dist/index.cjs CHANGED
@@ -82,7 +82,7 @@ function handleCacheHeaders(event, opts) {
82
82
  const cacheControls = ["public"].concat(opts.cacheControls || []);
83
83
  let cacheMatched = false;
84
84
  if (opts.maxAge !== void 0) {
85
- opts.cacheControls?.push(`max-age=${+opts.maxAge}`, `s-maxage=${+opts.maxAge}`);
85
+ cacheControls.push(`max-age=${+opts.maxAge}`, `s-maxage=${+opts.maxAge}`);
86
86
  }
87
87
  if (opts.modifiedTime) {
88
88
  const modifiedTime = new Date(opts.modifiedTime);
@@ -135,7 +135,12 @@ function defaultContentType(event, type) {
135
135
  function sendRedirect(event, location, code = 302) {
136
136
  event.res.statusCode = code;
137
137
  event.res.setHeader("Location", location);
138
- return send(event, "Redirecting to " + location, MIMES.html);
138
+ const html = `<!DOCTYPE html>
139
+ <html>
140
+ <head><meta http-equiv="refresh" content="0; url=${encodeURI(location)}"></head>
141
+ <body>Redirecting to <a href=${JSON.stringify(location)}>${encodeURI(location)}</a></body>
142
+ </html>`;
143
+ return send(event, html, MIMES.html);
139
144
  }
140
145
  function appendHeader(event, name, value) {
141
146
  let current = event.res.getHeader(name);
@@ -183,14 +188,17 @@ class H3Error extends Error {
183
188
  constructor() {
184
189
  super(...arguments);
185
190
  this.statusCode = 500;
191
+ this.fatal = false;
192
+ this.unhandled = false;
186
193
  this.statusMessage = "Internal Server Error";
187
194
  }
188
195
  }
196
+ H3Error.__h3_error__ = true;
189
197
  function createError(input) {
190
198
  if (typeof input === "string") {
191
199
  return new H3Error(input);
192
200
  }
193
- if (input instanceof H3Error) {
201
+ if (isError(input)) {
194
202
  return input;
195
203
  }
196
204
  const err = new H3Error(input.message ?? input.statusMessage, input.cause ? { cause: input.cause } : void 0);
@@ -203,6 +211,12 @@ function createError(input) {
203
211
  if (input.data) {
204
212
  err.data = input.data;
205
213
  }
214
+ if (input.fatal !== void 0) {
215
+ err.fatal = input.fatal;
216
+ }
217
+ if (input.unhandled !== void 0) {
218
+ err.unhandled = input.unhandled;
219
+ }
206
220
  return err;
207
221
  }
208
222
  function sendError(event, error, debug) {
@@ -228,7 +242,7 @@ function sendError(event, error, debug) {
228
242
  event.res.end(JSON.stringify(responseBody, null, 2));
229
243
  }
230
244
  function isError(input) {
231
- return input instanceof H3Error;
245
+ return input?.constructor?.__h3_error__ === true;
232
246
  }
233
247
 
234
248
  const defineHandler = (handler) => handler;
@@ -376,14 +390,18 @@ function createApp(options = {}) {
376
390
  const event = createEvent(req, res);
377
391
  try {
378
392
  await handler(event);
379
- } catch (err) {
393
+ } catch (_error) {
394
+ const error = createError(_error);
395
+ if (!isError(_error)) {
396
+ error.unhandled = true;
397
+ }
398
+ if (error.unhandled || error.fatal) {
399
+ console.error("[h3]", error.fatal ? "[fatal]" : "[unhandled]", error);
400
+ }
380
401
  if (options.onError) {
381
- await options.onError(err, event);
402
+ await options.onError(error, event);
382
403
  } else {
383
- if (!isError(err)) {
384
- console.error("[h3]", err);
385
- }
386
- await sendError(event, err, !!options.debug);
404
+ await sendError(event, error, !!options.debug);
387
405
  }
388
406
  }
389
407
  };
@@ -434,8 +452,11 @@ function createAppEventHandler(stack, options) {
434
452
  return send(event, val, MIMES.html);
435
453
  } else if (isStream(val)) {
436
454
  return sendStream(event, val);
455
+ } else if (val === null) {
456
+ event.res.statusCode = 204;
457
+ return send(event);
437
458
  } else if (type === "object" || type === "boolean" || type === "number") {
438
- if (val && val.buffer) {
459
+ if (val.buffer) {
439
460
  return send(event, val);
440
461
  } else if (val instanceof Error) {
441
462
  throw createError(val);
package/dist/index.d.ts CHANGED
@@ -98,12 +98,17 @@ declare function createAppEventHandler(stack: Stack, options: AppOptions): Event
98
98
  * @extends Error
99
99
  * @property {Number} statusCode An Integer indicating the HTTP response status code.
100
100
  * @property {String} statusMessage A String representing the HTTP status message
101
+ * @property {String} fatal Indicates if the error is a fatal error.
102
+ * @property {String} unhandled Indicates if the error was unhandled and auto captured.
101
103
  * @property {Any} data An extra data that will includes in the response.<br>
102
104
  * This can be used to pass additional information about the error.
103
105
  * @property {Boolean} internal Setting this property to <code>true</code> will mark error as an internal error
104
106
  */
105
107
  declare class H3Error extends Error {
108
+ static __h3_error__: boolean;
106
109
  statusCode: number;
110
+ fatal: boolean;
111
+ unhandled: boolean;
107
112
  statusMessage: string;
108
113
  data?: any;
109
114
  }
@@ -225,7 +230,7 @@ declare function useMethod(event: CompatibilityEvent, defaultMethod?: HTTPMethod
225
230
  declare function isMethod(event: CompatibilityEvent, expected: HTTPMethod | HTTPMethod[], allowHead?: boolean): boolean;
226
231
  declare function assertMethod(event: CompatibilityEvent, expected: HTTPMethod | HTTPMethod[], allowHead?: boolean): void;
227
232
 
228
- declare function send(event: CompatibilityEvent, data: any, type?: string): Promise<void>;
233
+ declare function send(event: CompatibilityEvent, data?: any, type?: string): Promise<void>;
229
234
  declare function defaultContentType(event: CompatibilityEvent, type?: string): void;
230
235
  declare function sendRedirect(event: CompatibilityEvent, location: string, code?: number): Promise<void>;
231
236
  declare function appendHeader(event: CompatibilityEvent, name: string, value: string): void;
package/dist/index.mjs CHANGED
@@ -74,7 +74,7 @@ function handleCacheHeaders(event, opts) {
74
74
  const cacheControls = ["public"].concat(opts.cacheControls || []);
75
75
  let cacheMatched = false;
76
76
  if (opts.maxAge !== void 0) {
77
- opts.cacheControls?.push(`max-age=${+opts.maxAge}`, `s-maxage=${+opts.maxAge}`);
77
+ cacheControls.push(`max-age=${+opts.maxAge}`, `s-maxage=${+opts.maxAge}`);
78
78
  }
79
79
  if (opts.modifiedTime) {
80
80
  const modifiedTime = new Date(opts.modifiedTime);
@@ -127,7 +127,12 @@ function defaultContentType(event, type) {
127
127
  function sendRedirect(event, location, code = 302) {
128
128
  event.res.statusCode = code;
129
129
  event.res.setHeader("Location", location);
130
- return send(event, "Redirecting to " + location, MIMES.html);
130
+ const html = `<!DOCTYPE html>
131
+ <html>
132
+ <head><meta http-equiv="refresh" content="0; url=${encodeURI(location)}"></head>
133
+ <body>Redirecting to <a href=${JSON.stringify(location)}>${encodeURI(location)}</a></body>
134
+ </html>`;
135
+ return send(event, html, MIMES.html);
131
136
  }
132
137
  function appendHeader(event, name, value) {
133
138
  let current = event.res.getHeader(name);
@@ -175,14 +180,17 @@ class H3Error extends Error {
175
180
  constructor() {
176
181
  super(...arguments);
177
182
  this.statusCode = 500;
183
+ this.fatal = false;
184
+ this.unhandled = false;
178
185
  this.statusMessage = "Internal Server Error";
179
186
  }
180
187
  }
188
+ H3Error.__h3_error__ = true;
181
189
  function createError(input) {
182
190
  if (typeof input === "string") {
183
191
  return new H3Error(input);
184
192
  }
185
- if (input instanceof H3Error) {
193
+ if (isError(input)) {
186
194
  return input;
187
195
  }
188
196
  const err = new H3Error(input.message ?? input.statusMessage, input.cause ? { cause: input.cause } : void 0);
@@ -195,6 +203,12 @@ function createError(input) {
195
203
  if (input.data) {
196
204
  err.data = input.data;
197
205
  }
206
+ if (input.fatal !== void 0) {
207
+ err.fatal = input.fatal;
208
+ }
209
+ if (input.unhandled !== void 0) {
210
+ err.unhandled = input.unhandled;
211
+ }
198
212
  return err;
199
213
  }
200
214
  function sendError(event, error, debug) {
@@ -220,7 +234,7 @@ function sendError(event, error, debug) {
220
234
  event.res.end(JSON.stringify(responseBody, null, 2));
221
235
  }
222
236
  function isError(input) {
223
- return input instanceof H3Error;
237
+ return input?.constructor?.__h3_error__ === true;
224
238
  }
225
239
 
226
240
  const defineHandler = (handler) => handler;
@@ -368,14 +382,18 @@ function createApp(options = {}) {
368
382
  const event = createEvent(req, res);
369
383
  try {
370
384
  await handler(event);
371
- } catch (err) {
385
+ } catch (_error) {
386
+ const error = createError(_error);
387
+ if (!isError(_error)) {
388
+ error.unhandled = true;
389
+ }
390
+ if (error.unhandled || error.fatal) {
391
+ console.error("[h3]", error.fatal ? "[fatal]" : "[unhandled]", error);
392
+ }
372
393
  if (options.onError) {
373
- await options.onError(err, event);
394
+ await options.onError(error, event);
374
395
  } else {
375
- if (!isError(err)) {
376
- console.error("[h3]", err);
377
- }
378
- await sendError(event, err, !!options.debug);
396
+ await sendError(event, error, !!options.debug);
379
397
  }
380
398
  }
381
399
  };
@@ -426,8 +444,11 @@ function createAppEventHandler(stack, options) {
426
444
  return send(event, val, MIMES.html);
427
445
  } else if (isStream(val)) {
428
446
  return sendStream(event, val);
447
+ } else if (val === null) {
448
+ event.res.statusCode = 204;
449
+ return send(event);
429
450
  } else if (type === "object" || type === "boolean" || type === "number") {
430
- if (val && val.buffer) {
451
+ if (val.buffer) {
431
452
  return send(event, val);
432
453
  } else if (val instanceof Error) {
433
454
  throw createError(val);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "h3",
3
- "version": "0.7.10",
3
+ "version": "0.7.13",
4
4
  "description": "Tiny JavaScript Server",
5
5
  "repository": "unjs/h3",
6
6
  "license": "MIT",
@@ -22,7 +22,7 @@
22
22
  "cookie-es": "^0.5.0",
23
23
  "destr": "^1.1.1",
24
24
  "radix3": "^0.1.2",
25
- "ufo": "^0.8.4"
25
+ "ufo": "^0.8.5"
26
26
  },
27
27
  "devDependencies": {
28
28
  "0x": "latest",
@@ -45,7 +45,7 @@
45
45
  "unbuild": "latest",
46
46
  "vitest": "latest"
47
47
  },
48
- "packageManager": "pnpm@7.2.1",
48
+ "packageManager": "pnpm@7.8.0",
49
49
  "scripts": {
50
50
  "build": "unbuild",
51
51
  "dev": "vitest",