milliparsec 3.0.0 → 4.0.0
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/README.md +15 -8
- package/dist/index.d.ts +2 -1
- package/dist/index.js +37 -4
- package/package.json +10 -5
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@ Check out [deno-libs/parsec](https://github.com/deno-libs/parsec) for Deno port.
|
|
|
17
17
|
|
|
18
18
|
- ⏩ built with `async` / `await`
|
|
19
19
|
- 🛠 JSON / raw / urlencoded data support
|
|
20
|
-
- 📦 tiny package size (
|
|
20
|
+
- 📦 tiny package size (8KB dist size)
|
|
21
21
|
- 🔥 no dependencies
|
|
22
22
|
- ✨ [tinyhttp](https://github.com/tinyhttp/tinyhttp) and Express support
|
|
23
23
|
- ⚡ 30% faster than body-parser
|
|
@@ -28,11 +28,8 @@ Check out [deno-libs/parsec](https://github.com/deno-libs/parsec) for Deno port.
|
|
|
28
28
|
# pnpm
|
|
29
29
|
pnpm i milliparsec
|
|
30
30
|
|
|
31
|
-
#
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
# npm
|
|
35
|
-
npm i milliparsec
|
|
31
|
+
# bun
|
|
32
|
+
bun i milliparsec
|
|
36
33
|
```
|
|
37
34
|
|
|
38
35
|
## Usage
|
|
@@ -42,7 +39,7 @@ npm i milliparsec
|
|
|
42
39
|
Use a middleware inside a server:
|
|
43
40
|
|
|
44
41
|
```js
|
|
45
|
-
import { createServer } from 'http'
|
|
42
|
+
import { createServer } from 'node:http'
|
|
46
43
|
import { json } from 'milliparsec'
|
|
47
44
|
|
|
48
45
|
const server = createServer(async (req: ReqWithBody, res) => {
|
|
@@ -86,12 +83,22 @@ Parses request body using `new URLSearchParams`.
|
|
|
86
83
|
|
|
87
84
|
Parses request body using `JSON.parse`.
|
|
88
85
|
|
|
86
|
+
### `multipart(req, res, cb)`
|
|
87
|
+
|
|
88
|
+
Parses request body using `multipart/form-data` content type and boundary. Supports files as well.
|
|
89
|
+
|
|
90
|
+
```js
|
|
91
|
+
// curl -F "textfield=textfield" -F "someother=textfield with text" localhost:3000
|
|
92
|
+
await multipart()(req, res, (err) => void err && console.log(err))
|
|
93
|
+
res.end(req.body) // { textfield: "textfield", someother: "textfield with text" }
|
|
94
|
+
```
|
|
95
|
+
|
|
89
96
|
### `custom(fn)(req, res, cb)`
|
|
90
97
|
|
|
91
98
|
Custom function for `parsec`.
|
|
92
99
|
|
|
93
100
|
```js
|
|
94
|
-
// curl -d "this text must be uppercased" localhost
|
|
101
|
+
// curl -d "this text must be uppercased" localhost:3000
|
|
95
102
|
await custom(
|
|
96
103
|
req,
|
|
97
104
|
(d) => d.toUpperCase(),
|
package/dist/index.d.ts
CHANGED
|
@@ -11,4 +11,5 @@ declare const json: () => (req: ReqWithBody, res: Response, next: NextFunction)
|
|
|
11
11
|
declare const raw: () => (req: ReqWithBody, _res: Response, next: NextFunction) => Promise<void>;
|
|
12
12
|
declare const text: () => (req: ReqWithBody, _res: Response, next: NextFunction) => Promise<void>;
|
|
13
13
|
declare const urlencoded: () => (req: ReqWithBody, res: Response, next: NextFunction) => Promise<void>;
|
|
14
|
-
|
|
14
|
+
declare const multipart: () => (req: ReqWithBody, res: Response, next: NextFunction) => Promise<void>;
|
|
15
|
+
export { custom, json, raw, text, urlencoded, multipart };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
export const hasBody = (method) => ['POST', 'PUT', 'PATCH', 'DELETE'].includes(method);
|
|
2
|
-
// Main function
|
|
3
2
|
export const p = (fn) => async (req, _res, next) => {
|
|
4
3
|
try {
|
|
5
4
|
let body = '';
|
|
@@ -11,9 +10,8 @@ export const p = (fn) => async (req, _res, next) => {
|
|
|
11
10
|
next(e);
|
|
12
11
|
}
|
|
13
12
|
};
|
|
14
|
-
// JSON, raw, FormData
|
|
15
13
|
const custom = (fn) => async (req, _res, next) => {
|
|
16
|
-
req.body = await p(fn)(req,
|
|
14
|
+
req.body = await p(fn)(req, _res, next);
|
|
17
15
|
next();
|
|
18
16
|
};
|
|
19
17
|
const json = () => async (req, res, next) => {
|
|
@@ -51,4 +49,39 @@ const urlencoded = () => async (req, res, next) => {
|
|
|
51
49
|
else
|
|
52
50
|
next();
|
|
53
51
|
};
|
|
54
|
-
|
|
52
|
+
const getBoundary = (contentType) => {
|
|
53
|
+
const match = /boundary=(.+);?/.exec(contentType);
|
|
54
|
+
return match ? `--${match[1]}` : null;
|
|
55
|
+
};
|
|
56
|
+
const parseMultipart = (body, boundary) => {
|
|
57
|
+
const parts = body.split(new RegExp(`${boundary}(--)?`)).filter((part) => !!part && /content-disposition/i.test(part));
|
|
58
|
+
const parsedBody = {};
|
|
59
|
+
parts.map((part) => {
|
|
60
|
+
const [headers, ...lines] = part.split('\r\n').filter((part) => !!part);
|
|
61
|
+
const data = lines.join('\r\n').trim();
|
|
62
|
+
const name = /name="(.+?)"/.exec(headers)[1];
|
|
63
|
+
const filename = /filename="(.+?)"/.exec(headers);
|
|
64
|
+
if (filename) {
|
|
65
|
+
const contentTypeMatch = /Content-Type: (.+)/i.exec(data);
|
|
66
|
+
const fileContent = data.slice(contentTypeMatch[0].length + 2);
|
|
67
|
+
return Object.assign(parsedBody, {
|
|
68
|
+
[name]: new File([fileContent], filename[1], { type: contentTypeMatch[1] })
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
return Object.assign(parsedBody, { [name]: data });
|
|
72
|
+
});
|
|
73
|
+
return parsedBody;
|
|
74
|
+
};
|
|
75
|
+
const multipart = () => async (req, res, next) => {
|
|
76
|
+
if (hasBody(req.method)) {
|
|
77
|
+
req.body = await p((x) => {
|
|
78
|
+
const boundary = getBoundary(req.headers['content-type']);
|
|
79
|
+
if (boundary)
|
|
80
|
+
return parseMultipart(x, boundary);
|
|
81
|
+
})(req, res, next);
|
|
82
|
+
next();
|
|
83
|
+
}
|
|
84
|
+
else
|
|
85
|
+
next();
|
|
86
|
+
};
|
|
87
|
+
export { custom, json, raw, text, urlencoded, multipart };
|
package/package.json
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "milliparsec",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"description": "tiniest body parser in the universe",
|
|
5
|
-
"repository":
|
|
6
|
-
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/tinyhttp/milliparsec"
|
|
8
|
+
},
|
|
9
|
+
"author": "talentlessguy <hi@v1rtl.site>",
|
|
7
10
|
"license": "MIT",
|
|
8
11
|
"types": "./dist/index.d.ts",
|
|
9
12
|
"type": "module",
|
|
@@ -14,12 +17,11 @@
|
|
|
14
17
|
"body-parsing"
|
|
15
18
|
],
|
|
16
19
|
"engines": {
|
|
17
|
-
"node": ">=
|
|
20
|
+
"node": ">=20"
|
|
18
21
|
},
|
|
19
22
|
"exports": "./dist/index.js",
|
|
20
23
|
"devDependencies": {
|
|
21
24
|
"@biomejs/biome": "1.8.3",
|
|
22
|
-
"@tinyhttp/app": "^2.2.4",
|
|
23
25
|
"@types/node": "^20.14.9",
|
|
24
26
|
"c8": "10.1.2",
|
|
25
27
|
"supertest-fetch": "^2.0.0",
|
|
@@ -30,6 +32,9 @@
|
|
|
30
32
|
"files": [
|
|
31
33
|
"dist"
|
|
32
34
|
],
|
|
35
|
+
"publishConfig": {
|
|
36
|
+
"provenance": true
|
|
37
|
+
},
|
|
33
38
|
"scripts": {
|
|
34
39
|
"test": "uvu -r tsm",
|
|
35
40
|
"test:coverage": "c8 --include=src pnpm test",
|