diff --git a/.config/automd.yaml b/.config/automd.yaml new file mode 100644 index 00000000..63e39fe7 --- /dev/null +++ b/.config/automd.yaml @@ -0,0 +1 @@ +input: ["README.md", "docs/**/*.md"] diff --git a/.github/workflows/autofix.yml b/.github/workflows/autofix.yml index 5cb2623f..55b1a12e 100644 --- a/.github/workflows/autofix.yml +++ b/.github/workflows/autofix.yml @@ -16,11 +16,11 @@ jobs: - run: corepack enable - uses: actions/setup-node@v4 with: - node-version: 18 + node-version: 20 cache: "pnpm" - run: pnpm install - - name: Fix lint issues - run: pnpm run lint:fix + - run: pnpm run lint:fix + - run: pnpm automd - uses: autofix-ci/action@ea32e3a12414e6d3183163c3424a7d7a8631ad84 with: - commit-message: "chore: apply automated fixes" + commit-message: "chore: apply automated updates" diff --git a/README.md b/README.md index 2f3d0fd6..9acfb81b 100644 --- a/README.md +++ b/README.md @@ -1,47 +1,48 @@ # H3 -[![npm version][npm-version-src]][npm-version-href] -[![npm downloads][npm-downloads-src]][npm-downloads-href] -[![bundle][bundle-src]][bundle-href] -[![Codecov][codecov-src]][codecov-href] -[![License][license-src]][license-href] -[![JSDocs][jsdocs-src]][jsdocs-href] + + +[![npm version](https://flat.badgen.net/npm/v/h3)](https://npmjs.com/package/h3) +[![npm downloads](https://flat.badgen.net/npm/dm/h3)](https://npmjs.com/package/h3) + + H3 (pronounced as /eΙͺtΚƒΞΈriː/, like h-3) is a minimal h(ttp) framework built for high performance and portability. -πŸ‘‰ [Online Playground](https://stackblitz.com/github/unjs/h3/tree/main/playground) +πŸ‘‰ [Documentation](https://h3.unjs.io) -πŸ‘‰ [Online Examples Playground](https://stackblitz.com/github/unjs/h3/tree/main/examples) +## Contribution -## Features +
+ Local development -βœ”οΈ  **Portable:** Works perfectly in Serverless, Workers, and Node.js +- Clone this repository +- Install the latest LTS version of [Node.js](https://nodejs.org/en/) +- Enable [Corepack](https://github.com/nodejs/corepack) using `corepack enable` +- Install dependencies using `pnpm install` +- Run tests using `pnpm dev` or `pnpm test` -βœ”οΈ  **Minimal:** Small and tree-shakable +
-βœ”οΈ  **Modern:** Native promise support + -βœ”οΈ  **Extendable:** Ships with a set of composable utilities but can be extended +## License -βœ”οΈ  **Router:** Super fast route matching using [unjs/radix3](https://github.com/unjs/radix3) + -βœ”οΈ  **Compatible:** Compatibility layer with node/connect/express middleware +Published under the [MIT](https://github.com/unjs/h3/blob/main/LICENSE) license. +Made by [@pi0](https://github.com/pi0) and [community](https://github.com/unjs/h3/graphs/contributors) πŸ’› +

+ + + -## License + + + + +--- + +_πŸ€– auto updated with [automd](https://automd.unjs.io)_ -MIT - - - -[npm-version-src]: https://img.shields.io/npm/v/h3?style=flat&colorA=18181B&colorB=F0DB4F -[npm-version-href]: https://npmjs.com/package/h3 -[npm-downloads-src]: https://img.shields.io/npm/dm/h3?style=flat&colorA=18181B&colorB=F0DB4F -[npm-downloads-href]: https://npmjs.com/package/h3 -[codecov-src]: https://img.shields.io/codecov/c/gh/unjs/h3/main?style=flat&colorA=18181B&colorB=F0DB4F -[codecov-href]: https://codecov.io/gh/unjs/h3 -[bundle-src]: https://img.shields.io/bundlephobia/minzip/h3?style=flat&colorA=18181B&colorB=F0DB4F -[bundle-href]: https://bundlephobia.com/result?p=h3 -[license-src]: https://img.shields.io/github/license/unjs/h3.svg?style=flat&colorA=18181B&colorB=F0DB4F -[license-href]: https://github.com/unjs/h3/blob/main/LICENSE -[jsdocs-src]: https://img.shields.io/badge/jsDocs.io-reference-18181B?style=flat&colorA=18181B&colorB=F0DB4F -[jsdocs-href]: https://www.jsdocs.io/package/h3 + diff --git a/docs/2.utils/1.request.md b/docs/2.utils/1.request.md index e281454e..1dca82d5 100644 --- a/docs/2.utils/1.request.md +++ b/docs/2.utils/1.request.md @@ -2,7 +2,7 @@ > Utilities to access incoming request - + ### `assertMethod(event, expected, allowHead?)` @@ -38,7 +38,7 @@ - + ### `getRequestFingerprint(event, opts)` @@ -46,7 +46,7 @@ ## Body utils - + ### `getRequestWebStream(event)` diff --git a/docs/2.utils/2.reponse.md b/docs/2.utils/2.reponse.md index a8010000..a432f0a3 100644 --- a/docs/2.utils/2.reponse.md +++ b/docs/2.utils/2.reponse.md @@ -2,7 +2,7 @@ > Utilities to send response headers and data - + ### `appendHeader(event, name, value)` diff --git a/docs/2.utils/98.advanced.md b/docs/2.utils/98.advanced.md index fbc33f68..d9029207 100644 --- a/docs/2.utils/98.advanced.md +++ b/docs/2.utils/98.advanced.md @@ -4,7 +4,7 @@ ## Session utils - + ### `clearSession(event, config)` @@ -22,7 +22,7 @@ ## Cookie utils - + ### `deleteCookie(event, name, serializeOptions?)` @@ -42,13 +42,13 @@ Set a cookie value by name. ### `splitCookiesString(cookiesString)` -Set-Cookie header field-values are sometimes comma joined in one string. This splits them without choking on commas that are within a single set-cookie field-value, such as in the Expires portion. This is uncommon, but explicitly allowed - see https://tools.ietf.org/html/rfc2616#section-4.2 Node.js does this for every header _except_ set-cookie - see https://github.com/nodejs/node/blob/d5e363b77ebaf1caf67cd7528224b651c86815c1/lib/_http_incoming.js#L128 Based on: https://github.com/google/j2objc/commit/16820fdbc8f76ca0c33472810ce0cb03d20efe25 Credits to: https://github.com/tomball for original and https://github.com/chrusart for JavaScript implementation +Set-Cookie header field-values are sometimes comma joined in one string. This splits them without choking on commas that are within a single set-cookie field-value, such as in the Expires portion. This is uncommon, but explicitly allowed - see https://tools.ietf.org/html/rfc2616#section-4.2 Node.js does this for every header *except* set-cookie - see https://github.com/nodejs/node/blob/d5e363b77ebaf1caf67cd7528224b651c86815c1/lib/_http_incoming.js#L128 Based on: https://github.com/google/j2objc/commit/16820fdbc8f76ca0c33472810ce0cb03d20efe25 Credits to: https://github.com/tomball for original and https://github.com/chrusart for JavaScript implementation ## Sanitize - + ### `sanitizeStatusCode(statusCode?, defaultStatusCode)` @@ -58,7 +58,7 @@ Set-Cookie header field-values are sometimes comma joined in one string. This sp ## Route - + ### `useBase(base, handler)` @@ -68,7 +68,7 @@ Prefixes and executes a handler with a base path. ## Cache - + ### `handleCacheHeaders(event, opts)` @@ -78,7 +78,7 @@ Check request caching headers (`If-Modified-Since`) and add caching headers (Las ## Proxy - + ### `fetchWithEvent(event, req, init?, options?: { fetch: F })` @@ -92,7 +92,7 @@ Check request caching headers (`If-Modified-Since`) and add caching headers (Las ## CORS - + ### `appendCorsHeaders(event, options)` diff --git a/package.json b/package.json index 1d3dbd6d..8b404eb0 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "@types/supertest": "^6.0.2", "@vitest/coverage-v8": "^1.3.1", "autocannon": "^7.15.0", + "automd": "^0.3.5", "changelogen": "^0.5.5", "connect": "^3.7.0", "eslint": "^8.56.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d1ce55ed..26ab8975 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -54,6 +54,9 @@ importers: autocannon: specifier: ^7.15.0 version: 7.15.0 + automd: + specifier: ^0.3.5 + version: 0.3.5 changelogen: specifier: ^0.5.5 version: 0.5.5 @@ -339,6 +342,13 @@ packages: '@babel/types': 7.23.9 dev: true + /@babel/runtime@7.23.9: + resolution: {integrity: sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==} + engines: {node: '>=6.9.0'} + dependencies: + regenerator-runtime: 0.14.1 + dev: true + /@babel/standalone@7.23.9: resolution: {integrity: sha512-89NGhVfgKDqDQrtNPxqfnhIReKvp2CR80ofPNEAUpbtnouFelq33hQFURLralD9I+eFS7s5zVK61JRg/D1nLWg==} engines: {node: '>=6.9.0'} @@ -1055,6 +1065,11 @@ packages: resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} dev: true + /@sindresorhus/merge-streams@2.3.0: + resolution: {integrity: sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==} + engines: {node: '>=18'} + dev: true + /@trysound/sax@0.2.0: resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} engines: {node: '>=10.13.0'} @@ -1625,6 +1640,30 @@ packages: timestring: 6.0.0 dev: true + /automd@0.3.5: + resolution: {integrity: sha512-JScZoTTu8Skf49zqFfRUJVShGfiAWDMAi7FtXyLWSo2t+bBe+zZjK+lZbYhWoBcFwH8m0oJSKT6N1SndglUJ8A==} + hasBin: true + dependencies: + '@parcel/watcher': 2.4.0 + c12: 1.9.0 + citty: 0.1.5 + consola: 3.2.3 + defu: 6.1.4 + destr: 2.0.3 + didyoumean2: 6.0.1 + globby: 14.0.1 + magic-string: 0.30.7 + mlly: 1.6.0 + ofetch: 1.3.3 + omark: 0.1.0 + pathe: 1.1.2 + pkg-types: 1.0.3 + scule: 1.3.0 + untyped: 1.4.2 + transitivePeerDependencies: + - supports-color + dev: true + /autoprefixer@10.4.17(postcss@8.4.33): resolution: {integrity: sha512-/cpVNRLSfhOtcGflT13P2794gVSgmPgTR+erw5ifnMLZb0UnSlkK4tquLmkd3BhA+nLo5tX8Cu0upUsGKvKbmg==} engines: {node: ^10 || ^12 || >=14} @@ -1935,6 +1974,23 @@ packages: rc9: 2.1.1 dev: true + /c12@1.9.0: + resolution: {integrity: sha512-7KTCZXdIbOA2hLRQ+1KzJ15Qp9Wn58one74dkihMVp2H6EzKTa3OYBy0BSfS1CCcmxYyqeX8L02m40zjQ+dstg==} + dependencies: + chokidar: 3.5.3 + confbox: 0.1.3 + defu: 6.1.4 + dotenv: 16.4.1 + giget: 1.2.1 + jiti: 1.21.0 + mlly: 1.6.0 + ohash: 1.1.3 + pathe: 1.1.2 + perfect-debounce: 1.0.0 + pkg-types: 1.0.3 + rc9: 2.1.1 + dev: true + /cac@6.7.14: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} @@ -2210,6 +2266,10 @@ packages: typedarray: 0.0.6 dev: true + /confbox@0.1.3: + resolution: {integrity: sha512-eH3ZxAihl1PhKfpr4VfEN6/vUd87fmgb6JkldHgg/YR6aEBhW63qUDgzP2Y6WM0UumdsYp5H3kibalXAdHfbgg==} + dev: true + /connect@3.7.0: resolution: {integrity: sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==} engines: {node: '>= 0.10.0'} @@ -2730,6 +2790,15 @@ packages: wrappy: 1.0.2 dev: true + /didyoumean2@6.0.1: + resolution: {integrity: sha512-PSy0zQwMg5O+LjT5Mz7vnKC8I7DfWLPF6M7oepqW7WP5mn2CY3hz46xZOa1GJY+KVfyXhdmz6+tdgXwrHlZc5g==} + engines: {node: ^16.14.0 || >=18.12.0} + dependencies: + '@babel/runtime': 7.23.9 + fastest-levenshtein: 1.0.16 + lodash.deburr: 4.1.0 + dev: true + /diff-sequences@29.6.3: resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -3505,6 +3574,11 @@ packages: resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} dev: true + /fastest-levenshtein@1.0.16: + resolution: {integrity: sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==} + engines: {node: '>= 4.9.1'} + dev: true + /fastq@1.16.0: resolution: {integrity: sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==} dependencies: @@ -3826,6 +3900,18 @@ packages: slash: 4.0.0 dev: true + /globby@14.0.1: + resolution: {integrity: sha512-jOMLD2Z7MAhyG8aJpNOpmziMOP4rPLcc95oQPKXBazW82z+CEgPFBQvEpRUa1KeIMUJo4Wsm+q6uzO/Q/4BksQ==} + engines: {node: '>=18'} + dependencies: + '@sindresorhus/merge-streams': 2.3.0 + fast-glob: 3.3.2 + ignore: 5.3.0 + path-type: 5.0.0 + slash: 5.1.0 + unicorn-magic: 0.1.0 + dev: true + /gopd@1.0.1: resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} dependencies: @@ -4605,6 +4691,10 @@ packages: resolution: {integrity: sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==} dev: true + /lodash.deburr@4.1.0: + resolution: {integrity: sha512-m/M1U1f3ddMCs6Hq2tAsYThTBDaAKFDX3dwDo97GEYzamXi9SqUpjWi/Rrj/gf3X2n8ktwgZrlP1z6E3v/IExQ==} + dev: true + /lodash.flatten@4.4.0: resolution: {integrity: sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==} dev: true @@ -4672,6 +4762,13 @@ packages: '@jridgewell/sourcemap-codec': 1.4.15 dev: true + /magic-string@0.30.7: + resolution: {integrity: sha512-8vBuFF/I/+OSLRmdf2wwFCJCz+nSn0m6DPvGH1fS/KiQoSaR+sETbov0eIk9KhEKy8CYqIkIAnbohxT/4H0kuA==} + engines: {node: '>=12'} + dependencies: + '@jridgewell/sourcemap-codec': 1.4.15 + dev: true + /magicast@0.3.3: resolution: {integrity: sha512-ZbrP1Qxnpoes8sz47AM0z08U+jW6TyRgZzcWy3Ma3vDhJttwMwAFDMMQFobwdBxByBD46JYmxRzeF7w2+wJEuw==} dependencies: @@ -4891,6 +4988,14 @@ packages: pkg-types: 1.0.3 ufo: 1.4.0 + /mlly@1.6.0: + resolution: {integrity: sha512-YOvg9hfYQmnaB56Yb+KrJE2u0Yzz5zR+sLejEvF4fzwzV1Al6hkf2vyHTwqCRyv0hCi9rVCqVoXpyYevQIRwLQ==} + dependencies: + acorn: 8.11.3 + pathe: 1.1.2 + pkg-types: 1.0.3 + ufo: 1.4.0 + /module-deps@6.2.3: resolution: {integrity: sha512-fg7OZaQBcL4/L+AK5f4iVqf9OMbCclXfy/znXRxTVhJSeW5AIlS9AwheYwDaXM3lVW7OBeaeUEY3gbaC6cLlSA==} engines: {node: '>= 0.8.0'} @@ -5126,6 +5231,10 @@ packages: /ohash@1.1.3: resolution: {integrity: sha512-zuHHiGTYTA1sYJ/wZN+t5HKZaH23i4yI1HMwbuXm24Nid7Dv0KcuRlKoNKS9UNfAVSBlnGLcuQrnOKWOZoEGaw==} + /omark@0.1.0: + resolution: {integrity: sha512-l+7hOfsjru88QuW7E937KH7BSz99NownkNTGigi+e4JzeSSCosMp2v3eVW1wdmgm99pFbzaUVg1kiT2V0QvvtQ==} + dev: true + /on-finished@2.3.0: resolution: {integrity: sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==} engines: {node: '>= 0.8'} @@ -5319,6 +5428,11 @@ packages: engines: {node: '>=8'} dev: true + /path-type@5.0.0: + resolution: {integrity: sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==} + engines: {node: '>=12'} + dev: true + /pathe@1.1.2: resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} @@ -5353,7 +5467,7 @@ packages: resolution: {integrity: sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==} dependencies: jsonc-parser: 3.2.1 - mlly: 1.5.0 + mlly: 1.6.0 pathe: 1.1.2 /pluralize@8.0.0: @@ -5906,6 +6020,10 @@ packages: picomatch: 2.3.1 dev: true + /regenerator-runtime@0.14.1: + resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} + dev: true + /regexp-tree@0.1.27: resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==} hasBin: true @@ -6087,6 +6205,10 @@ packages: resolution: {integrity: sha512-CRCmi5zHQnSoeCik9565PONMg0kfkvYmcSqrbOJY4txFfy1wvVULV4FDaiXhUblUgahdqz3F2NwHZ8i4eBTwUw==} dev: true + /scule@1.3.0: + resolution: {integrity: sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==} + dev: true + /semver@5.7.2: resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} hasBin: true @@ -6230,6 +6352,11 @@ packages: engines: {node: '>=12'} dev: true + /slash@5.1.0: + resolution: {integrity: sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==} + engines: {node: '>=14.16'} + dev: true + /source-map-js@1.0.2: resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} engines: {node: '>=0.10.0'} @@ -6841,6 +6968,11 @@ packages: node-fetch-native: 1.6.2 pathe: 1.1.2 + /unicorn-magic@0.1.0: + resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==} + engines: {node: '>=18'} + dev: true + /universalify@2.0.1: resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} engines: {node: '>= 10.0.0'}