h3 0.5.4 → 0.5.7

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
@@ -78,6 +78,37 @@ async function useBody(event) {
78
78
  return json;
79
79
  }
80
80
 
81
+ function handleCacheHeaders(event, opts) {
82
+ const cacheControls = ["public"].concat(opts.cacheControls || []);
83
+ let cacheMatched = false;
84
+ if (opts.maxAge !== void 0) {
85
+ opts.cacheControls?.push(`max-age=${+opts.maxAge}`, `s-maxage=${+opts.maxAge}`);
86
+ }
87
+ if (opts.modifiedTime) {
88
+ const ifModifiedSince = event.req.headers["if-modified-since"];
89
+ event.res.setHeader("Last-Modified", +opts.modifiedTime + "");
90
+ if (ifModifiedSince) {
91
+ if (new Date(ifModifiedSince) >= opts.modifiedTime) {
92
+ cacheMatched = true;
93
+ }
94
+ }
95
+ }
96
+ if (opts.etag) {
97
+ event.res.setHeader("Etag", opts.etag);
98
+ const ifNonMatch = event.req.headers["if-none-match"];
99
+ if (ifNonMatch === opts.etag) {
100
+ cacheMatched = true;
101
+ }
102
+ }
103
+ event.res.setHeader("Cache-Control", cacheControls.join(", "));
104
+ if (cacheMatched) {
105
+ event.res.statusCode = 304;
106
+ event.res.end("");
107
+ return true;
108
+ }
109
+ return false;
110
+ }
111
+
81
112
  const MIMES = {
82
113
  html: "text/html",
83
114
  json: "application/json"
@@ -254,6 +285,7 @@ function defineEventHandler(handler) {
254
285
  handler.__is_handler__ = true;
255
286
  return handler;
256
287
  }
288
+ const eventHandler = defineEventHandler;
257
289
  function defineLazyEventHandler(factory) {
258
290
  let _promise;
259
291
  let _resolved;
@@ -273,13 +305,26 @@ function defineLazyEventHandler(factory) {
273
305
  }
274
306
  return _promise;
275
307
  };
276
- return defineEventHandler((event) => {
308
+ return eventHandler((event) => {
277
309
  if (_resolved) {
278
310
  return _resolved(event);
279
311
  }
280
312
  return resolveHandler().then((handler) => handler(event));
281
313
  });
282
314
  }
315
+ const lazyEventHandler = defineLazyEventHandler;
316
+ function dynamicEventHandler(initial) {
317
+ let current = initial;
318
+ const wrapper = eventHandler((event) => {
319
+ if (current) {
320
+ return current(event);
321
+ }
322
+ });
323
+ wrapper.set = (handler) => {
324
+ current = handler;
325
+ };
326
+ return wrapper;
327
+ }
283
328
  function isEventHandler(input) {
284
329
  return "__is_handler__" in input;
285
330
  }
@@ -290,7 +335,7 @@ function toEventHandler(handler) {
290
335
  if (typeof handler !== "function") {
291
336
  throw new TypeError("Invalid handler. It should be a function:", handler);
292
337
  }
293
- return defineEventHandler((event) => {
338
+ return eventHandler((event) => {
294
339
  return callHandler(handler, event.req, event.res);
295
340
  });
296
341
  }
@@ -356,7 +401,7 @@ function use(app, arg1, arg2, arg3) {
356
401
  }
357
402
  function createAppEventHandler(stack, options) {
358
403
  const spacing = options.debug ? 2 : void 0;
359
- return defineEventHandler(async (event) => {
404
+ return eventHandler(async (event) => {
360
405
  event.req.originalUrl = event.req.originalUrl || event.req.url || "/";
361
406
  const reqUrl = event.req.url || "/";
362
407
  for (const layer of stack) {
@@ -401,7 +446,7 @@ function normalizeLayer(input) {
401
446
  handler = handler.handler;
402
447
  }
403
448
  if (input.lazy) {
404
- handler = defineLazyEventHandler(handler);
449
+ handler = lazyEventHandler(handler);
405
450
  } else if (!isEventHandler(handler)) {
406
451
  handler = toEventHandler(handler);
407
452
  }
@@ -430,7 +475,7 @@ function createRouter() {
430
475
  for (const method of RouterMethods) {
431
476
  router[method] = (path, handle) => router.add(path, handle, method);
432
477
  }
433
- router.handler = defineEventHandler((event) => {
478
+ router.handler = eventHandler((event) => {
434
479
  let path = event.req.url || "/";
435
480
  const queryUrlIndex = path.lastIndexOf("?");
436
481
  if (queryUrlIndex > -1) {
@@ -478,11 +523,15 @@ exports.defineLazyEventHandler = defineLazyEventHandler;
478
523
  exports.defineLazyHandler = defineLazyHandler;
479
524
  exports.defineMiddleware = defineMiddleware;
480
525
  exports.deleteCookie = deleteCookie;
526
+ exports.dynamicEventHandler = dynamicEventHandler;
527
+ exports.eventHandler = eventHandler;
528
+ exports.handleCacheHeaders = handleCacheHeaders;
481
529
  exports.isError = isError;
482
530
  exports.isEvent = isEvent;
483
531
  exports.isEventHandler = isEventHandler;
484
532
  exports.isMethod = isMethod;
485
533
  exports.isStream = isStream;
534
+ exports.lazyEventHandler = lazyEventHandler;
486
535
  exports.lazyHandle = lazyHandle;
487
536
  exports.promisifyHandle = promisifyHandle;
488
537
  exports.promisifyHandler = promisifyHandler;
package/dist/index.d.ts CHANGED
@@ -7,12 +7,10 @@ interface H3Event {
7
7
  event: H3Event;
8
8
  req: IncomingMessage;
9
9
  res: ServerResponse;
10
- /**
11
- * Request params only filled with h3 Router handlers
12
- */
10
+ /** Request params only filled with h3 Router handlers */
13
11
  params?: Record<string, any>;
14
12
  }
15
- declare type CompatibilityEvent = H3Event | IncomingMessage | ServerResponse;
13
+ declare type CompatibilityEvent = H3Event | IncomingMessage;
16
14
  declare type _JSONValue<T = string | number | boolean> = T | T[] | Record<string, T>;
17
15
  declare type JSONValue = _JSONValue<_JSONValue>;
18
16
  declare type H3Response = void | JSONValue | Buffer;
@@ -21,27 +19,35 @@ interface EventHandler {
21
19
  (event: CompatibilityEvent): H3Response | Promise<H3Response>;
22
20
  }
23
21
  declare function defineEventHandler(handler: EventHandler): EventHandler;
22
+ declare const eventHandler: typeof defineEventHandler;
24
23
  declare type LazyEventHandler = () => EventHandler | Promise<EventHandler>;
25
24
  declare function defineLazyEventHandler(factory: LazyEventHandler): EventHandler;
25
+ declare const lazyEventHandler: typeof defineLazyEventHandler;
26
+ interface DynamicEventHandler extends EventHandler {
27
+ set: (handler: EventHandler) => void;
28
+ }
29
+ declare function dynamicEventHandler(initial?: EventHandler): DynamicEventHandler;
26
30
  declare function isEventHandler(input: any): input is EventHandler;
27
31
  declare type CompatibilityEventHandler = EventHandler | Handler | Middleware;
28
32
  declare function toEventHandler(handler: CompatibilityEventHandler): EventHandler;
29
33
  declare function createEvent(req: http.IncomingMessage, res: http.ServerResponse): CompatibilityEvent;
30
34
  declare function isEvent(input: any): input is H3Event;
31
35
 
32
- interface IncomingMessage extends http.IncomingMessage {
33
- originalUrl?: string;
36
+ interface CompatibilityRequestProps {
34
37
  event: H3Event;
38
+ /** Only available with connect and press */
39
+ originalUrl?: string;
40
+ /** Request params only filled with h3 Router handlers */
41
+ params?: Record<string, any>;
42
+ }
43
+ interface IncomingMessage extends http.IncomingMessage, CompatibilityRequestProps {
35
44
  req: H3Event['req'];
36
45
  res: H3Event['res'];
37
46
  }
38
47
  interface ServerResponse extends http.ServerResponse {
39
48
  event: H3Event;
40
49
  res: H3Event['res'];
41
- req: http.ServerResponse['req'] & {
42
- event: H3Event;
43
- originalUrl?: string;
44
- };
50
+ req: http.ServerResponse['req'] & CompatibilityRequestProps;
45
51
  }
46
52
  declare type Handler<T = any, ReqT = {}> = (req: IncomingMessage & ReqT, res: ServerResponse) => T;
47
53
  declare type PromisifiedHandler = Handler<Promise<any>>;
@@ -157,6 +163,19 @@ declare function useRawBody(event: CompatibilityEvent, encoding?: Encoding): Enc
157
163
  */
158
164
  declare function useBody<T = any>(event: CompatibilityEvent): Promise<T>;
159
165
 
166
+ interface CacheConditions {
167
+ modifiedTime?: Date;
168
+ maxAge?: number;
169
+ etag?: string;
170
+ cacheControls?: string[];
171
+ }
172
+ /**
173
+ * Check request caching headers (`If-Modified-Since`) and add caching headers (Last-Modified, Cache-Control)
174
+ * Note: `public` cache control will be added by default
175
+ * @returns `true` when cache headers are matching. When `true` is returned, no reponse should be sent anymore
176
+ */
177
+ declare function handleCacheHeaders(event: CompatibilityEvent, opts: CacheConditions): boolean;
178
+
160
179
  declare const MIMES: {
161
180
  html: string;
162
181
  json: string;
@@ -225,4 +244,4 @@ interface Router extends AddRouteShortcuts {
225
244
  }
226
245
  declare function createRouter(): Router;
227
246
 
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 };
247
+ export { AddRouteShortcuts, App, AppOptions, AppUse, CacheConditions, CompatibilityEvent, CompatibilityEventHandler, DynamicEventHandler, 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, dynamicEventHandler, eventHandler, handleCacheHeaders, isError, isEvent, isEventHandler, isMethod, isStream, lazyEventHandler, lazyHandle, promisifyHandle, promisifyHandler, send, sendError, sendRedirect, sendStream, setCookie, toEventHandler, use, useBase, useBody, useCookie, useCookies, useMethod, useQuery, useRawBody };
package/dist/index.mjs CHANGED
@@ -70,6 +70,37 @@ async function useBody(event) {
70
70
  return json;
71
71
  }
72
72
 
73
+ function handleCacheHeaders(event, opts) {
74
+ const cacheControls = ["public"].concat(opts.cacheControls || []);
75
+ let cacheMatched = false;
76
+ if (opts.maxAge !== void 0) {
77
+ opts.cacheControls?.push(`max-age=${+opts.maxAge}`, `s-maxage=${+opts.maxAge}`);
78
+ }
79
+ if (opts.modifiedTime) {
80
+ const ifModifiedSince = event.req.headers["if-modified-since"];
81
+ event.res.setHeader("Last-Modified", +opts.modifiedTime + "");
82
+ if (ifModifiedSince) {
83
+ if (new Date(ifModifiedSince) >= opts.modifiedTime) {
84
+ cacheMatched = true;
85
+ }
86
+ }
87
+ }
88
+ if (opts.etag) {
89
+ event.res.setHeader("Etag", opts.etag);
90
+ const ifNonMatch = event.req.headers["if-none-match"];
91
+ if (ifNonMatch === opts.etag) {
92
+ cacheMatched = true;
93
+ }
94
+ }
95
+ event.res.setHeader("Cache-Control", cacheControls.join(", "));
96
+ if (cacheMatched) {
97
+ event.res.statusCode = 304;
98
+ event.res.end("");
99
+ return true;
100
+ }
101
+ return false;
102
+ }
103
+
73
104
  const MIMES = {
74
105
  html: "text/html",
75
106
  json: "application/json"
@@ -246,6 +277,7 @@ function defineEventHandler(handler) {
246
277
  handler.__is_handler__ = true;
247
278
  return handler;
248
279
  }
280
+ const eventHandler = defineEventHandler;
249
281
  function defineLazyEventHandler(factory) {
250
282
  let _promise;
251
283
  let _resolved;
@@ -265,13 +297,26 @@ function defineLazyEventHandler(factory) {
265
297
  }
266
298
  return _promise;
267
299
  };
268
- return defineEventHandler((event) => {
300
+ return eventHandler((event) => {
269
301
  if (_resolved) {
270
302
  return _resolved(event);
271
303
  }
272
304
  return resolveHandler().then((handler) => handler(event));
273
305
  });
274
306
  }
307
+ const lazyEventHandler = defineLazyEventHandler;
308
+ function dynamicEventHandler(initial) {
309
+ let current = initial;
310
+ const wrapper = eventHandler((event) => {
311
+ if (current) {
312
+ return current(event);
313
+ }
314
+ });
315
+ wrapper.set = (handler) => {
316
+ current = handler;
317
+ };
318
+ return wrapper;
319
+ }
275
320
  function isEventHandler(input) {
276
321
  return "__is_handler__" in input;
277
322
  }
@@ -282,7 +327,7 @@ function toEventHandler(handler) {
282
327
  if (typeof handler !== "function") {
283
328
  throw new TypeError("Invalid handler. It should be a function:", handler);
284
329
  }
285
- return defineEventHandler((event) => {
330
+ return eventHandler((event) => {
286
331
  return callHandler(handler, event.req, event.res);
287
332
  });
288
333
  }
@@ -348,7 +393,7 @@ function use(app, arg1, arg2, arg3) {
348
393
  }
349
394
  function createAppEventHandler(stack, options) {
350
395
  const spacing = options.debug ? 2 : void 0;
351
- return defineEventHandler(async (event) => {
396
+ return eventHandler(async (event) => {
352
397
  event.req.originalUrl = event.req.originalUrl || event.req.url || "/";
353
398
  const reqUrl = event.req.url || "/";
354
399
  for (const layer of stack) {
@@ -393,7 +438,7 @@ function normalizeLayer(input) {
393
438
  handler = handler.handler;
394
439
  }
395
440
  if (input.lazy) {
396
- handler = defineLazyEventHandler(handler);
441
+ handler = lazyEventHandler(handler);
397
442
  } else if (!isEventHandler(handler)) {
398
443
  handler = toEventHandler(handler);
399
444
  }
@@ -422,7 +467,7 @@ function createRouter() {
422
467
  for (const method of RouterMethods) {
423
468
  router[method] = (path, handle) => router.add(path, handle, method);
424
469
  }
425
- router.handler = defineEventHandler((event) => {
470
+ router.handler = eventHandler((event) => {
426
471
  let path = event.req.url || "/";
427
472
  const queryUrlIndex = path.lastIndexOf("?");
428
473
  if (queryUrlIndex > -1) {
@@ -452,4 +497,4 @@ function createRouter() {
452
497
  return router;
453
498
  }
454
499
 
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 };
500
+ export { H3Error, MIMES, appendHeader, assertMethod, callHandler, createApp, createAppEventHandler, createError, createEvent, createRouter, defaultContentType, defineEventHandler, defineHandle, defineHandler, defineLazyEventHandler, defineLazyHandler, defineMiddleware, deleteCookie, dynamicEventHandler, eventHandler, handleCacheHeaders, isError, isEvent, isEventHandler, isMethod, isStream, lazyEventHandler, 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.4",
3
+ "version": "0.5.7",
4
4
  "description": "Tiny JavaScript Server",
5
5
  "repository": "unjs/h3",
6
6
  "license": "MIT",