milliparsec 5.0.2 → 5.1.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/dist/index.d.ts +11 -27
- package/dist/index.js +17 -17
- package/dist/types.d.ts +24 -0
- package/dist/types.js +1 -0
- package/dist/utils.d.ts +4 -0
- package/dist/utils.js +2 -0
- package/package.json +9 -8
package/dist/index.d.ts
CHANGED
|
@@ -1,52 +1,36 @@
|
|
|
1
1
|
import { Buffer } from 'node:buffer';
|
|
2
|
-
import type {
|
|
3
|
-
type NextFunction
|
|
4
|
-
|
|
5
|
-
* Request extension with a body
|
|
6
|
-
*/
|
|
7
|
-
export type ReqWithBody<T = any> = IncomingMessage & {
|
|
8
|
-
body?: T;
|
|
9
|
-
};
|
|
10
|
-
export declare const hasBody: (method: string) => boolean;
|
|
11
|
-
export type LimitErrorFn = (limit: number) => Error;
|
|
12
|
-
export type ParserOptions = Partial<{
|
|
13
|
-
/**
|
|
14
|
-
* Limit payload size (in bytes)
|
|
15
|
-
* @default '100KB'
|
|
16
|
-
*/
|
|
17
|
-
payloadLimit: number;
|
|
18
|
-
/**
|
|
19
|
-
* Custom error function for payload limit
|
|
20
|
-
*/
|
|
21
|
-
payloadLimitErrorFn: LimitErrorFn;
|
|
22
|
-
}>;
|
|
2
|
+
import type { ServerResponse as Response } from 'node:http';
|
|
3
|
+
import type { LimitErrorFn, NextFunction, ParserOptions, ReqWithBody } from './types.js';
|
|
4
|
+
export * from './types.js';
|
|
23
5
|
export declare const p: <T = any>(fn: (body: Buffer) => void, payloadLimit?: number, payloadLimitErrorFn?: LimitErrorFn) => (req: ReqWithBody<T>, _res: Response, next?: (err?: any) => void) => Promise<void>;
|
|
24
6
|
/**
|
|
25
7
|
* Parse payload with a custom function
|
|
26
8
|
* @param fn
|
|
27
9
|
*/
|
|
28
|
-
declare const custom: <T = any>(fn: (body: Buffer) => any) => (req: ReqWithBody, _res: Response, next?: NextFunction) => Promise<void>;
|
|
10
|
+
declare const custom: <T = any>(fn: (body: Buffer) => any, type?: ParserOptions["type"]) => (req: ReqWithBody, _res: Response, next?: NextFunction) => Promise<void>;
|
|
29
11
|
/**
|
|
30
12
|
* Parse JSON payload
|
|
31
13
|
* @param options
|
|
32
14
|
*/
|
|
33
|
-
declare const json: ({ payloadLimit, payloadLimitErrorFn
|
|
15
|
+
declare const json: ({ payloadLimit, payloadLimitErrorFn, type, reviver }?: ParserOptions<{
|
|
16
|
+
reviver?: (this: any, key: string, value: any) => any;
|
|
17
|
+
}>) => (req: ReqWithBody, res: Response, next?: NextFunction) => Promise<void>;
|
|
34
18
|
/**
|
|
35
19
|
* Parse raw payload
|
|
36
20
|
* @param options
|
|
37
21
|
*/
|
|
38
|
-
declare const raw: ({ payloadLimit, payloadLimitErrorFn }?: ParserOptions) => (req: ReqWithBody, _res: Response, next?: NextFunction) => Promise<void>;
|
|
22
|
+
declare const raw: ({ payloadLimit, payloadLimitErrorFn, type }?: ParserOptions) => (req: ReqWithBody, _res: Response, next?: NextFunction) => Promise<void>;
|
|
39
23
|
/**
|
|
40
24
|
* Stringify request payload
|
|
41
25
|
* @param param0
|
|
42
26
|
* @returns
|
|
43
27
|
*/
|
|
44
|
-
declare const text: ({ payloadLimit, payloadLimitErrorFn }?: ParserOptions) => (req: ReqWithBody, _res: Response, next?: NextFunction) => Promise<void>;
|
|
28
|
+
declare const text: ({ payloadLimit, payloadLimitErrorFn, type }?: ParserOptions) => (req: ReqWithBody, _res: Response, next?: NextFunction) => Promise<void>;
|
|
45
29
|
/**
|
|
46
30
|
* Parse urlencoded payload
|
|
47
31
|
* @param options
|
|
48
32
|
*/
|
|
49
|
-
declare const urlencoded: ({ payloadLimit, payloadLimitErrorFn }?: ParserOptions) => (req: ReqWithBody, _res: Response, next?: NextFunction) => Promise<void>;
|
|
33
|
+
declare const urlencoded: ({ payloadLimit, payloadLimitErrorFn, type }?: ParserOptions) => (req: ReqWithBody, _res: Response, next?: NextFunction) => Promise<void>;
|
|
50
34
|
type MultipartOptions = Partial<{
|
|
51
35
|
/**
|
|
52
36
|
* Limit number of files
|
|
@@ -67,5 +51,5 @@ type MultipartOptions = Partial<{
|
|
|
67
51
|
* Does not restrict total payload size by default.
|
|
68
52
|
* @param options
|
|
69
53
|
*/
|
|
70
|
-
declare const multipart: ({ payloadLimit, payloadLimitErrorFn, ...opts }?: MultipartOptions & ParserOptions) => (req: ReqWithBody, res: Response, next?: NextFunction) => Promise<void>;
|
|
54
|
+
declare const multipart: ({ payloadLimit, payloadLimitErrorFn, type, ...opts }?: MultipartOptions & ParserOptions) => (req: ReqWithBody, res: Response, next?: NextFunction) => Promise<void>;
|
|
71
55
|
export { custom, json, raw, text, urlencoded, multipart };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Buffer, File } from 'node:buffer';
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
import { checkType, hasBody } from './utils.js';
|
|
3
|
+
export * from './types.js';
|
|
4
|
+
const defaultPayloadLimit = 102400; // 100KiB
|
|
4
5
|
const defaultErrorFn = (payloadLimit) => new Error(`Payload too large. Limit: ${payloadLimit} bytes`);
|
|
5
6
|
// Main function
|
|
6
7
|
export const p = (fn, payloadLimit = defaultPayloadLimit, payloadLimitErrorFn = defaultErrorFn) => async (req, _res, next) => {
|
|
@@ -22,8 +23,8 @@ export const p = (fn, payloadLimit = defaultPayloadLimit, payloadLimitErrorFn =
|
|
|
22
23
|
* Parse payload with a custom function
|
|
23
24
|
* @param fn
|
|
24
25
|
*/
|
|
25
|
-
const custom = (fn) => async (req, _res, next) => {
|
|
26
|
-
if (hasBody(req.method))
|
|
26
|
+
const custom = (fn, type) => async (req, _res, next) => {
|
|
27
|
+
if (hasBody(req.method) && checkType(req, type))
|
|
27
28
|
req.body = await p(fn)(req, _res, next);
|
|
28
29
|
next === null || next === void 0 ? void 0 : next();
|
|
29
30
|
};
|
|
@@ -31,11 +32,11 @@ const custom = (fn) => async (req, _res, next) => {
|
|
|
31
32
|
* Parse JSON payload
|
|
32
33
|
* @param options
|
|
33
34
|
*/
|
|
34
|
-
const json = ({ payloadLimit, payloadLimitErrorFn } = {}) => async (req, res, next) => {
|
|
35
|
-
if (hasBody(req.method)) {
|
|
35
|
+
const json = ({ payloadLimit, payloadLimitErrorFn, type, reviver } = {}) => async (req, res, next) => {
|
|
36
|
+
if (hasBody(req.method) && checkType(req, type)) {
|
|
36
37
|
req.body = await p((x) => {
|
|
37
38
|
const str = td.decode(x);
|
|
38
|
-
return str ? JSON.parse(str) : {};
|
|
39
|
+
return str ? JSON.parse(str, reviver) : {};
|
|
39
40
|
}, payloadLimit, payloadLimitErrorFn)(req, res, next);
|
|
40
41
|
}
|
|
41
42
|
next === null || next === void 0 ? void 0 : next();
|
|
@@ -44,8 +45,8 @@ const json = ({ payloadLimit, payloadLimitErrorFn } = {}) => async (req, res, ne
|
|
|
44
45
|
* Parse raw payload
|
|
45
46
|
* @param options
|
|
46
47
|
*/
|
|
47
|
-
const raw = ({ payloadLimit, payloadLimitErrorFn } = {}) => async (req, _res, next) => {
|
|
48
|
-
if (hasBody(req.method)) {
|
|
48
|
+
const raw = ({ payloadLimit, payloadLimitErrorFn, type } = {}) => async (req, _res, next) => {
|
|
49
|
+
if (hasBody(req.method) && checkType(req, type)) {
|
|
49
50
|
req.body = await p((x) => x, payloadLimit, payloadLimitErrorFn)(req, _res, next);
|
|
50
51
|
}
|
|
51
52
|
next === null || next === void 0 ? void 0 : next();
|
|
@@ -56,8 +57,8 @@ const td = new TextDecoder();
|
|
|
56
57
|
* @param param0
|
|
57
58
|
* @returns
|
|
58
59
|
*/
|
|
59
|
-
const text = ({ payloadLimit, payloadLimitErrorFn } = {}) => async (req, _res, next) => {
|
|
60
|
-
if (hasBody(req.method)) {
|
|
60
|
+
const text = ({ payloadLimit, payloadLimitErrorFn, type } = {}) => async (req, _res, next) => {
|
|
61
|
+
if (hasBody(req.method) && checkType(req, type)) {
|
|
61
62
|
req.body = await p((x) => td.decode(x), payloadLimit, payloadLimitErrorFn)(req, _res, next);
|
|
62
63
|
}
|
|
63
64
|
next === null || next === void 0 ? void 0 : next();
|
|
@@ -66,8 +67,8 @@ const text = ({ payloadLimit, payloadLimitErrorFn } = {}) => async (req, _res, n
|
|
|
66
67
|
* Parse urlencoded payload
|
|
67
68
|
* @param options
|
|
68
69
|
*/
|
|
69
|
-
const urlencoded = ({ payloadLimit, payloadLimitErrorFn } = {}) => async (req, _res, next) => {
|
|
70
|
-
if (hasBody(req.method)) {
|
|
70
|
+
const urlencoded = ({ payloadLimit, payloadLimitErrorFn, type } = {}) => async (req, _res, next) => {
|
|
71
|
+
if (hasBody(req.method) && checkType(req, type)) {
|
|
71
72
|
req.body = await p((x) => Object.fromEntries(new URLSearchParams(x.toString()).entries()), payloadLimit, payloadLimitErrorFn)(req, _res, next);
|
|
72
73
|
}
|
|
73
74
|
next === null || next === void 0 ? void 0 : next();
|
|
@@ -77,13 +78,12 @@ const getBoundary = (contentType) => {
|
|
|
77
78
|
return match ? `--${match[1]}` : null;
|
|
78
79
|
};
|
|
79
80
|
const defaultFileSizeLimitErrorFn = (limit) => new Error(`File too large. Limit: ${limit} bytes`);
|
|
80
|
-
const defaultFileSizeLimit = 200 * 1024 * 1024;
|
|
81
|
+
const defaultFileSizeLimit = 200 * 1024 * 1024; // 200MiB
|
|
81
82
|
const parseMultipart = (body, boundary, { fileCountLimit, fileSizeLimit = defaultFileSizeLimit, fileSizeLimitErrorFn = defaultFileSizeLimitErrorFn }) => {
|
|
82
83
|
const parts = body.split(new RegExp(`${boundary}(--)?`)).filter((part) => !!part && /content-disposition/i.test(part));
|
|
83
84
|
const parsedBody = {};
|
|
84
85
|
if (fileCountLimit && parts.length > fileCountLimit)
|
|
85
86
|
throw new Error(`Too many files. Limit: ${fileCountLimit}`);
|
|
86
|
-
// biome-ignore lint/complexity/noForEach: for...of fails
|
|
87
87
|
parts.forEach((part) => {
|
|
88
88
|
const [headers, ...lines] = part.split('\r\n').filter((part) => !!part);
|
|
89
89
|
const data = lines.join('\r\n').trim();
|
|
@@ -110,8 +110,8 @@ const parseMultipart = (body, boundary, { fileCountLimit, fileSizeLimit = defaul
|
|
|
110
110
|
* Does not restrict total payload size by default.
|
|
111
111
|
* @param options
|
|
112
112
|
*/
|
|
113
|
-
const multipart = ({ payloadLimit = Number.POSITIVE_INFINITY, payloadLimitErrorFn, ...opts } = {}) => async (req, res, next) => {
|
|
114
|
-
if (hasBody(req.method)) {
|
|
113
|
+
const multipart = ({ payloadLimit = Number.POSITIVE_INFINITY, payloadLimitErrorFn, type, ...opts } = {}) => async (req, res, next) => {
|
|
114
|
+
if (hasBody(req.method) && checkType(req, type)) {
|
|
115
115
|
req.body = await p((x) => {
|
|
116
116
|
const boundary = getBoundary(req.headers['content-type']);
|
|
117
117
|
if (boundary)
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { IncomingMessage } from 'node:http';
|
|
2
|
+
/**
|
|
3
|
+
* Request extension with a body
|
|
4
|
+
*/
|
|
5
|
+
export type ReqWithBody<T = any> = IncomingMessage & {
|
|
6
|
+
body?: T;
|
|
7
|
+
};
|
|
8
|
+
export type LimitErrorFn = (limit: number) => Error;
|
|
9
|
+
export type ParserOptions<T extends Record<string, any> = Record<string, any>> = Partial<{
|
|
10
|
+
/**
|
|
11
|
+
* Limit payload size (in bytes)
|
|
12
|
+
* @default 102400
|
|
13
|
+
*/
|
|
14
|
+
payloadLimit: number;
|
|
15
|
+
/**
|
|
16
|
+
* Custom error function for payload limit
|
|
17
|
+
*/
|
|
18
|
+
payloadLimitErrorFn: LimitErrorFn;
|
|
19
|
+
/**
|
|
20
|
+
* Middleware content type
|
|
21
|
+
*/
|
|
22
|
+
type: (req: IncomingMessage) => boolean;
|
|
23
|
+
}> & T;
|
|
24
|
+
export type NextFunction = (err?: any) => void;
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/utils.d.ts
ADDED
package/dist/utils.js
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "milliparsec",
|
|
3
|
-
"version": "5.0
|
|
3
|
+
"version": "5.1.0",
|
|
4
4
|
"description": "tiniest body parser in the universe",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -21,10 +21,12 @@
|
|
|
21
21
|
},
|
|
22
22
|
"exports": "./dist/index.js",
|
|
23
23
|
"devDependencies": {
|
|
24
|
-
"@biomejs/biome": "
|
|
24
|
+
"@biomejs/biome": "2.2.2",
|
|
25
25
|
"@tinyhttp/app": "^2.4.0",
|
|
26
|
-
"@types/
|
|
26
|
+
"@types/express": "^5.0.3",
|
|
27
|
+
"@types/node": "^18",
|
|
27
28
|
"c8": "10.1.2",
|
|
29
|
+
"express": "^5.1.0",
|
|
28
30
|
"supertest-fetch": "^2.0.0",
|
|
29
31
|
"tsx": "^4.19.1",
|
|
30
32
|
"typescript": "^5.6.2"
|
|
@@ -32,14 +34,13 @@
|
|
|
32
34
|
"files": [
|
|
33
35
|
"dist"
|
|
34
36
|
],
|
|
35
|
-
"publishConfig": {
|
|
36
|
-
"provenance": true
|
|
37
|
-
},
|
|
38
37
|
"scripts": {
|
|
39
38
|
"test": "tsx --test test.ts",
|
|
40
39
|
"test:coverage": "c8 --include=src pnpm test",
|
|
41
40
|
"test:report": "c8 report --reporter=text-lcov > coverage.lcov",
|
|
42
41
|
"build": "tsc -p tsconfig.build.json",
|
|
42
|
+
"prepublishOnly": "pnpm build && pnpm test",
|
|
43
43
|
"check": "biome check --write"
|
|
44
|
-
}
|
|
45
|
-
|
|
44
|
+
},
|
|
45
|
+
"packageManager": "pnpm@10.11.0"
|
|
46
|
+
}
|