Comparing version 0.4.2 to 0.5.0
@@ -1,16 +0,51 @@ | ||
import { IncomingMessage, ServerResponse } from 'http'; | ||
import http from 'http'; | ||
import { CookieSerializeOptions } from 'cookie-es'; | ||
import * as ufo from 'ufo'; | ||
declare type Encoding = false | 'ascii' | 'utf8' | 'utf-8' | 'utf16le' | 'ucs2' | 'ucs-2' | 'base64' | 'latin1' | 'binary' | 'hex'; | ||
interface H3Event { | ||
'__is_event__': true; | ||
event: H3Event; | ||
req: IncomingMessage; | ||
res: ServerResponse; | ||
/** | ||
* Request params only filled with h3 Router handlers | ||
*/ | ||
params?: Record<string, any>; | ||
} | ||
declare type CompatibilityEvent = H3Event | IncomingMessage | ServerResponse; | ||
declare type _JSONValue<T = string | number | boolean> = T | T[] | Record<string, T>; | ||
declare type JSONValue = _JSONValue<_JSONValue>; | ||
declare type H3Response = void | JSONValue | Buffer; | ||
interface EventHandler { | ||
'__is_handler__'?: true; | ||
(event: CompatibilityEvent): H3Response | Promise<H3Response>; | ||
} | ||
declare function defineEventHandler(handler: EventHandler): EventHandler; | ||
declare function defineLazyEventHandler(factory: () => EventHandler | Promise<EventHandler>): EventHandler; | ||
declare function isEventHandler(input: any): input is EventHandler; | ||
declare type CompatibilityEventHandler = EventHandler | Handler | Middleware; | ||
declare function toEventHandler(handler: CompatibilityEventHandler): EventHandler; | ||
declare function createEvent(req: http.IncomingMessage, res: http.ServerResponse): CompatibilityEvent; | ||
declare function isEvent(input: any): input is H3Event; | ||
declare type Handle<T = any, ReqT = {}> = (req: IncomingMessage & ReqT, res: ServerResponse) => T; | ||
declare type PHandle = Handle<Promise<any>>; | ||
interface IncomingMessage extends http.IncomingMessage { | ||
originalUrl?: string; | ||
event: H3Event; | ||
req: H3Event['req']; | ||
res: H3Event['res']; | ||
} | ||
interface ServerResponse extends http.ServerResponse { | ||
event: H3Event; | ||
res: H3Event['res']; | ||
req: http.ServerResponse['req'] & { | ||
event: H3Event; | ||
originalUrl?: string; | ||
}; | ||
} | ||
declare type Handler<T = any, ReqT = {}> = (req: IncomingMessage & ReqT, res: ServerResponse) => T; | ||
declare type PromisifiedHandler = Handler<Promise<any>>; | ||
declare type Middleware = (req: IncomingMessage, res: ServerResponse, next: (err?: Error) => any) => any; | ||
declare type LazyHandle = () => Handle | Promise<Handle>; | ||
declare const defineHandle: <T>(handler: Handle<T, {}>) => Handle<T, {}>; | ||
declare const defineMiddleware: (middleware: Middleware) => Middleware; | ||
declare function promisifyHandle(handle: Handle | Middleware): PHandle; | ||
declare function callHandle(handle: Middleware, req: IncomingMessage, res: ServerResponse): Promise<unknown>; | ||
declare function lazyHandle(handle: LazyHandle, promisify?: boolean): PHandle; | ||
declare function useBase(base: string, handle: PHandle): PHandle; | ||
declare type LazyHandler = () => Handler | Promise<Handler>; | ||
declare type Encoding = false | 'ascii' | 'utf8' | 'utf-8' | 'utf16le' | 'ucs2' | 'ucs-2' | 'base64' | 'latin1' | 'binary' | 'hex'; | ||
declare type HTTPMethod = 'GET' | 'HEAD' | 'POST' | 'PUT' | 'DELETE' | 'CONNECT' | 'OPTIONS' | 'TRACE'; | ||
@@ -20,3 +55,3 @@ interface Layer { | ||
match?: Matcher; | ||
handle: Handle; | ||
handler: EventHandler; | ||
} | ||
@@ -27,19 +62,20 @@ declare type Stack = Layer[]; | ||
match?: Matcher; | ||
handle: Handle | LazyHandle; | ||
handler: Handler | LazyHandler; | ||
lazy?: boolean; | ||
/** | ||
* @deprecated | ||
*/ | ||
promisify?: boolean; | ||
} | ||
declare type InputStack = InputLayer[]; | ||
declare type Matcher = (url: string, req?: IncomingMessage) => boolean; | ||
declare type Matcher = (url: string, event?: CompatibilityEvent) => boolean; | ||
interface AppUse { | ||
(route: string | string[], handle: Middleware | Middleware[], options?: Partial<InputLayer>): App; | ||
(route: string | string[], handle: Handle | Handle[], options?: Partial<InputLayer>): App; | ||
(handle: Middleware | Middleware[], options?: Partial<InputLayer>): App; | ||
(handle: Handle | Handle[], options?: Partial<InputLayer>): App; | ||
(route: string | string[], handler: CompatibilityEventHandler | CompatibilityEventHandler[], options?: Partial<InputLayer>): App; | ||
(handler: CompatibilityEventHandler | CompatibilityEventHandler[], options?: Partial<InputLayer>): App; | ||
(options: InputLayer): App; | ||
} | ||
interface App { | ||
(req: IncomingMessage, res: ServerResponse): Promise<any>; | ||
declare type NodeHandler = (req: http.IncomingMessage, res: http.ServerResponse) => void | Promise<void>; | ||
interface App extends NodeHandler { | ||
stack: Stack; | ||
_handle: PHandle; | ||
handler: EventHandler; | ||
use: AppUse; | ||
@@ -49,7 +85,7 @@ } | ||
debug?: boolean; | ||
onError?: (error: Error, req: IncomingMessage, res: ServerResponse) => any; | ||
onError?: (error: Error, event: CompatibilityEvent) => any; | ||
} | ||
declare function createApp(options?: AppOptions): App; | ||
declare function use(app: App, arg1: string | Handle | InputLayer | InputLayer[], arg2?: Handle | Partial<InputLayer> | Handle[] | Middleware | Middleware[], arg3?: Partial<InputLayer>): App; | ||
declare function createHandle(stack: Stack, options: AppOptions): PHandle; | ||
declare function use(app: App, arg1: string | Handler | InputLayer | InputLayer[], arg2?: Handler | Partial<InputLayer> | Handler[] | Middleware | Middleware[], arg3?: Partial<InputLayer>): App; | ||
declare function createAppEventHandler(stack: Stack, options: AppOptions): EventHandler; | ||
@@ -83,3 +119,3 @@ /** | ||
* | ||
* @param res {ServerResponse} The ServerResponse object is passed as the second parameter in the handler function | ||
@param event {CompatibilityEvent} H3 event or req passed by h3 handler | ||
* @param error {H3Error|Error} Raised error | ||
@@ -89,13 +125,20 @@ * @param debug {Boolean} Whether application is in debug mode.<br> | ||
*/ | ||
declare function sendError(res: ServerResponse, error: Error | H3Error, debug?: boolean): void; | ||
declare function sendError(event: CompatibilityEvent, error: Error | H3Error, debug?: boolean): void; | ||
declare const RawBodySymbol: unique symbol; | ||
interface _IncomingMessage extends IncomingMessage { | ||
[RawBodySymbol]?: Promise<Buffer>; | ||
ParsedBodySymbol?: any; | ||
body?: any; | ||
} | ||
declare const defineHandler: <T>(handler: Handler<T, {}>) => Handler<T, {}>; | ||
/** @deprecated Use defineHandler */ | ||
declare const defineHandle: <T>(handler: Handler<T, {}>) => Handler<T, {}>; | ||
declare const defineMiddleware: (middleware: Middleware) => Middleware; | ||
declare function promisifyHandler(handler: Handler | Middleware): PromisifiedHandler; | ||
/** @deprecated Use defineHandler */ | ||
declare const promisifyHandle: typeof promisifyHandler; | ||
declare function callHandler(handler: Middleware, req: IncomingMessage, res: ServerResponse): Promise<unknown>; | ||
declare function defineLazyHandler(handler: LazyHandler, promisify?: boolean): PromisifiedHandler; | ||
/** @deprecated Use defineLazyHandler */ | ||
declare const lazyHandle: typeof defineLazyHandler; | ||
declare function useBase(base: string, handler: PromisifiedHandler): PromisifiedHandler; | ||
/** | ||
* Reads body of the request and returns encoded raw string (default) or `Buffer` if encoding if falsy. | ||
* @param req {IncomingMessage} An IncomingMessage object is created by [http.Server](https://nodejs.org/api/http.html#http_class_http_server) | ||
* @param event {CompatibilityEvent} H3 event or req passed by h3 handler | ||
* @param encoding {Encoding} encoding="utf-8" - The character encoding to use. | ||
@@ -105,6 +148,6 @@ * | ||
*/ | ||
declare function useRawBody(req: _IncomingMessage, encoding?: Encoding): Encoding extends false ? Buffer : Promise<string>; | ||
declare function useRawBody(event: CompatibilityEvent, encoding?: Encoding): Encoding extends false ? Buffer : Promise<string | Buffer>; | ||
/** | ||
* Reads request body and try to safely parse using [destr](https://github.com/unjs/destr) | ||
* @param req {IncomingMessage} An IncomingMessage object created by [http.Server](https://nodejs.org/api/http.html#http_class_http_server) | ||
* @param event {CompatibilityEvent} H3 event or req passed by h3 handler | ||
* @param encoding {Encoding} encoding="utf-8" - The character encoding to use. | ||
@@ -118,3 +161,3 @@ * | ||
*/ | ||
declare function useBody<T = any>(req: _IncomingMessage): Promise<T>; | ||
declare function useBody<T = any>(event: CompatibilityEvent): Promise<T>; | ||
@@ -127,90 +170,4 @@ declare const MIMES: { | ||
/** | ||
* Additional serialization options | ||
*/ | ||
interface CookieSerializeOptions { | ||
/** | ||
* Specifies the value for the {@link https://tools.ietf.org/html/rfc6265#section-5.2.3|Domain Set-Cookie attribute}. By default, no | ||
* domain is set, and most clients will consider the cookie to apply to only | ||
* the current domain. | ||
*/ | ||
domain?: string; | ||
/** | ||
* Specifies a function that will be used to encode a cookie's value. Since | ||
* value of a cookie has a limited character set (and must be a simple | ||
* string), this function can be used to encode a value into a string suited | ||
* for a cookie's value. | ||
* | ||
* The default function is the global `encodeURIComponent`, which will | ||
* encode a JavaScript string into UTF-8 byte sequences and then URL-encode | ||
* any that fall outside of the cookie range. | ||
*/ | ||
encode?(value: string): string; | ||
/** | ||
* Specifies the `Date` object to be the value for the {@link https://tools.ietf.org/html/rfc6265#section-5.2.1|`Expires` `Set-Cookie` attribute}. By default, | ||
* no expiration is set, and most clients will consider this a "non-persistent cookie" and will delete | ||
* it on a condition like exiting a web browser application. | ||
* | ||
* *Note* the {@link https://tools.ietf.org/html/rfc6265#section-5.3|cookie storage model specification} | ||
* states that if both `expires` and `maxAge` are set, then `maxAge` takes precedence, but it is | ||
* possible not all clients by obey this, so if both are set, they should | ||
* point to the same date and time. | ||
*/ | ||
expires?: Date; | ||
/** | ||
* Specifies the boolean value for the {@link https://tools.ietf.org/html/rfc6265#section-5.2.6|`HttpOnly` `Set-Cookie` attribute}. | ||
* When truthy, the `HttpOnly` attribute is set, otherwise it is not. By | ||
* default, the `HttpOnly` attribute is not set. | ||
* | ||
* *Note* be careful when setting this to true, as compliant clients will | ||
* not allow client-side JavaScript to see the cookie in `document.cookie`. | ||
*/ | ||
httpOnly?: boolean; | ||
/** | ||
* Specifies the number (in seconds) to be the value for the `Max-Age` | ||
* `Set-Cookie` attribute. The given number will be converted to an integer | ||
* by rounding down. By default, no maximum age is set. | ||
* | ||
* *Note* the {@link https://tools.ietf.org/html/rfc6265#section-5.3|cookie storage model specification} | ||
* states that if both `expires` and `maxAge` are set, then `maxAge` takes precedence, but it is | ||
* possible not all clients by obey this, so if both are set, they should | ||
* point to the same date and time. | ||
*/ | ||
maxAge?: number; | ||
/** | ||
* Specifies the value for the {@link https://tools.ietf.org/html/rfc6265#section-5.2.4|`Path` `Set-Cookie` attribute}. | ||
* By default, the path is considered the "default path". | ||
*/ | ||
path?: string; | ||
/** | ||
* Specifies the boolean or string to be the value for the {@link https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-03#section-4.1.2.7|`SameSite` `Set-Cookie` attribute}. | ||
* | ||
* - `true` will set the `SameSite` attribute to `Strict` for strict same | ||
* site enforcement. | ||
* - `false` will not set the `SameSite` attribute. | ||
* - `'lax'` will set the `SameSite` attribute to Lax for lax same site | ||
* enforcement. | ||
* - `'strict'` will set the `SameSite` attribute to Strict for strict same | ||
* site enforcement. | ||
* - `'none'` will set the SameSite attribute to None for an explicit | ||
* cross-site cookie. | ||
* | ||
* More information about the different enforcement levels can be found in {@link https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-03#section-4.1.2.7|the specification}. | ||
* | ||
* *note* This is an attribute that has not yet been fully standardized, and may change in the future. This also means many clients may ignore this attribute until they understand it. | ||
*/ | ||
sameSite?: true | false | 'lax' | 'strict' | 'none'; | ||
/** | ||
* Specifies the boolean value for the {@link https://tools.ietf.org/html/rfc6265#section-5.2.5|`Secure` `Set-Cookie` attribute}. When truthy, the | ||
* `Secure` attribute is set, otherwise it is not. By default, the `Secure` attribute is not set. | ||
* | ||
* *Note* be careful when setting this to `true`, as compliant clients will | ||
* not send the cookie back to the server in the future if the browser does | ||
* not have an HTTPS connection. | ||
*/ | ||
secure?: boolean; | ||
} | ||
/** | ||
* Parse the request to get HTTP Cookie header string and returning an object of all cookie name-value pairs. | ||
* @param req {IncomingMessage} An IncomingMessage object created by [http.Server](https://nodejs.org/api/http.html#http_class_http_server) | ||
* @param event {CompatibilityEvent} H3 event or req passed by h3 handler | ||
* @returns Object of cookie name-value pairs | ||
@@ -221,6 +178,6 @@ * ```ts | ||
*/ | ||
declare function useCookies(req: IncomingMessage): Record<string, string>; | ||
declare function useCookies(event: CompatibilityEvent): Record<string, string>; | ||
/** | ||
* Get a cookie value by name. | ||
* @param req {IncomingMessage} An IncomingMessage object created by [http.Server](https://nodejs.org/api/http.html#http_class_http_server) | ||
* @param event {CompatibilityEvent} H3 event or req passed by h3 handler | ||
* @param name Name of the cookie to get | ||
@@ -232,6 +189,6 @@ * @returns {*} Value of the cookie (String or undefined) | ||
*/ | ||
declare function useCookie(req: IncomingMessage, name: string): string | undefined; | ||
declare function useCookie(event: CompatibilityEvent, name: string): string | undefined; | ||
/** | ||
* Set a cookie value by name. | ||
* @param res {ServerResponse} A ServerResponse object created by [http.Server](https://nodejs.org/api/http.html#http_class_http_server) | ||
* @param event {CompatibilityEvent} H3 event or res passed by h3 handler | ||
* @param name Name of the cookie to set | ||
@@ -244,6 +201,6 @@ * @param value Value of the cookie to set | ||
*/ | ||
declare function setCookie(res: ServerResponse, name: string, value: string, serializeOptions?: CookieSerializeOptions): void; | ||
declare function setCookie(event: CompatibilityEvent, name: string, value: string, serializeOptions?: CookieSerializeOptions): void; | ||
/** | ||
* Set a cookie value by name. | ||
* @param res {ServerResponse} A ServerResponse object created by [http.Server](https://nodejs.org/api/http.html#http_class_http_server) | ||
* @param event {CompatibilityEvent} H3 event or res passed by h3 handler | ||
* @param name Name of the cookie to delete | ||
@@ -255,30 +212,26 @@ * @param serializeOptions {CookieSerializeOptions} Cookie options | ||
*/ | ||
declare function deleteCookie(res: ServerResponse, name: string, serializeOptions?: CookieSerializeOptions): void; | ||
declare function deleteCookie(event: CompatibilityEvent, name: string, serializeOptions?: CookieSerializeOptions): void; | ||
declare type HTTPMethod = 'GET' | 'HEAD' | 'POST' | 'PUT' | 'DELETE' | 'CONNECT' | 'OPTIONS' | 'TRACE'; | ||
declare function useQuery(event: CompatibilityEvent): ufo.QueryObject; | ||
declare function useMethod(event: CompatibilityEvent, defaultMethod?: HTTPMethod): HTTPMethod; | ||
declare function isMethod(event: CompatibilityEvent, expected: HTTPMethod | HTTPMethod[], allowHead?: boolean): boolean; | ||
declare function assertMethod(event: CompatibilityEvent, expected: HTTPMethod | HTTPMethod[], allowHead?: boolean): void; | ||
declare function useQuery(req: IncomingMessage): ufo.QueryObject; | ||
declare function useMethod(req: IncomingMessage, defaultMethod?: HTTPMethod): HTTPMethod; | ||
declare function isMethod(req: IncomingMessage, expected: HTTPMethod | HTTPMethod[], allowHead?: boolean): boolean; | ||
declare function assertMethod(req: IncomingMessage, expected: HTTPMethod | HTTPMethod[], allowHead?: boolean): void; | ||
declare function send(event: CompatibilityEvent, data: any, type?: string): Promise<void>; | ||
declare function defaultContentType(event: CompatibilityEvent, type?: string): void; | ||
declare function sendRedirect(event: CompatibilityEvent, location: string, code?: number): Promise<void>; | ||
declare function appendHeader(event: CompatibilityEvent, name: string, value: string): void; | ||
declare function isStream(data: any): any; | ||
declare function sendStream(event: CompatibilityEvent, data: any): Promise<void>; | ||
declare function send(res: ServerResponse, data: any, type?: string): Promise<void>; | ||
declare function defaultContentType(res: ServerResponse, type?: string): void; | ||
declare function sendRedirect(res: ServerResponse, location: string, code?: number): Promise<void>; | ||
declare function appendHeader(res: ServerResponse, name: string, value: string): void; | ||
declare function isStream(data: any): boolean; | ||
declare function sendStream(res: ServerResponse, data: any): Promise<unknown>; | ||
declare type RouterMethod = Lowercase<HTTPMethod>; | ||
declare type HandleWithParams = Handle<any, { | ||
params: Record<string, string>; | ||
}>; | ||
declare type AddWithMethod = (path: string, handle: HandleWithParams) => Router; | ||
declare type AddRouteShortcuts = Record<Lowercase<HTTPMethod>, AddWithMethod>; | ||
declare type RouterUse = (path: string, handler: CompatibilityEventHandler, method?: RouterMethod) => Router; | ||
declare type AddRouteShortcuts = Record<RouterMethod, RouterUse>; | ||
interface Router extends AddRouteShortcuts { | ||
add: (path: string, handle: HandleWithParams, method?: RouterMethod | 'all') => Router; | ||
handle: Handle; | ||
add: RouterUse; | ||
use: RouterUse; | ||
handler: EventHandler; | ||
} | ||
declare function createRouter(): Router; | ||
export { AddRouteShortcuts, AddWithMethod, App, AppOptions, AppUse, H3Error, Handle, HandleWithParams, InputLayer, InputStack, Layer, LazyHandle, MIMES, Matcher, Middleware, PHandle, Router, RouterMethod, Stack, appendHeader, assertMethod, callHandle, createApp, createError, createHandle, createRouter, defaultContentType, defineHandle, defineMiddleware, deleteCookie, isMethod, isStream, lazyHandle, promisifyHandle, send, sendError, sendRedirect, sendStream, setCookie, use, useBase, useBody, useCookie, useCookies, useMethod, useQuery, useRawBody }; | ||
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 }; |
{ | ||
"name": "h3", | ||
"version": "0.4.2", | ||
"version": "0.5.0", | ||
"description": "Tiny JavaScript Server", | ||
@@ -50,4 +50,5 @@ "repository": "unjs/h3", | ||
"build": "unbuild", | ||
"dev": "jiti ./playground/index.ts", | ||
"dev": "vitest", | ||
"lint": "eslint --ext ts,mjs,cjs .", | ||
"play": "jiti ./playground/index.ts", | ||
"profile": "0x -o -D .profile -P 'autocannon -c 100 -p 10 -d 40 http://localhost:$PORT' ./playground/server.cjs", | ||
@@ -57,3 +58,3 @@ "release": "pnpm lint && pnpm test && pnpm build && standard-version && pnpm publish && git push --follow-tags", | ||
}, | ||
"readme": "[![npm downloads](https://img.shields.io/npm/dm/h3.svg?style=flat-square)](https://npmjs.com/package/h3)\n[![version](https://img.shields.io/npm/v/h3/latest.svg?style=flat-square)](https://npmjs.com/package/h3)\n[![bundlephobia](https://img.shields.io/bundlephobia/min/h3/latest.svg?style=flat-square)](https://bundlephobia.com/result?p=h3)\n[![build status](https://img.shields.io/github/workflow/status/unjs/h3/ci/main?style=flat-square)](https://github.com/unjs/h3/actions)\n[![coverage](https://img.shields.io/codecov/c/gh/unjs/h3/main?style=flat-square)](https://codecov.io/gh/unjs/h3)\n[![jsDocs.io](https://img.shields.io/badge/jsDocs.io-reference-blue?style=flat-square)](https://www.jsdocs.io/package/h3)\n\n> H3 is a minimal h(ttp) framework built for high performance and portability\n\n<!-- ![h3 - Tiny JavaScript Server](.github/banner.svg) -->\n\n## Features\n\n✔️ **Portable:** Works perfectly in Serverless, Workers, and Node.js\n\n✔️ **Compatible:** Support connect/express middleware\n\n✔️ **Minimal:** Small, tree-shakable and zero-dependency\n\n✔️ **Modern:** Native promise support\n\n✔️ **Extendable:** Ships with a set of composable utilities but can be extended\n\n✔️ **Router:** Super fast route matching using [unjs/radix3](https://github.com/unjs/radix3)\n\n## Install\n\n```bash\n# Using npm\nnpm install h3\n\n# Using pnpm\npnpm add h3\n\n# Using pnpm\npnpm add h3\n```\n\n## Usage\n\n```ts\nimport { createServer } from 'http'\nimport { createApp } from 'h3'\n\nconst app = createApp()\napp.use('/', () => 'Hello world!')\n\ncreateServer(app).listen(process.env.PORT || 3000)\n```\n\n<details>\n <summary>Example using <a href=\"https://github.com/unjs/listhen\">listhen</a> for an elegant listener.</summary>\n\n```ts\nimport { createApp } from 'h3'\nimport { listen } from 'listhen'\n\nconst app = createApp()\napp.use('/', () => 'Hello world!')\n\nlisten(app)\n```\n</details>\n\n## Router\n\nThe `app` instance created by `h3` uses a middleware stack (see [how it works](#how-it-works)) with the ability to match route prefix and apply matched middleware.\n\nTo opt-in using a more advanced and convenient routing system, we can create a router instance and register it to app instance.\n\n```ts\nimport { createApp, createRouter } from 'h3'\n\nconst app = createApp()\n\nconst router = createRouter()\n .get('/', () => 'Hello World!')\n .get('/hello/:name', req => `Hello ${req.params.name}!`)\n\napp.use(router)\n```\n\n**Tip:** We can register same route more than once with different methods.\n\nRoutes are internally stored in a [Radix Tree](https://en.wikipedia.org/wiki/Radix_tree) and matched using [unjs/radix3](https://github.com/unjs/radix3).\n\n## More usage examples\n\n```js\n// Handle can directly return object or Promise<object> for JSON response\napp.use('/api', (req) => ({ url: req.url }))\n\n// We can have better matching other than quick prefix match\napp.use('/odd', () => 'Is odd!', { match: url => url.substr(1) % 2 })\n\n// Handle can directly return string for HTML response\napp.use(() => '<h1>Hello world!</h1>')\n\n// We can chain calls to .use()\napp.use('/1', () => '<h1>Hello world!</h1>')\n .use('/2', () => '<h1>Goodbye!</h1>')\n\n// Legacy middleware with 3rd argument are automatically promisified\napp.use((req, res, next) => { req.setHeader('X-Foo', 'bar'); next() })\n\n// Force promisify a legacy middleware\n// app.use(someMiddleware, { promisify: true })\n\n// Lazy loaded routes using { lazy: true }\n// app.use('/big', () => import('./big'), { lazy: true })\n```\n\n## Utilities\n\nInstead of adding helpers to `req` and `res`, h3 exposes them as composable utilities.\n\n- `useRawBody(req, encoding?)`\n- `useBody(req)`\n- `useCookies(req)`\n- `useCookie(req, name)`\n- `setCookie(res, name, value, opts?)`\n- `deleteCookie(res, name, opts?)`\n- `useQuery(req)`\n- `send(res, data, type?)`\n- `sendRedirect(res, location, code=302)`\n- `appendHeader(res, name, value)`\n- `createError({ statusCode, statusMessage, data? })`\n- `sendError(res, error, debug?)`\n- `defineHandle(handle)`\n- `defineMiddleware(middlware)`\n- `useMethod(req, default?)`\n- `isMethod(req, expected, allowHead?)`\n- `assertMethod(req, expected, allowHead?)`\n\n👉 You can learn more about usage in [JSDocs Documentation](https://www.jsdocs.io/package/h3#package-functions).\n\n## How it works?\n\nUsing `createApp`, it returns a standard `(req, res)` handler function and internally an array called middleware stack. using`use()` method we can add an item to this internal stack.\n\nWhen a request comes, each stack item that matches the route will be called and resolved until [`res.writableEnded`](https://nodejs.org/api/http.html#http_response_writableended) flag is set, which means the response is sent. If `writableEnded` is not set after all middleware, a `404` error will be thrown. And if one of the stack items resolves to a value, it will be serialized and sent as response as a shorthand method to sending responses.\n\nFor maximum compatibility with connect/express middleware (`req, res, next?` signature), h3 converts classic middleware into a promisified version ready to use with stack runner:\n\n- If middleware has 3rd next/callback param, the promise will `resolve/reject` when called\n- If middleware returns a promise, it will be **chained** to the main promise\n- If calling middleware throws an immediate error, the promise will be rejected\n- On `close` and `error` events of res, the promise will `resolve/reject` (to ensure if middleware simply calls `res.end`)\n\n## License\n\nMIT\n" | ||
"readme": "[![npm downloads](https://img.shields.io/npm/dm/h3.svg?style=flat-square)](https://npmjs.com/package/h3)\n[![version](https://img.shields.io/npm/v/h3/latest.svg?style=flat-square)](https://npmjs.com/package/h3)\n[![bundlephobia](https://img.shields.io/bundlephobia/min/h3/latest.svg?style=flat-square)](https://bundlephobia.com/result?p=h3)\n[![build status](https://img.shields.io/github/workflow/status/unjs/h3/ci/main?style=flat-square)](https://github.com/unjs/h3/actions)\n[![coverage](https://img.shields.io/codecov/c/gh/unjs/h3/main?style=flat-square)](https://codecov.io/gh/unjs/h3)\n[![jsDocs.io](https://img.shields.io/badge/jsDocs.io-reference-blue?style=flat-square)](https://www.jsdocs.io/package/h3)\n\n> H3 is a minimal h(ttp) framework built for high performance and portability\n\n<!-- ![h3 - Tiny JavaScript Server](.github/banner.svg) -->\n\n## Features\n\n✔️ **Portable:** Works perfectly in Serverless, Workers, and Node.js\n\n✔️ **Compatible:** Support connect/express middleware\n\n✔️ **Minimal:** Small, tree-shakable and zero-dependency\n\n✔️ **Modern:** Native promise support\n\n✔️ **Extendable:** Ships with a set of composable utilities but can be extended\n\n✔️ **Router:** Super fast route matching using [unjs/radix3](https://github.com/unjs/radix3)\n\n## Install\n\n```bash\n# Using npm\nnpm install h3\n\n# Using yarn\nyarn add h3\n\n# Using pnpm\npnpm add h3\n```\n\n## Usage\n\n```ts\nimport { createServer } from 'http'\nimport { createApp } from 'h3'\n\nconst app = createApp()\napp.use('/', () => 'Hello world!')\n\ncreateServer(app).listen(process.env.PORT || 3000)\n```\n\n<details>\n <summary>Example using <a href=\"https://github.com/unjs/listhen\">listhen</a> for an elegant listener.</summary>\n\n```ts\nimport { createApp } from 'h3'\nimport { listen } from 'listhen'\n\nconst app = createApp()\napp.use('/', () => 'Hello world!')\n\nlisten(app)\n```\n</details>\n\n## Router\n\nThe `app` instance created by `h3` uses a middleware stack (see [how it works](#how-it-works)) with the ability to match route prefix and apply matched middleware.\n\nTo opt-in using a more advanced and convenient routing system, we can create a router instance and register it to app instance.\n\n```ts\nimport { createApp, createRouter } from 'h3'\n\nconst app = createApp()\n\nconst router = createRouter()\n .get('/', () => 'Hello World!')\n .get('/hello/:name', req => `Hello ${req.params.name}!`)\n\napp.use(router)\n```\n\n**Tip:** We can register same route more than once with different methods.\n\nRoutes are internally stored in a [Radix Tree](https://en.wikipedia.org/wiki/Radix_tree) and matched using [unjs/radix3](https://github.com/unjs/radix3).\n\n## More usage examples\n\n```js\n// Handle can directly return object or Promise<object> for JSON response\napp.use('/api', (req) => ({ url: req.url }))\n\n// We can have better matching other than quick prefix match\napp.use('/odd', () => 'Is odd!', { match: url => url.substr(1) % 2 })\n\n// Handle can directly return string for HTML response\napp.use(() => '<h1>Hello world!</h1>')\n\n// We can chain calls to .use()\napp.use('/1', () => '<h1>Hello world!</h1>')\n .use('/2', () => '<h1>Goodbye!</h1>')\n\n// Legacy middleware with 3rd argument are automatically promisified\napp.use((req, res, next) => { req.setHeader('X-Foo', 'bar'); next() })\n\n// Force promisify a legacy middleware\n// app.use(someMiddleware, { promisify: true })\n\n// Lazy loaded routes using { lazy: true }\n// app.use('/big', () => import('./big'), { lazy: true })\n```\n\n## Utilities\n\nInstead of adding helpers to `req` and `res`, h3 exposes them as composable utilities.\n\n- `useRawBody(req, encoding?)`\n- `useBody(req)`\n- `useCookies(req)`\n- `useCookie(req, name)`\n- `setCookie(res, name, value, opts?)`\n- `deleteCookie(res, name, opts?)`\n- `useQuery(req)`\n- `send(res, data, type?)`\n- `sendRedirect(res, location, code=302)`\n- `appendHeader(res, name, value)`\n- `createError({ statusCode, statusMessage, data? })`\n- `sendError(res, error, debug?)`\n- `defineHandle(handle)`\n- `defineMiddleware(middlware)`\n- `useMethod(req, default?)`\n- `isMethod(req, expected, allowHead?)`\n- `assertMethod(req, expected, allowHead?)`\n\n👉 You can learn more about usage in [JSDocs Documentation](https://www.jsdocs.io/package/h3#package-functions).\n\n## How it works?\n\nUsing `createApp`, it returns a standard `(req, res)` handler function and internally an array called middleware stack. using`use()` method we can add an item to this internal stack.\n\nWhen a request comes, each stack item that matches the route will be called and resolved until [`res.writableEnded`](https://nodejs.org/api/http.html#http_response_writableended) flag is set, which means the response is sent. If `writableEnded` is not set after all middleware, a `404` error will be thrown. And if one of the stack items resolves to a value, it will be serialized and sent as response as a shorthand method to sending responses.\n\nFor maximum compatibility with connect/express middleware (`req, res, next?` signature), h3 converts classic middleware into a promisified version ready to use with stack runner:\n\n- If middleware has 3rd next/callback param, the promise will `resolve/reject` when called\n- If middleware returns a promise, it will be **chained** to the main promise\n- If calling middleware throws an immediate error, the promise will be rejected\n- On `close` and `error` events of res, the promise will `resolve/reject` (to ensure if middleware simply calls `res.end`)\n\n## License\n\nMIT\n" | ||
} |
@@ -32,4 +32,4 @@ [![npm downloads](https://img.shields.io/npm/dm/h3.svg?style=flat-square)](https://npmjs.com/package/h3) | ||
# Using pnpm | ||
pnpm add h3 | ||
# Using yarn | ||
yarn add h3 | ||
@@ -36,0 +36,0 @@ # Using pnpm |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
50239
1088