diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index f17596c..f1655a9 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -23,12 +23,11 @@ jobs:
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v4
- - name: Enable corepack
- run: corepack enable pnpm
+ - uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
- node-version: 20
- cache: 'pnpm'
+ node-version: 18.13
+ cache: "pnpm"
- run: pnpm install
- run: pnpm test:coverage
- run: pnpm test:report
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index 55c4adb..3fdd8a8 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -10,14 +10,12 @@ jobs:
id-token: write
steps:
- uses: actions/checkout@v4
- - name: Enable corepack
- run: corepack enable pnpm
-
+ - uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
- cache: 'pnpm'
+ cache: "pnpm"
node-version: 20
- registry-url: 'https://registry.npmjs.org'
+ registry-url: "https://registry.npmjs.org"
- run: pnpm install
- run: pnpm build
- name: Setup Biome
@@ -29,4 +27,4 @@ jobs:
run: biome ci .
- run: pnpm publish --no-git-checks
env:
- NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
\ No newline at end of file
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
diff --git a/README.md b/README.md
index 128dfb0..42fa3cb 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,9 @@
-[![Version][v-badge-url]][npm-url] [![Coverage][cov-img]][cov-url] [![Github actions][gh-actions-img]][github-actions] [![Downloads][dl-badge-url]][npm-url]
+[![Version][v-badge-url]][npm-url] [![Coverage][cov-img]][cov-url]
+[![Github actions][gh-actions-img]][github-actions]
+[![Downloads][dl-badge-url]][npm-url]
@@ -18,7 +20,7 @@ Check out [deno-libs/parsec](https://github.com/deno-libs/parsec) for Deno port.
- 📦 tiny package size (8KB dist size)
- 🔥 no dependencies
- ✨ [tinyhttp](https://github.com/tinyhttp/tinyhttp) and Express support
-- ⚡ 30% faster than body-parser
+- ⚡ 40% faster than body-parser and 20x faster than formidable
## Install
@@ -51,7 +53,8 @@ const server = createServer(async (req: ReqWithBody, res) => {
### What is "parsec"?
-The parsec is a unit of length used to measure large distances to astronomical objects outside the Solar System.
+The parsec is a unit of length used to measure large distances to astronomical
+objects outside the Solar System.
[v-badge-url]: https://img.shields.io/npm/v/milliparsec.svg?style=for-the-badge&color=25608B&logo=npm&label=
[npm-url]: https://www.npmjs.com/package/milliparsec
diff --git a/bench/index.md b/bench/index.md
index 5d6b545..d747666 100644
--- a/bench/index.md
+++ b/bench/index.md
@@ -1,13 +1,16 @@
# Benchmark
-Below are benchmarks of body-parser vs milliparsec and formidable vs milliparsec. Please take into account that these benchmarks are not entirely accurate, since they are taken on a regular desktop computer in usual conditions.
+Below are benchmarks of body-parser vs milliparsec and formidable vs
+milliparsec. Please take into account that these benchmarks are not entirely
+accurate, since they are taken on a regular desktop computer in usual
+conditions.
## Environment
-- Node.js 22.3.0
-- System: Linux 6.10.10
-- CPU: Intel Core i9-13900H
-- Machine: Asus ROG Zephyrus G16
+- Node.js 22.3.1
+- System: macOS Sequoia 15.3.1 / Darwin 24.3.0 arm64 kernel
+- CPU: Apple M2 (8) @ 3.50 GHz
+- Machine: MacBook Air (M2, 2022)
## JSON parsing
@@ -22,40 +25,45 @@ autocannon -b '{"a":1}' -H "Content-Type=application/json" localhost:3002 # or 3
body-parser result:
```
-┌─────────┬──────┬──────┬───────┬──────┬─────────┬─────────┬────────┐
-│ Stat │ 2.5% │ 50% │ 97.5% │ 99% │ Avg │ Stdev │ Max │
-├─────────┼──────┼──────┼───────┼──────┼─────────┼─────────┼────────┤
-│ Latency │ 0 ms │ 0 ms │ 0 ms │ 0 ms │ 0.01 ms │ 0.91 ms │ 272 ms │
-└─────────┴──────┴──────┴───────┴──────┴─────────┴─────────┴────────┘
-┌───────────┬─────────┬─────────┬─────────┬────────┬───────────┬──────────┬─────────┐
-│ Stat │ 1% │ 2.5% │ 50% │ 97.5% │ Avg │ Stdev │ Min │
-├───────────┼─────────┼─────────┼─────────┼────────┼───────────┼──────────┼─────────┤
-│ Req/Sec │ 30,767 │ 30,767 │ 41,343 │ 44,191 │ 39,307.64 │ 4,333.33 │ 30,762 │
-├───────────┼─────────┼─────────┼─────────┼────────┼───────────┼──────────┼─────────┤
-│ Bytes/Sec │ 3.97 MB │ 3.97 MB │ 5.33 MB │ 5.7 MB │ 5.07 MB │ 560 kB │ 3.97 MB │
-└───────────┴─────────┴─────────┴─────────┴────────┴───────────┴──────────┴─────────┘
+┌─────────┬──────┬──────┬───────┬──────┬─────────┬─────────┬───────┐
+│ Stat │ 2.5% │ 50% │ 97.5% │ 99% │ Avg │ Stdev │ Max │
+├─────────┼──────┼──────┼───────┼──────┼─────────┼─────────┼───────┤
+│ Latency │ 0 ms │ 0 ms │ 0 ms │ 0 ms │ 0.01 ms │ 0.12 ms │ 22 ms │
+└─────────┴──────┴──────┴───────┴──────┴─────────┴─────────┴───────┘
+┌───────────┬─────────┬─────────┬─────────┬─────────┬──────────┬──────────┬─────────┐
+│ Stat │ 1% │ 2.5% │ 50% │ 97.5% │ Avg │ Stdev │ Min │
+├───────────┼─────────┼─────────┼─────────┼─────────┼──────────┼──────────┼─────────┤
+│ Req/Sec │ 54,591 │ 54,591 │ 61,759 │ 63,871 │ 61,436.8 │ 2,478.39 │ 54,589 │
+├───────────┼─────────┼─────────┼─────────┼─────────┼──────────┼──────────┼─────────┤
+│ Bytes/Sec │ 7.05 MB │ 7.05 MB │ 7.97 MB │ 8.24 MB │ 7.93 MB │ 319 kB │ 7.04 MB │
+└───────────┴─────────┴─────────┴─────────┴─────────┴──────────┴──────────┴─────────┘
Req/Bytes counts sampled once per second.
-# of samples: 11
+# of samples: 10
-432k requests in 11.03s, 55.8 MB read
+614k requests in 10.01s, 79.3 MB read
```
milliparsec result:
```
-┌─────────┬──────┬──────┬───────┬──────┬─────────┬─────────┬────────┐
-│ Stat │ 2.5% │ 50% │ 97.5% │ 99% │ Avg │ Stdev │ Max │
-├─────────┼──────┼──────┼───────┼──────┼─────────┼─────────┼────────┤
-│ Latency │ 0 ms │ 0 ms │ 0 ms │ 0 ms │ 0.01 ms │ 0.68 ms │ 255 ms │
-└─────────┴──────┴──────┴───────┴──────┴─────────┴─────────┴────────┘
-┌───────────┬─────────┬─────────┬─────────┬─────────┬──────────┬──────────┬─────────┐
-│ Stat │ 1% │ 2.5% │ 50% │ 97.5% │ Avg │ Stdev │ Min │
-├───────────┼─────────┼─────────┼─────────┼─────────┼──────────┼──────────┼─────────┤
-│ Req/Sec │ 46,047 │ 46,047 │ 59,391 │ 64,255 │ 58,285.1 │ 4,625.15 │ 46,025 │
-├───────────┼─────────┼─────────┼─────────┼─────────┼──────────┼──────────┼─────────┤
-│ Bytes/Sec │ 5.62 MB │ 5.62 MB │ 7.25 MB │ 7.84 MB │ 7.11 MB │ 565 kB │ 5.62 MB │
-└───────────┴─────────┴─────────┴─────────┴─────────┴──────────┴──────────┴─────────┘
+┌─────────┬──────┬──────┬───────┬──────┬─────────┬─────────┬───────┐
+│ Stat │ 2.5% │ 50% │ 97.5% │ 99% │ Avg │ Stdev │ Max │
+├─────────┼──────┼──────┼───────┼──────┼─────────┼─────────┼───────┤
+│ Latency │ 0 ms │ 0 ms │ 0 ms │ 0 ms │ 0.01 ms │ 0.04 ms │ 11 ms │
+└─────────┴──────┴──────┴───────┴──────┴─────────┴─────────┴───────┘
+┌───────────┬─────────┬─────────┬─────────┬─────────┬───────────┬──────────┬─────────┐
+│ Stat │ 1% │ 2.5% │ 50% │ 97.5% │ Avg │ Stdev │ Min │
+├───────────┼─────────┼─────────┼─────────┼─────────┼───────────┼──────────┼─────────┤
+│ Req/Sec │ 79,999 │ 79,999 │ 88,127 │ 88,767 │ 87,095.28 │ 2,370.01 │ 79,966 │
+├───────────┼─────────┼─────────┼─────────┼─────────┼───────────┼──────────┼─────────┤
+│ Bytes/Sec │ 9.76 MB │ 9.76 MB │ 10.7 MB │ 10.8 MB │ 10.6 MB │ 289 kB │ 9.76 MB │
+└───────────┴─────────┴─────────┴─────────┴─────────┴───────────┴──────────┴─────────┘
+
+Req/Bytes counts sampled once per second.
+# of samples: 11
+
+958k requests in 11.01s, 117 MB read
Req/Bytes counts sampled once per second.
# of samples: 11
@@ -65,14 +73,14 @@ Req/Bytes counts sampled once per second.
### Verdict
-milliparsec, on average, is ~30-40% faster.
+milliparsec, on average, is ~40% faster.
## Multipart with files
### Benchmark command:
```sh
-autocannon -m POST --form '{ "file": { "type": "file", "path": "./file.txt" } }' localhost:3004
+autocannon -m POST --form '{ "file": { "type": "file", "path": "./file.txt" } }' localhost:3004
```
### Results
@@ -80,47 +88,47 @@ autocannon -m POST --form '{ "file": { "type": "file", "path": "./file.txt" }
formidable result:
```
-┌─────────┬──────┬───────┬───────┬───────┬─────────┬─────────┬────────┐
-│ Stat │ 2.5% │ 50% │ 97.5% │ 99% │ Avg │ Stdev │ Max │
-├─────────┼──────┼───────┼───────┼───────┼─────────┼─────────┼────────┤
-│ Latency │ 1 ms │ 10 ms │ 29 ms │ 33 ms │ 11.1 ms │ 9.48 ms │ 261 ms │
-└─────────┴──────┴───────┴───────┴───────┴─────────┴─────────┴────────┘
-┌───────────┬───────┬───────┬────────┬────────┬────────┬────────┬───────┐
-│ Stat │ 1% │ 2.5% │ 50% │ 97.5% │ Avg │ Stdev │ Min │
-├───────────┼───────┼───────┼────────┼────────┼────────┼────────┼───────┤
-│ Req/Sec │ 500 │ 500 │ 630 │ 2,339 │ 860.9 │ 526.44 │ 500 │
-├───────────┼───────┼───────┼────────┼────────┼────────┼────────┼───────┤
-│ Bytes/Sec │ 99 kB │ 99 kB │ 125 kB │ 463 kB │ 170 kB │ 104 kB │ 99 kB │
-└───────────┴───────┴───────┴────────┴────────┴────────┴────────┴───────┘
+┌─────────┬──────┬──────┬───────┬───────┬─────────┬─────────┬───────┐
+│ Stat │ 2.5% │ 50% │ 97.5% │ 99% │ Avg │ Stdev │ Max │
+├─────────┼──────┼──────┼───────┼───────┼─────────┼─────────┼───────┤
+│ Latency │ 1 ms │ 5 ms │ 19 ms │ 26 ms │ 6.63 ms │ 5.86 ms │ 54 ms │
+└─────────┴──────┴──────┴───────┴───────┴─────────┴─────────┴───────┘
+┌───────────┬────────┬────────┬────────┬────────┬────────┬──────────┬────────┐
+│ Stat │ 1% │ 2.5% │ 50% │ 97.5% │ Avg │ Stdev │ Min │
+├───────────┼────────┼────────┼────────┼────────┼────────┼──────────┼────────┤
+│ Req/Sec │ 530 │ 530 │ 775 │ 4,595 │ 1,404 │ 1,179.32 │ 530 │
+├───────────┼────────┼────────┼────────┼────────┼────────┼──────────┼────────┤
+│ Bytes/Sec │ 105 kB │ 105 kB │ 153 kB │ 910 kB │ 278 kB │ 233 kB │ 105 kB │
+└───────────┴────────┴────────┴────────┴────────┴────────┴──────────┴────────┘
Req/Bytes counts sampled once per second.
# of samples: 10
-9k requests in 10.03s, 1.7 MB read
+14k requests in 10.02s, 2.78 MB read
```
milliparsec result:
```
-┌─────────┬──────┬──────┬───────┬──────┬─────────┬─────────┬────────┐
-│ Stat │ 2.5% │ 50% │ 97.5% │ 99% │ Avg │ Stdev │ Max │
-├─────────┼──────┼──────┼───────┼──────┼─────────┼─────────┼────────┤
-│ Latency │ 0 ms │ 0 ms │ 1 ms │ 1 ms │ 0.09 ms │ 1.39 ms │ 267 ms │
-└─────────┴──────┴──────┴───────┴──────┴─────────┴─────────┴────────┘
+┌─────────┬──────┬──────┬───────┬──────┬─────────┬─────────┬───────┐
+│ Stat │ 2.5% │ 50% │ 97.5% │ 99% │ Avg │ Stdev │ Max │
+├─────────┼──────┼──────┼───────┼──────┼─────────┼─────────┼───────┤
+│ Latency │ 0 ms │ 0 ms │ 0 ms │ 0 ms │ 0.02 ms │ 0.19 ms │ 20 ms │
+└─────────┴──────┴──────┴───────┴──────┴─────────┴─────────┴───────┘
┌───────────┬─────────┬─────────┬─────────┬─────────┬───────────┬──────────┬─────────┐
│ Stat │ 1% │ 2.5% │ 50% │ 97.5% │ Avg │ Stdev │ Min │
├───────────┼─────────┼─────────┼─────────┼─────────┼───────────┼──────────┼─────────┤
-│ Req/Sec │ 8,543 │ 8,543 │ 17,775 │ 18,399 │ 16,962.55 │ 2,697.57 │ 8,537 │
+│ Req/Sec │ 24,063 │ 24,063 │ 29,727 │ 30,863 │ 29,263.28 │ 1,758.94 │ 24,051 │
├───────────┼─────────┼─────────┼─────────┼─────────┼───────────┼──────────┼─────────┤
-│ Bytes/Sec │ 1.69 MB │ 1.69 MB │ 3.52 MB │ 3.64 MB │ 3.36 MB │ 534 kB │ 1.69 MB │
+│ Bytes/Sec │ 4.76 MB │ 4.76 MB │ 5.89 MB │ 6.11 MB │ 5.79 MB │ 348 kB │ 4.76 MB │
└───────────┴─────────┴─────────┴─────────┴─────────┴───────────┴──────────┴─────────┘
Req/Bytes counts sampled once per second.
# of samples: 11
-187k requests in 11.03s, 36.9 MB read
+322k requests in 11.01s, 63.7 MB read
```
### Verdict
-milliparsec, on average, is 10-20x faster.
\ No newline at end of file
+milliparsec, on average, is ~20x faster.
diff --git a/bench/package.json b/bench/package.json
index 654771c..a37a9f1 100644
--- a/bench/package.json
+++ b/bench/package.json
@@ -14,10 +14,10 @@
"devDependencies": {
"@types/body-parser": "^1.19.5",
"@types/formidable": "^3.4.5",
- "autocannon": "^7.15.0",
- "body-parser": "^1.20.2"
+ "autocannon": "^8.0.0",
+ "body-parser": "^1.20.3"
},
"dependencies": {
- "formidable": "^3.5.1"
+ "formidable": "^3.5.2"
}
}
diff --git a/bench/pnpm-lock.yaml b/bench/pnpm-lock.yaml
index 548235e..00b308e 100644
--- a/bench/pnpm-lock.yaml
+++ b/bench/pnpm-lock.yaml
@@ -9,8 +9,8 @@ importers:
.:
dependencies:
formidable:
- specifier: ^3.5.1
- version: 3.5.1
+ specifier: ^3.5.2
+ version: 3.5.2
devDependencies:
'@types/body-parser':
specifier: ^1.19.5
@@ -19,11 +19,11 @@ importers:
specifier: ^3.4.5
version: 3.4.5
autocannon:
- specifier: ^7.15.0
- version: 7.15.0
+ specifier: ^8.0.0
+ version: 8.0.0
body-parser:
- specifier: ^1.20.2
- version: 1.20.2
+ specifier: ^1.20.3
+ version: 1.20.3
packages:
@@ -34,6 +34,9 @@ packages:
resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==}
engines: {node: '>=0.1.90'}
+ '@minimistjs/subarg@1.0.0':
+ resolution: {integrity: sha512-Q/ONBiM2zNeYUy0mVSO44mWWKYM3UHuEK43PKIOzJCbvUnPoMH1K+gk3cf1kgnCVJFlWmddahQQCmrmBGlk9jQ==}
+
'@types/body-parser@1.19.5':
resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==}
@@ -60,15 +63,15 @@ packages:
asynckit@0.4.0:
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
- autocannon@7.15.0:
- resolution: {integrity: sha512-NaP2rQyA+tcubOJMFv2+oeW9jv2pq/t+LM6BL3cfJic0HEfscEcnWgAyU5YovE/oTHUzAgTliGdLPR+RQAWUbg==}
+ autocannon@8.0.0:
+ resolution: {integrity: sha512-fMMcWc2JPFcUaqHeR6+PbmEpTxCrPZyBUM95oG4w3ngJ8NfBNas/ZXA+pTHXLqJ0UlFVTcy05GC25WxKx/M20A==}
hasBin: true
base64-js@1.5.1:
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
- body-parser@1.20.2:
- resolution: {integrity: sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==}
+ body-parser@1.20.3:
+ resolution: {integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==}
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
buffer@5.7.1:
@@ -160,8 +163,8 @@ packages:
resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==}
engines: {node: '>= 6'}
- formidable@3.5.1:
- resolution: {integrity: sha512-WJWKelbRHN41m5dumb0/k8TeAx7Id/y3a+Z7QfhxP/htI9Js5zYaEDtG8uMgG0vM0lOlqnmjE99/kfpOYi/0Og==}
+ formidable@3.5.2:
+ resolution: {integrity: sha512-Jqc1btCy3QzRbJaICGwKcBfGWuLADRerLzDqi2NwSt/UkXLsHJw2TVResiaoBufHVHy9aSgClOHCeJsSsFLTbg==}
function-bind@1.1.2:
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
@@ -202,8 +205,8 @@ packages:
hdr-histogram-percentiles-obj@3.0.0:
resolution: {integrity: sha512-7kIufnBqdsBGcSZLPJwqHT3yhk1QTsSlFsVD3kx5ixH/AlgBs9yM1q6DPhXZ8f8gtdqgh7N7/5btRLpQsS2gHw==}
- hexoid@1.0.0:
- resolution: {integrity: sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==}
+ hexoid@2.0.0:
+ resolution: {integrity: sha512-qlspKUK7IlSQv2o+5I7yhUd7TxlOG2Vr5LTa3ve2XSNVKAL/n/u/7KLvKmFNimomDIKvZFXWHv0T12mv7rT8Aw==}
engines: {node: '>=8'}
http-errors@2.0.0:
@@ -286,8 +289,8 @@ packages:
resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==}
engines: {node: '>=0.4.0'}
- qs@6.11.0:
- resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==}
+ qs@6.13.0:
+ resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==}
engines: {node: '>=0.6'}
raw-body@2.5.2:
@@ -331,9 +334,6 @@ packages:
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
engines: {node: '>=8'}
- subarg@1.0.0:
- resolution: {integrity: sha512-RIrIdRY0X1xojthNcVtgT9sjpOGagEUKpZdgBUi054OEPFo282yg+zE+t1Rj3+RqKq2xStL7uUHhY+AjbC4BXg==}
-
supports-color@7.2.0:
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
engines: {node: '>=8'}
@@ -374,6 +374,10 @@ snapshots:
'@colors/colors@1.5.0':
optional: true
+ '@minimistjs/subarg@1.0.0':
+ dependencies:
+ minimist: 1.2.8
+
'@types/body-parser@1.19.5':
dependencies:
'@types/connect': 3.4.38
@@ -401,8 +405,9 @@ snapshots:
asynckit@0.4.0: {}
- autocannon@7.15.0:
+ autocannon@8.0.0:
dependencies:
+ '@minimistjs/subarg': 1.0.0
chalk: 4.1.2
char-spinner: 1.0.1
cli-table3: 0.6.5
@@ -424,12 +429,11 @@ snapshots:
reinterval: 1.1.0
retimer: 3.0.0
semver: 7.6.2
- subarg: 1.0.0
timestring: 6.0.0
base64-js@1.5.1: {}
- body-parser@1.20.2:
+ body-parser@1.20.3:
dependencies:
bytes: 3.1.2
content-type: 1.0.5
@@ -439,7 +443,7 @@ snapshots:
http-errors: 2.0.0
iconv-lite: 0.4.24
on-finished: 2.4.1
- qs: 6.11.0
+ qs: 6.13.0
raw-body: 2.5.2
type-is: 1.6.18
unpipe: 1.0.0
@@ -527,10 +531,10 @@ snapshots:
combined-stream: 1.0.8
mime-types: 2.1.35
- formidable@3.5.1:
+ formidable@3.5.2:
dependencies:
dezalgo: 1.0.4
- hexoid: 1.0.0
+ hexoid: 2.0.0
once: 1.4.0
function-bind@1.1.2: {}
@@ -571,7 +575,7 @@ snapshots:
hdr-histogram-percentiles-obj@3.0.0: {}
- hexoid@1.0.0: {}
+ hexoid@2.0.0: {}
http-errors@2.0.0:
dependencies:
@@ -637,7 +641,7 @@ snapshots:
progress@2.0.3: {}
- qs@6.11.0:
+ qs@6.13.0:
dependencies:
side-channel: 1.0.6
@@ -686,10 +690,6 @@ snapshots:
dependencies:
ansi-regex: 5.0.1
- subarg@1.0.0:
- dependencies:
- minimist: 1.2.8
-
supports-color@7.2.0:
dependencies:
has-flag: 4.0.0
diff --git a/package.json b/package.json
index 9362ebb..bdf603c 100644
--- a/package.json
+++ b/package.json
@@ -17,13 +17,13 @@
"body-parsing"
],
"engines": {
- "node": ">=20"
+ "node": ">=18.13 || >=19.20 || >=20"
},
"exports": "./dist/index.js",
"devDependencies": {
"@biomejs/biome": "1.9.3",
"@tinyhttp/app": "^2.4.0",
- "@types/node": "^22.7.4",
+ "@types/node": "^18.19.76",
"c8": "10.1.2",
"supertest-fetch": "^2.0.0",
"tsx": "^4.19.1",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index fcfa059..d35bcc5 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -15,8 +15,8 @@ importers:
specifier: ^2.4.0
version: 2.4.0
'@types/node':
- specifier: ^22.7.4
- version: 22.7.4
+ specifier: ^18.19.76
+ version: 18.19.76
c8:
specifier: 10.1.2
version: 10.1.2
@@ -325,8 +325,8 @@ packages:
'@types/istanbul-lib-coverage@2.0.6':
resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==}
- '@types/node@22.7.4':
- resolution: {integrity: sha512-y+NPi1rFzDs1NdQHHToqeiX2TIS79SWEAw9GYhkkx8bD0ChpfqC+n2j5OXOCpzfojBEBt6DnEnnG9MY0zk1XLg==}
+ '@types/node@18.19.76':
+ resolution: {integrity: sha512-yvR7Q9LdPz2vGpmpJX5LolrgRdWvB67MJKDPSgIIzpFbaf9a1j/f5DnLp5VDyHGMR0QZHlTr1afsD87QCXFHKw==}
ansi-regex@5.0.1:
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
@@ -578,8 +578,8 @@ packages:
engines: {node: '>=14.17'}
hasBin: true
- undici-types@6.19.8:
- resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==}
+ undici-types@5.26.5:
+ resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
v8-to-istanbul@9.3.0:
resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==}
@@ -820,9 +820,9 @@ snapshots:
'@types/istanbul-lib-coverage@2.0.6': {}
- '@types/node@22.7.4':
+ '@types/node@18.19.76':
dependencies:
- undici-types: 6.19.8
+ undici-types: 5.26.5
ansi-regex@5.0.1: {}
@@ -1066,7 +1066,7 @@ snapshots:
typescript@5.6.2: {}
- undici-types@6.19.8: {}
+ undici-types@5.26.5: {}
v8-to-istanbul@9.3.0:
dependencies:
diff --git a/src/index.ts b/src/index.ts
index f633e7e..5dd51e4 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,4 +1,4 @@
-import { Buffer } from 'node:buffer'
+import { Buffer, File } from 'node:buffer'
import type { IncomingMessage, ServerResponse as Response } from 'node:http'
type NextFunction = (err?: any) => void
diff --git a/test.ts b/test.ts
index ac4d401..179314a 100644
--- a/test.ts
+++ b/test.ts
@@ -1,5 +1,6 @@
import assert from 'node:assert/strict'
import { Buffer } from 'node:buffer'
+import { File } from 'node:buffer'
import { createServer } from 'node:http'
import { describe, it } from 'node:test'
import { App } from '@tinyhttp/app'
@@ -353,7 +354,7 @@ describe('Multipart', () => {
it('should parse multipart with files', async () => {
const fd = new FormData()
const file = new File(['hello world'], 'hello.txt', { type: 'text/plain' })
- fd.set('file', file)
+ fd.set('file', file as Blob)
const server = createServer(async (req: ReqWithBody<{ file: [File] }>, res) => {
await multipart()(req, res, (err) => err && console.log(err))
@@ -380,8 +381,8 @@ describe('Multipart', () => {
new File(['bye world'], 'bye.txt', { type: 'text/plain' })
]
- fd.set('file1', files[0])
- fd.set('file2', files[1])
+ fd.set('file1', files[0] as Blob)
+ fd.set('file2', files[1] as Blob)
const server = createServer(async (req: ReqWithBody<{ file1: [File]; file2: [File] }>, res) => {
await multipart()(req, res, (err) => err && console.log(err))
@@ -405,7 +406,7 @@ describe('Multipart', () => {
it('should support binary files', async () => {
const fd = new FormData()
const file = new File([new Uint8Array([1, 2, 3])], 'blob.bin', { type: 'application/octet-stream' })
- fd.set('file', file)
+ fd.set('file', file as Blob)
const server = createServer(async (req: ReqWithBody<{ file: [File] }>, res) => {
await multipart()(req, res, (err) => err && console.log(err))
@@ -495,8 +496,8 @@ describe('Limits', () => {
const fd = new FormData()
- fd.set('file1', new File(['hello world'], 'hello.txt', { type: 'text/plain' }))
- fd.set('file2', new File(['bye world'], 'bye.txt', { type: 'text/plain' }))
+ fd.set('file1', new File(['hello world'], 'hello.txt', { type: 'text/plain' }) as Blob)
+ fd.set('file2', new File(['bye world'], 'bye.txt', { type: 'text/plain' }) as Blob)
await makeFetch(server)('/', {
body: fd,
@@ -514,7 +515,7 @@ describe('Limits', () => {
const fd = new FormData()
- fd.set('file', new File(['hello world'], 'hello.txt', { type: 'text/plain' }))
+ fd.set('file', new File(['hello world'], 'hello.txt', { type: 'text/plain' }) as Blob)
await makeFetch(server)('/', {
body: fd,
@@ -534,7 +535,7 @@ describe('Limits', () => {
const fd = new FormData()
- fd.set('file', new File(['hello world to everyone'], 'hello.txt', { type: 'text/plain' }))
+ fd.set('file', new File(['hello world to everyone'], 'hello.txt', { type: 'text/plain' }) as Blob)
await makeFetch(server)('/', {
body: fd,