h3 0.5.0 → 0.5.3

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
@@ -21,10 +21,23 @@ function promisifyHandler(handler) {
21
21
  }
22
22
  const promisifyHandle = promisifyHandler;
23
23
  function callHandler(handler, req, res) {
24
+ const isMiddleware = handler.length > 2;
24
25
  return new Promise((resolve, reject) => {
25
- const next = (err) => err ? reject(err) : resolve(void 0);
26
+ const next = (err) => {
27
+ if (isMiddleware) {
28
+ res.off("close", next);
29
+ res.off("error", next);
30
+ }
31
+ return err ? reject(err) : resolve(void 0);
32
+ };
26
33
  try {
27
- return resolve(handler(req, res, next));
34
+ const returned = handler(req, res, next);
35
+ if (isMiddleware && returned === void 0) {
36
+ res.once("close", next);
37
+ res.once("error", next);
38
+ } else {
39
+ resolve(returned);
40
+ }
28
41
  } catch (err) {
29
42
  next(err);
30
43
  }
@@ -68,7 +81,11 @@ function defineLazyEventHandler(factory) {
68
81
  }
69
82
  if (!_promise) {
70
83
  _promise = Promise.resolve(factory()).then((r) => {
71
- _resolved = r.default || r;
84
+ const handler = r.default || r;
85
+ if (typeof handler !== "function") {
86
+ throw new TypeError("Invalid lazy handler result. It should be a function:", handler);
87
+ }
88
+ _resolved = toEventHandler(r.default || r);
72
89
  return _resolved;
73
90
  });
74
91
  }
@@ -88,6 +105,9 @@ function toEventHandler(handler) {
88
105
  if (isEventHandler(handler)) {
89
106
  return handler;
90
107
  }
108
+ if (typeof handler !== "function") {
109
+ throw new TypeError("Invalid handler. It should be a function:", handler);
110
+ }
91
111
  return defineEventHandler((event) => {
92
112
  return callHandler(handler, event.req, event.res);
93
113
  });
@@ -104,6 +124,7 @@ function createEvent(req, res) {
104
124
  req.res = res;
105
125
  res.event = event;
106
126
  res.res = res;
127
+ res.req = res.req || {};
107
128
  res.req.res = res;
108
129
  res.req.req = req;
109
130
  return event;
@@ -170,6 +191,10 @@ async function useBody(event) {
170
191
  return event.req[ParsedBodySymbol];
171
192
  }
172
193
  const body = await useRawBody(event);
194
+ if (event.req.headers["content-type"] === "application/x-www-form-urlencoded") {
195
+ const parsedForm = Object.fromEntries(new URLSearchParams(body));
196
+ return parsedForm;
197
+ }
173
198
  const json = destr__default(body);
174
199
  event.req[ParsedBodySymbol] = json;
175
200
  return json;
@@ -265,30 +290,30 @@ function createError(input) {
265
290
  return err;
266
291
  }
267
292
  function sendError(event, error, debug) {
268
- let h3Error;
269
- if (error instanceof H3Error) {
270
- h3Error = error;
271
- } else {
272
- console.error(error);
273
- h3Error = createError(error);
274
- }
275
293
  if (event.res.writableEnded) {
276
294
  return;
277
295
  }
278
- event.res.statusCode = h3Error.statusCode;
279
- event.res.statusMessage = h3Error.statusMessage;
296
+ const h3Error = isError(error) ? error : createError(error);
280
297
  const responseBody = {
281
- statusCode: event.res.statusCode,
282
- statusMessage: event.res.statusMessage,
298
+ statusCode: h3Error.statusCode,
299
+ statusMessage: h3Error.statusMessage,
283
300
  stack: [],
284
301
  data: h3Error.data
285
302
  };
286
303
  if (debug) {
287
304
  responseBody.stack = (h3Error.stack || "").split("\n").map((l) => l.trim());
288
305
  }
306
+ if (event.res.writableEnded) {
307
+ return;
308
+ }
309
+ event.res.statusCode = h3Error.statusCode;
310
+ event.res.statusMessage = h3Error.statusMessage;
289
311
  event.res.setHeader("Content-Type", MIMES.json);
290
312
  event.res.end(JSON.stringify(responseBody, null, 2));
291
313
  }
314
+ function isError(input) {
315
+ return input instanceof H3Error;
316
+ }
292
317
 
293
318
  function createApp(options = {}) {
294
319
  const stack = [];
@@ -300,11 +325,16 @@ function createApp(options = {}) {
300
325
  } catch (err) {
301
326
  if (options.onError) {
302
327
  await options.onError(err, event);
328
+ } else {
329
+ if (!isError(err)) {
330
+ console.error("[h3]", err);
331
+ }
332
+ await sendError(event, err, !!options.debug);
303
333
  }
304
- await sendError(event, err, !!options.debug);
305
334
  }
306
335
  };
307
336
  const app = nodeHandler;
337
+ app.nodeHandler = nodeHandler;
308
338
  app.stack = stack;
309
339
  app.handler = handler;
310
340
  app.use = (arg1, arg2, arg3) => use(app, arg1, arg2, arg3);
@@ -366,14 +396,13 @@ function createAppEventHandler(stack, options) {
366
396
  });
367
397
  }
368
398
  function normalizeLayer(input) {
369
- let handler = input.handler;
399
+ let handler = input.handler || input.handle;
370
400
  if (handler.handler) {
371
401
  handler = handler.handler;
372
402
  }
373
- if (!isEventHandler(handler)) {
374
- if (input.lazy) {
375
- handler = defineLazyHandler(handler);
376
- }
403
+ if (input.lazy) {
404
+ handler = defineLazyEventHandler(handler);
405
+ } else if (!isEventHandler(handler)) {
377
406
  handler = toEventHandler(handler);
378
407
  }
379
408
  return {
@@ -449,6 +478,7 @@ exports.defineLazyEventHandler = defineLazyEventHandler;
449
478
  exports.defineLazyHandler = defineLazyHandler;
450
479
  exports.defineMiddleware = defineMiddleware;
451
480
  exports.deleteCookie = deleteCookie;
481
+ exports.isError = isError;
452
482
  exports.isEvent = isEvent;
453
483
  exports.isEventHandler = isEventHandler;
454
484
  exports.isMethod = isMethod;
package/dist/index.d.ts CHANGED
@@ -21,7 +21,8 @@ interface EventHandler {
21
21
  (event: CompatibilityEvent): H3Response | Promise<H3Response>;
22
22
  }
23
23
  declare function defineEventHandler(handler: EventHandler): EventHandler;
24
- declare function defineLazyEventHandler(factory: () => EventHandler | Promise<EventHandler>): EventHandler;
24
+ declare type LazyEventHandler = () => EventHandler | Promise<EventHandler>;
25
+ declare function defineLazyEventHandler(factory: LazyEventHandler): EventHandler;
25
26
  declare function isEventHandler(input: any): input is EventHandler;
26
27
  declare type CompatibilityEventHandler = EventHandler | Handler | Middleware;
27
28
  declare function toEventHandler(handler: CompatibilityEventHandler): EventHandler;
@@ -58,11 +59,11 @@ declare type Stack = Layer[];
58
59
  interface InputLayer {
59
60
  route?: string;
60
61
  match?: Matcher;
61
- handler: Handler | LazyHandler;
62
+ handler: Handler | LazyHandler | EventHandler | LazyEventHandler;
62
63
  lazy?: boolean;
63
- /**
64
- * @deprecated
65
- */
64
+ /** @deprecated */
65
+ handle?: Handler;
66
+ /** @deprecated */
66
67
  promisify?: boolean;
67
68
  }
68
69
  declare type InputStack = InputLayer[];
@@ -72,10 +73,11 @@ interface AppUse {
72
73
  (handler: CompatibilityEventHandler | CompatibilityEventHandler[], options?: Partial<InputLayer>): App;
73
74
  (options: InputLayer): App;
74
75
  }
75
- declare type NodeHandler = (req: http.IncomingMessage, res: http.ServerResponse) => void | Promise<void>;
76
+ declare type NodeHandler = (req: http.IncomingMessage, res: http.ServerResponse) => Promise<void>;
76
77
  interface App extends NodeHandler {
77
78
  stack: Stack;
78
79
  handler: EventHandler;
80
+ nodeHandler: NodeHandler;
79
81
  use: AppUse;
80
82
  }
81
83
  interface AppOptions {
@@ -119,6 +121,7 @@ declare function createError(input: Partial<H3Error>): H3Error;
119
121
  * In the debug mode the stack trace of errors will be return in response.
120
122
  */
121
123
  declare function sendError(event: CompatibilityEvent, error: Error | H3Error, debug?: boolean): void;
124
+ declare function isError(input: any): input is H3Error;
122
125
 
123
126
  declare const defineHandler: <T>(handler: Handler<T, {}>) => Handler<T, {}>;
124
127
  /** @deprecated Use defineHandler */
@@ -128,10 +131,10 @@ declare function promisifyHandler(handler: Handler | Middleware): PromisifiedHan
128
131
  /** @deprecated Use defineHandler */
129
132
  declare const promisifyHandle: typeof promisifyHandler;
130
133
  declare function callHandler(handler: Middleware, req: IncomingMessage, res: ServerResponse): Promise<unknown>;
131
- declare function defineLazyHandler(handler: LazyHandler, promisify?: boolean): PromisifiedHandler;
134
+ declare function defineLazyHandler(handler: LazyHandler, promisify?: boolean): Handler;
132
135
  /** @deprecated Use defineLazyHandler */
133
136
  declare const lazyHandle: typeof defineLazyHandler;
134
- declare function useBase(base: string, handler: PromisifiedHandler): PromisifiedHandler;
137
+ declare function useBase(base: string, handler: Handler): Handler;
135
138
 
136
139
  /**
137
140
  * Reads body of the request and returns encoded raw string (default) or `Buffer` if encoding if falsy.
@@ -222,4 +225,4 @@ interface Router extends AddRouteShortcuts {
222
225
  }
223
226
  declare function createRouter(): Router;
224
227
 
225
- export { AddRouteShortcuts, App, AppOptions, AppUse, CompatibilityEvent, CompatibilityEventHandler, EventHandler, H3Error, H3Event, H3Response, InputLayer, InputStack, JSONValue, Layer, MIMES, Matcher, NodeHandler, Router, RouterMethod, RouterUse, Stack, _JSONValue, appendHeader, assertMethod, callHandler, createApp, createAppEventHandler, createError, createEvent, createRouter, defaultContentType, defineEventHandler, defineHandle, defineHandler, defineLazyEventHandler, defineLazyHandler, defineMiddleware, deleteCookie, isEvent, isEventHandler, isMethod, isStream, lazyHandle, promisifyHandle, promisifyHandler, send, sendError, sendRedirect, sendStream, setCookie, toEventHandler, use, useBase, useBody, useCookie, useCookies, useMethod, useQuery, useRawBody };
228
+ export { AddRouteShortcuts, App, AppOptions, AppUse, CompatibilityEvent, CompatibilityEventHandler, Encoding, EventHandler, H3Error, H3Event, H3Response, HTTPMethod, Handler, IncomingMessage, InputLayer, InputStack, JSONValue, Layer, LazyEventHandler, LazyHandler, MIMES, Matcher, Middleware, NodeHandler, PromisifiedHandler, Router, RouterMethod, RouterUse, ServerResponse, Stack, _JSONValue, appendHeader, assertMethod, callHandler, createApp, createAppEventHandler, createError, createEvent, createRouter, defaultContentType, defineEventHandler, defineHandle, defineHandler, defineLazyEventHandler, defineLazyHandler, defineMiddleware, deleteCookie, isError, isEvent, isEventHandler, isMethod, isStream, lazyHandle, promisifyHandle, promisifyHandler, send, sendError, sendRedirect, sendStream, setCookie, toEventHandler, use, useBase, useBody, useCookie, useCookies, useMethod, useQuery, useRawBody };
package/dist/index.mjs CHANGED
@@ -13,10 +13,23 @@ function promisifyHandler(handler) {
13
13
  }
14
14
  const promisifyHandle = promisifyHandler;
15
15
  function callHandler(handler, req, res) {
16
+ const isMiddleware = handler.length > 2;
16
17
  return new Promise((resolve, reject) => {
17
- const next = (err) => err ? reject(err) : resolve(void 0);
18
+ const next = (err) => {
19
+ if (isMiddleware) {
20
+ res.off("close", next);
21
+ res.off("error", next);
22
+ }
23
+ return err ? reject(err) : resolve(void 0);
24
+ };
18
25
  try {
19
- return resolve(handler(req, res, next));
26
+ const returned = handler(req, res, next);
27
+ if (isMiddleware && returned === void 0) {
28
+ res.once("close", next);
29
+ res.once("error", next);
30
+ } else {
31
+ resolve(returned);
32
+ }
20
33
  } catch (err) {
21
34
  next(err);
22
35
  }
@@ -60,7 +73,11 @@ function defineLazyEventHandler(factory) {
60
73
  }
61
74
  if (!_promise) {
62
75
  _promise = Promise.resolve(factory()).then((r) => {
63
- _resolved = r.default || r;
76
+ const handler = r.default || r;
77
+ if (typeof handler !== "function") {
78
+ throw new TypeError("Invalid lazy handler result. It should be a function:", handler);
79
+ }
80
+ _resolved = toEventHandler(r.default || r);
64
81
  return _resolved;
65
82
  });
66
83
  }
@@ -80,6 +97,9 @@ function toEventHandler(handler) {
80
97
  if (isEventHandler(handler)) {
81
98
  return handler;
82
99
  }
100
+ if (typeof handler !== "function") {
101
+ throw new TypeError("Invalid handler. It should be a function:", handler);
102
+ }
83
103
  return defineEventHandler((event) => {
84
104
  return callHandler(handler, event.req, event.res);
85
105
  });
@@ -96,6 +116,7 @@ function createEvent(req, res) {
96
116
  req.res = res;
97
117
  res.event = event;
98
118
  res.res = res;
119
+ res.req = res.req || {};
99
120
  res.req.res = res;
100
121
  res.req.req = req;
101
122
  return event;
@@ -162,6 +183,10 @@ async function useBody(event) {
162
183
  return event.req[ParsedBodySymbol];
163
184
  }
164
185
  const body = await useRawBody(event);
186
+ if (event.req.headers["content-type"] === "application/x-www-form-urlencoded") {
187
+ const parsedForm = Object.fromEntries(new URLSearchParams(body));
188
+ return parsedForm;
189
+ }
165
190
  const json = destr(body);
166
191
  event.req[ParsedBodySymbol] = json;
167
192
  return json;
@@ -257,30 +282,30 @@ function createError(input) {
257
282
  return err;
258
283
  }
259
284
  function sendError(event, error, debug) {
260
- let h3Error;
261
- if (error instanceof H3Error) {
262
- h3Error = error;
263
- } else {
264
- console.error(error);
265
- h3Error = createError(error);
266
- }
267
285
  if (event.res.writableEnded) {
268
286
  return;
269
287
  }
270
- event.res.statusCode = h3Error.statusCode;
271
- event.res.statusMessage = h3Error.statusMessage;
288
+ const h3Error = isError(error) ? error : createError(error);
272
289
  const responseBody = {
273
- statusCode: event.res.statusCode,
274
- statusMessage: event.res.statusMessage,
290
+ statusCode: h3Error.statusCode,
291
+ statusMessage: h3Error.statusMessage,
275
292
  stack: [],
276
293
  data: h3Error.data
277
294
  };
278
295
  if (debug) {
279
296
  responseBody.stack = (h3Error.stack || "").split("\n").map((l) => l.trim());
280
297
  }
298
+ if (event.res.writableEnded) {
299
+ return;
300
+ }
301
+ event.res.statusCode = h3Error.statusCode;
302
+ event.res.statusMessage = h3Error.statusMessage;
281
303
  event.res.setHeader("Content-Type", MIMES.json);
282
304
  event.res.end(JSON.stringify(responseBody, null, 2));
283
305
  }
306
+ function isError(input) {
307
+ return input instanceof H3Error;
308
+ }
284
309
 
285
310
  function createApp(options = {}) {
286
311
  const stack = [];
@@ -292,11 +317,16 @@ function createApp(options = {}) {
292
317
  } catch (err) {
293
318
  if (options.onError) {
294
319
  await options.onError(err, event);
320
+ } else {
321
+ if (!isError(err)) {
322
+ console.error("[h3]", err);
323
+ }
324
+ await sendError(event, err, !!options.debug);
295
325
  }
296
- await sendError(event, err, !!options.debug);
297
326
  }
298
327
  };
299
328
  const app = nodeHandler;
329
+ app.nodeHandler = nodeHandler;
300
330
  app.stack = stack;
301
331
  app.handler = handler;
302
332
  app.use = (arg1, arg2, arg3) => use(app, arg1, arg2, arg3);
@@ -358,14 +388,13 @@ function createAppEventHandler(stack, options) {
358
388
  });
359
389
  }
360
390
  function normalizeLayer(input) {
361
- let handler = input.handler;
391
+ let handler = input.handler || input.handle;
362
392
  if (handler.handler) {
363
393
  handler = handler.handler;
364
394
  }
365
- if (!isEventHandler(handler)) {
366
- if (input.lazy) {
367
- handler = defineLazyHandler(handler);
368
- }
395
+ if (input.lazy) {
396
+ handler = defineLazyEventHandler(handler);
397
+ } else if (!isEventHandler(handler)) {
369
398
  handler = toEventHandler(handler);
370
399
  }
371
400
  return {
@@ -423,4 +452,4 @@ function createRouter() {
423
452
  return router;
424
453
  }
425
454
 
426
- export { H3Error, MIMES, appendHeader, assertMethod, callHandler, createApp, createAppEventHandler, createError, createEvent, createRouter, defaultContentType, defineEventHandler, defineHandle, defineHandler, defineLazyEventHandler, defineLazyHandler, defineMiddleware, deleteCookie, isEvent, isEventHandler, isMethod, isStream, lazyHandle, promisifyHandle, promisifyHandler, send, sendError, sendRedirect, sendStream, setCookie, toEventHandler, use, useBase, useBody, useCookie, useCookies, useMethod, useQuery, useRawBody };
455
+ export { H3Error, MIMES, appendHeader, assertMethod, callHandler, createApp, createAppEventHandler, createError, createEvent, createRouter, defaultContentType, defineEventHandler, defineHandle, defineHandler, defineLazyEventHandler, defineLazyHandler, defineMiddleware, deleteCookie, isError, isEvent, isEventHandler, isMethod, isStream, lazyHandle, promisifyHandle, promisifyHandler, send, sendError, sendRedirect, sendStream, setCookie, toEventHandler, use, useBase, useBody, useCookie, useCookies, useMethod, useQuery, useRawBody };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "h3",
3
- "version": "0.5.0",
3
+ "version": "0.5.3",
4
4
  "description": "Tiny JavaScript Server",
5
5
  "repository": "unjs/h3",
6
6
  "license": "MIT",