diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index e45ad66..0000000 --- a/.eslintrc.js +++ /dev/null @@ -1,26 +0,0 @@ -module.exports = { - ignorePatterns: [ - 'bench', - 'deps/encoding' - ], - extends: [ - 'standard', - 'eslint:recommended', - 'plugin:n/recommended' - ], - rules: { - 'no-unused-vars': [1, { vars: 'all', args: 'none' }], - 'n/no-missing-require': 1, - 'no-constant-condition': 'off', - 'no-var': 'off', - 'no-redeclare': 1, - 'no-fallthrough': 1, - 'no-control-regex': 1, - 'no-empty': 'off', - 'prefer-const': 'off' - }, - env: { - node: true, - es6: true - } -} diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 6d10297..0000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,28 +0,0 @@ -# Changelog - -Major changes since the last busboy release (0.3.1): - -# 1.1.0 - 09 June, 2022 - -* Fix potential ReDOS-Attack-Vector in Headerparser (#72) -* Improve array parse performances (#69) -* Export Dicer library (#90) - -# 1.0.0 - 04 December, 2021 - -* Prevent malformed headers from crashing the web server (#34) -* Prevent empty parts from hanging the process (#55) -* Use non-deprecated Buffer creation (#8, #10) -* Include TypeScript types in the package itself (#13) -* Make `busboy` importable both as ESM and as CJS module (#61) -* Improve performance (#21, #32, #36) -* Set `autoDestroy` to `false` by default in order to avoid regressions when upgrading from Node.js 12 to Node.js 14 (#9) -* Add option `isPartAFile`, to make the file-detection configurable (#53) -* Add property `bytesRead` on FileStreams (#51) -* Add and expose headerSize limit (#64) -* Throw an error on non-number limit (#7) -* Use the native TextDecoder and the package `text-decoding` for fallback if Node.js does not support the requested encoding (#50) -* Integrate `dicer` dependency into `busboy` itself (#14) -* Convert tests to Mocha (#11, #12, #22, #23) -* Implement better benchmarks (#40, #54) -* Use JavaScript Standard style (#44, #45) diff --git a/README.md b/README.md index c648568..13c4980 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,9 @@ # busboy -
- [![Build Status](https://github.com/fastify/busboy/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/fastify/busboy/actions) -[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](https://standardjs.com/) -[![Security Responsible Disclosure](https://img.shields.io/badge/Security-Responsible%20Disclosure-yellow.svg)](https://github.com/fastify/.github/blob/main/SECURITY.md) - -
- -
- [![NPM version](https://img.shields.io/npm/v/@fastify/busboy.svg?style=flat)](https://www.npmjs.com/package/@fastify/busboy) -[![NPM downloads](https://img.shields.io/npm/dm/@fastify/busboy.svg?style=flat)](https://www.npmjs.com/package/@fastify/busboy) - -
+[![neostandard javascript style](https://img.shields.io/badge/code_style-neostandard-brightgreen?style=flat)](https://github.com/neostandard/neostandard) +[![Security Responsible Disclosure](https://img.shields.io/badge/Security-Responsible%20Disclosure-yellow.svg)](https://github.com/fastify/.github/blob/main/SECURITY.md) Description =========== @@ -37,7 +27,6 @@ Requirements * [Node.js](http://nodejs.org/) 10+ - Install ======= @@ -45,7 +34,6 @@ Install npm i @fastify/busboy ``` - Examples ======== @@ -189,7 +177,6 @@ http.createServer(function(req, res) { // Done parsing form! ``` - API === @@ -199,9 +186,9 @@ Busboy (special) events ----------------------- * **file**(< _string_ >fieldname, < _ReadableStream_ >stream, < _string_ >filename, < _string_ >transferEncoding, < _string_ >mimeType) - Emitted for each new file form field found. `transferEncoding` contains the 'Content-Transfer-Encoding' value for the file stream. `mimeType` contains the 'Content-Type' value for the file stream. - * Note: if you listen for this event, you should always handle the `stream` no matter if you care about the file contents or not (e.g. you can simply just do `stream.resume();` if you want to discard the contents), otherwise the 'finish' event will never fire on the Busboy instance. However, if you don't care about **any** incoming files, you can simply not listen for the 'file' event at all and any/all files will be automatically and safely discarded (these discarded files do still count towards `files` and `parts` limits). - * If a configured file size limit was reached, `stream` will both have a boolean property `truncated` (best checked at the end of the stream) and emit a 'limit' event to notify you when this happens. - * The property `bytesRead` informs about the number of bytes that have been read so far. + * Note: if you listen for this event, you should always handle the `stream` no matter if you care about the file contents or not (e.g. you can simply just do `stream.resume();` if you want to discard the contents), otherwise the 'finish' event will never fire on the Busboy instance. However, if you don't care about **any** incoming files, you can simply not listen for the 'file' event at all and any/all files will be automatically and safely discarded (these discarded files do still count towards `files` and `parts` limits). + * If a configured file size limit was reached, `stream` will both have a boolean property `truncated` (best checked at the end of the stream) and emit a 'limit' event to notify you when this happens. + * The property `bytesRead` informs about the number of bytes that have been read so far. * **limit**() - Emitted when a file exceeds the configured `fileSize` limit. You can listen on the file stream to handle it: @@ -221,62 +208,61 @@ busboy.on('file', (fieldname, stream) => { * **fieldsLimit**() - Emitted when specified `fields` limit has been reached. No more 'field' events will be emitted. - Busboy methods -------------- * **(constructor)**(< _object_ >config) - Creates and returns a new Busboy instance. - * The constructor takes the following valid `config` settings: + * The constructor takes the following valid `config` settings: - * **headers** - _object_ - These are the HTTP headers of the incoming request, which are used by individual parsers. + * **headers** - _object_ - These are the HTTP headers of the incoming request, which are used by individual parsers. - * **autoDestroy** - _boolean_ - Whether this stream should automatically call .destroy() on itself after ending. (Default: false). + * **autoDestroy** - _boolean_ - Whether this stream should automatically call .destroy() on itself after ending. (Default: false). - * **highWaterMark** - _integer_ - highWaterMark to use for this Busboy instance (Default: WritableStream default). + * **highWaterMark** - _integer_ - highWaterMark to use for this Busboy instance (Default: WritableStream default). - * **fileHwm** - _integer_ - highWaterMark to use for file streams (Default: ReadableStream default). + * **fileHwm** - _integer_ - highWaterMark to use for file streams (Default: ReadableStream default). - * **defCharset** - _string_ - Default character set to use when one isn't defined (Default: 'utf8'). + * **defCharset** - _string_ - Default character set to use when one isn't defined (Default: 'utf8'). - * **preservePath** - _boolean_ - If paths in the multipart 'filename' field shall be preserved. (Default: false). + * **preservePath** - _boolean_ - If paths in the multipart 'filename' field shall be preserved. (Default: false). - * **isPartAFile** - __function__ - Use this function to override the default file detection functionality. It has following parameters: + * **isPartAFile** - **function** - Use this function to override the default file detection functionality. It has following parameters: - * fieldName - __string__ The name of the field. + * fieldName - **string** The name of the field. - * contentType - __string__ The content-type of the part, e.g. `text/plain`, `image/jpeg`, `application/octet-stream` + * contentType - **string** The content-type of the part, e.g. `text/plain`, `image/jpeg`, `application/octet-stream` - * fileName - __string__ The name of a file supplied by the part. + * fileName - **string** The name of a file supplied by the part. (Default: `(fieldName, contentType, fileName) => (contentType === 'application/octet-stream' || fileName !== undefined)`) - * **limits** - _object_ - Various limits on incoming data. Valid properties are: + * **limits** - _object_ - Various limits on incoming data. Valid properties are: - * **fieldNameSize** - _integer_ - Max field name size (in bytes) (Default: 100 bytes). + * **fieldNameSize** - _integer_ - Max field name size (in bytes) (Default: 100 bytes). - * **fieldSize** - _integer_ - Max field value size (in bytes) (Default: 1 MiB, which is 1024 x 1024 bytes). + * **fieldSize** - _integer_ - Max field value size (in bytes) (Default: 1 MiB, which is 1024 x 1024 bytes). - * **fields** - _integer_ - Max number of non-file fields (Default: Infinity). + * **fields** - _integer_ - Max number of non-file fields (Default: Infinity). - * **fileSize** - _integer_ - For multipart forms, the max file size (in bytes) (Default: Infinity). + * **fileSize** - _integer_ - For multipart forms, the max file size (in bytes) (Default: Infinity). - * **files** - _integer_ - For multipart forms, the max number of file fields (Default: Infinity). + * **files** - _integer_ - For multipart forms, the max number of file fields (Default: Infinity). - * **parts** - _integer_ - For multipart forms, the max number of parts (fields + files) (Default: Infinity). + * **parts** - _integer_ - For multipart forms, the max number of parts (fields + files) (Default: Infinity). - * **headerPairs** - _integer_ - For multipart forms, the max number of header key=>value pairs to parse **Default:** 2000 + * **headerPairs** - _integer_ - For multipart forms, the max number of header key=>value pairs to parse **Default:** 2000 - * **headerSize** - _integer_ - For multipart forms, the max size of a multipart header **Default:** 81920. + * **headerSize** - _integer_ - For multipart forms, the max size of a multipart header **Default:** 81920. - * The constructor can throw errors: + * The constructor can throw errors: - * **Busboy expected an options-Object.** - Busboy expected an Object as first parameters. + * **Busboy expected an options-Object.** - Busboy expected an Object as first parameters. - * **Busboy expected an options-Object with headers-attribute.** - The first parameter is lacking of a headers-attribute. + * **Busboy expected an options-Object with headers-attribute.** - The first parameter is lacking of a headers-attribute. - * **Limit $limit is not a valid number** - Busboy expected the desired limit to be of type number. Busboy throws this Error to prevent a potential security issue by falling silently back to the Busboy-defaults. Potential source for this Error can be the direct use of environment variables without transforming them to the type number. + * **Limit $limit is not a valid number** - Busboy expected the desired limit to be of type number. Busboy throws this Error to prevent a potential security issue by falling silently back to the Busboy-defaults. Potential source for this Error can be the direct use of environment variables without transforming them to the type number. - * **Unsupported Content-Type.** - The `Content-Type` isn't one Busboy can parse. + * **Unsupported Content-Type.** - The `Content-Type` isn't one Busboy can parse. - * **Missing Content-Type-header.** - The provided headers don't include `Content-Type` at all. + * **Missing Content-Type-header.** - The provided headers don't include `Content-Type` at all. diff --git a/bench/busboy-form-bench-latin1.js b/bench/busboy-form-bench-latin1.js index 33634ad..6e2b8f8 100644 --- a/bench/busboy-form-bench-latin1.js +++ b/bench/busboy-form-bench-latin1.js @@ -1,32 +1,30 @@ 'use strict' -const Busboy = require('busboy'); -const { createMultipartBufferForEncodingBench } = require("./createMultipartBufferForEncodingBench"); +const Busboy = require('busboy') +const { createMultipartBufferForEncodingBench } = require('./createMultipartBufferForEncodingBench') - for (var i = 0, il = 10000; i < il; i++) { // eslint-disable-line no-var - const boundary = '-----------------------------168072824752491622650073', - busboy = new Busboy({ - headers: { - 'content-type': 'multipart/form-data; boundary=' + boundary - } - }), - buffer = createMultipartBufferForEncodingBench(boundary, 100, 'iso-8859-1'), - mb = buffer.length / 1048576; +for (var i = 0, il = 10000; i < il; i++) { // eslint-disable-line no-var + const boundary = '-----------------------------168072824752491622650073' + const busboy = new Busboy({ + headers: { + 'content-type': 'multipart/form-data; boundary=' + boundary + } + }) + const buffer = createMultipartBufferForEncodingBench(boundary, 100, 'iso-8859-1') + const mb = buffer.length / 1048576 - let processedData = 0; - busboy.on('file', (field, file, filename, encoding, mimetype) => { - file.resume() - }) + busboy.on('file', (field, file, filename, encoding, mimetype) => { + file.resume() + }) - busboy.on('error', function (err) { - }) - busboy.on('finish', function () { - }) + busboy.on('error', function () { + }) + busboy.on('finish', function () { + }) - const start = +new Date(); - const result = busboy.write(buffer, () => { }); - busboy.end(); - const duration = +new Date - start; - const mbPerSec = (mb / (duration / 1000)).toFixed(2); - console.log(mbPerSec + ' mb/sec'); - } \ No newline at end of file + const start = +new Date() + busboy.end() + const duration = +new Date() - start + const mbPerSec = (mb / (duration / 1000)).toFixed(2) + console.log(mbPerSec + ' mb/sec') +} diff --git a/bench/busboy-form-bench-utf8.js b/bench/busboy-form-bench-utf8.js index 1e6e0b7..9ff9b81 100644 --- a/bench/busboy-form-bench-utf8.js +++ b/bench/busboy-form-bench-utf8.js @@ -1,32 +1,30 @@ 'use strict' -const Busboy = require('busboy'); -const { createMultipartBufferForEncodingBench } = require("./createMultipartBufferForEncodingBench"); +const Busboy = require('busboy') +const { createMultipartBufferForEncodingBench } = require('./createMultipartBufferForEncodingBench') - for (var i = 0, il = 10000; i < il; i++) { // eslint-disable-line no-var - const boundary = '-----------------------------168072824752491622650073', - busboy = new Busboy({ - headers: { - 'content-type': 'multipart/form-data; boundary=' + boundary - } - }), - buffer = createMultipartBufferForEncodingBench(boundary, 100, 'utf-8'), - mb = buffer.length / 1048576; +for (var i = 0, il = 10000; i < il; i++) { // eslint-disable-line no-var + const boundary = '-----------------------------168072824752491622650073' + const busboy = new Busboy({ + headers: { + 'content-type': 'multipart/form-data; boundary=' + boundary + } + }) + const buffer = createMultipartBufferForEncodingBench(boundary, 100, 'utf-8') + const mb = buffer.length / 1048576 - let processedData = 0; - busboy.on('file', (field, file, filename, encoding, mimetype) => { - file.resume() - }) + busboy.on('file', (field, file, filename, encoding, mimetype) => { + file.resume() + }) - busboy.on('error', function (err) { - }) - busboy.on('finish', function () { - }) + busboy.on('error', function () { + }) + busboy.on('finish', function () { + }) - const start = +new Date(); - const result = busboy.write(buffer, () => { }); - busboy.end(); - const duration = +new Date - start; - const mbPerSec = (mb / (duration / 1000)).toFixed(2); - console.log(mbPerSec + ' mb/sec'); - } \ No newline at end of file + const start = +new Date() + busboy.end() + const duration = +new Date() - start + const mbPerSec = (mb / (duration / 1000)).toFixed(2) + console.log(mbPerSec + ' mb/sec') +} diff --git a/bench/createMultipartBufferForEncodingBench.js b/bench/createMultipartBufferForEncodingBench.js index 9d20f8f..94f6009 100644 --- a/bench/createMultipartBufferForEncodingBench.js +++ b/bench/createMultipartBufferForEncodingBench.js @@ -1,11 +1,12 @@ 'use strict' -function createMultipartBufferForEncodingBench(boundary, amount, charset) { - const filename = charset === 'utf-8' ? 'utf-8\'\'%c2%a3%20and%20%e2%82%ac%20rates' : `${charset}\'en\'%A3%20rates`; - const head = '--' + boundary + '\r\n' - + 'content-disposition: form-data; name="field1"\r\n' - + 'content-type: text/plain;charset=' + charset + '; filename*=' + filename + '\r\n' - + '\r\n', tail = '\r\n--' + boundary + '--\r\n', buffer = Buffer.concat([Buffer.from(head), Buffer.from(` +function createMultipartBufferForEncodingBench (boundary, amount, charset) { + // eslint-disable-next-line no-useless-escape + const filename = charset === 'utf-8' ? 'utf-8\'\'%c2%a3%20and%20%e2%82%ac%20rates' : `${charset}\'en\'%A3%20rates` + const head = '--' + boundary + '\r\n' + + 'content-disposition: form-data; name="field1"\r\n' + + 'content-type: text/plain;charset=' + charset + '; filename*=' + filename + '\r\n' + + '\r\n'; const tail = '\r\n--' + boundary + '--\r\n'; const buffer = Buffer.concat([Buffer.from(head), Buffer.from(` Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus pretium leo ex, vitae dignissim felis viverra non. Praesent id quam ac elit tincidunt porttitor sed eget magna. Vivamus nibh ipsum, malesuada in eros sit amet, rutrum mattis leo. Ut nunc justo, ornare a finibus in, consectetur euismod sapien. Praesent facilisis, odio consectetur facilisis varius, tellus justo tristique sapien, non porttitor eros massa quis nibh. Nam blandit orci ac efficitur cursus. Nunc non mollis sapien, sit amet pretium odio. Nam vestibulum lectus ac orci egestas aliquet. Duis nec nibh quis augue consequat vulputate a a dui. Aenean nec laoreet dolor, commodo aliquam leo. Quisque at placerat sem. In scelerisque cursus dolor, ac aliquam metus malesuada in. Vestibulum lacinia dolor purus, at convallis ipsum iaculis id. Integer bibendum sem neque, at bibendum enim lobortis eu. Cras pretium arcu eget congue cursus. Curabitur blandit ultricies mollis. Sed lacinia quis felis ut fringilla. @@ -14,10 +15,10 @@ Nulla vitae lobortis metus. Morbi gravida risus tortor, in pulvinar massa lobort Cras semper mi magna, nec iaculis neque rhoncus at. In sit amet odio sed libero fringilla commodo. Sed hendrerit pulvinar turpis sed porta. Pellentesque consequat scelerisque sapien nec iaculis. Aenean sed nunc a purus laoreet efficitur id eu orci. Mauris tincidunt auctor congue. Aliquam nisi ligula, facilisis a molestie sed, luctus vitae mauris. Mauris at facilisis elit. Maecenas sodales pretium nisi in sodales. Cras nec blandit enim. Praesent in lacus et nibh varius suscipit in sit amet nibh. -Nam hendrerit justo eu lectus molestie, sit amet fringilla ipsum semper. Maecenas sit amet nunc elementum, interdum nunc eu, euismod ipsum. Vestibulum ut mauris sapien. Praesent nec felis ex. Fusce vel leo lobortis, mattis sem a, ullamcorper dolor. Aliquam erat volutpat. Fusce feugiat odio ut feugiat volutpat. Vestibulum magna ante, tempor in volutpat ut, gravida vitae justo. Praesent vitae eleifend eros. Integer feugiat molestie dolor, et pretium enim accumsan sit amet. Sed quis suscipit dui. Integer gravida dolor elit, sit amet fringilla odio commodo at. Quisque ut eleifend risus. Nunc mollis velit quis lectus laoreet pellentesque.\r\n\r\n`)]); +Nam hendrerit justo eu lectus molestie, sit amet fringilla ipsum semper. Maecenas sit amet nunc elementum, interdum nunc eu, euismod ipsum. Vestibulum ut mauris sapien. Praesent nec felis ex. Fusce vel leo lobortis, mattis sem a, ullamcorper dolor. Aliquam erat volutpat. Fusce feugiat odio ut feugiat volutpat. Vestibulum magna ante, tempor in volutpat ut, gravida vitae justo. Praesent vitae eleifend eros. Integer feugiat molestie dolor, et pretium enim accumsan sit amet. Sed quis suscipit dui. Integer gravida dolor elit, sit amet fringilla odio commodo at. Quisque ut eleifend risus. Nunc mollis velit quis lectus laoreet pellentesque.\r\n\r\n`)]) - const buffers = new Array(amount).fill(buffer); - buffers.push(Buffer.from(tail)); - return Buffer.concat(buffers); + const buffers = new Array(amount).fill(buffer) + buffers.push(Buffer.from(tail)) + return Buffer.concat(buffers) } -exports.createMultipartBufferForEncodingBench = createMultipartBufferForEncodingBench; +exports.createMultipartBufferForEncodingBench = createMultipartBufferForEncodingBench diff --git a/bench/dicer/dicer-bench-multipart-parser.js b/bench/dicer/dicer-bench-multipart-parser.js index d24f599..054ad44 100644 --- a/bench/dicer/dicer-bench-multipart-parser.js +++ b/bench/dicer/dicer-bench-multipart-parser.js @@ -2,25 +2,25 @@ const Dicer = require('../../deps/dicer/lib/Dicer') -function createMultipartBuffer(boundary, size) { +function createMultipartBuffer (boundary, size) { const head = - '--' + boundary + '\r\n' - + 'content-disposition: form-data; name="field1"\r\n' - + '\r\n' - , tail = '\r\n--' + boundary + '--\r\n' - , buffer = Buffer.allocUnsafe(size); - - buffer.write(head, 0, 'ascii'); - buffer.write(tail, buffer.length - tail.length, 'ascii'); - return buffer; + '--' + boundary + '\r\n' + + 'content-disposition: form-data; name="field1"\r\n' + + '\r\n' + const tail = '\r\n--' + boundary + '--\r\n' + const buffer = Buffer.allocUnsafe(size) + + buffer.write(head, 0, 'ascii') + buffer.write(tail, buffer.length - tail.length, 'ascii') + return buffer } for (var i = 0, il = 10; i < il; i++) { // eslint-disable-line no-var - const boundary = '-----------------------------168072824752491622650073', - d = new Dicer({ boundary: boundary }), - mb = 100, - buffer = createMultipartBuffer(boundary, mb * 1024 * 1024), - callbacks = + const boundary = '-----------------------------168072824752491622650073' + const d = new Dicer({ boundary }) + const mb = 100 + const buffer = createMultipartBuffer(boundary, mb * 1024 * 1024) + const callbacks = { partBegin: -1, partEnd: -1, @@ -28,33 +28,32 @@ for (var i = 0, il = 10; i < il; i++) { // eslint-disable-line no-var headerValue: -1, partData: -1, end: -1, - }; - + } d.on('part', function (p) { - callbacks.partBegin++; + callbacks.partBegin++ p.on('header', function (header) { - /*for (var h in header) - console.log('Part header: k: ' + inspect(h) + ', v: ' + inspect(header[h]));*/ - }); + /* for (var h in header) + console.log('Part header: k: ' + inspect(h) + ', v: ' + inspect(header[h])); */ + }) p.on('data', function (data) { - callbacks.partData++; - //console.log('Part data: ' + inspect(data.toString())); - }); + callbacks.partData++ + // console.log('Part data: ' + inspect(data.toString())); + }) p.on('end', function () { - //console.log('End of part\n'); - callbacks.partEnd++; - }); - }); + // console.log('End of part\n'); + callbacks.partEnd++ + }) + }) d.on('end', function () { - //console.log('End of parts'); - callbacks.end++; - }); + // console.log('End of parts'); + callbacks.end++ + }) - const start = +new Date(); - d.write(buffer); - const duration = +new Date - start; - const mbPerSec = (mb / (duration / 1000)).toFixed(2); + const start = +new Date() + d.write(buffer) + const duration = +new Date() - start + const mbPerSec = (mb / (duration / 1000)).toFixed(2) - console.log(mbPerSec + ' mb/sec'); + console.log(mbPerSec + ' mb/sec') } diff --git a/bench/dicer/formidable-bench-multipart-parser.js b/bench/dicer/formidable-bench-multipart-parser.js index 0470771..a36454c 100644 --- a/bench/dicer/formidable-bench-multipart-parser.js +++ b/bench/dicer/formidable-bench-multipart-parser.js @@ -1,71 +1,73 @@ 'use strict' -require('../node_modules/formidable/test/common'); -var multipartParser = require('../node_modules/formidable/lib/multipart_parser'), - MultipartParser = multipartParser.MultipartParser, - parser = new MultipartParser(), - boundary = '-----------------------------168072824752491622650073', - mb = 100, - buffer = createMultipartBuffer(boundary, mb * 1024 * 1024), - callbacks = - { partBegin: -1, +/* eslint-disable */ + +require('../node_modules/formidable/test/common') +const multipartParser = require('../node_modules/formidable/lib/multipart_parser') +const MultipartParser = multipartParser.MultipartParser +const parser = new MultipartParser() +const boundary = '-----------------------------168072824752491622650073' +const mb = 100 +const buffer = createMultipartBuffer(boundary, mb * 1024 * 1024) +const callbacks = + { + partBegin: -1, partEnd: -1, headerField: -1, headerValue: -1, partData: -1, end: -1, - }; - + } -parser.initWithBoundary(boundary); -parser.onHeaderField = function() { - callbacks.headerField++; -}; +parser.initWithBoundary(boundary) +parser.onHeaderField = function () { + callbacks.headerField++ +} -parser.onHeaderValue = function() { - callbacks.headerValue++; -}; +parser.onHeaderValue = function () { + callbacks.headerValue++ +} -parser.onPartBegin = function() { - callbacks.partBegin++; -}; +parser.onPartBegin = function () { + callbacks.partBegin++ +} -parser.onPartData = function() { - callbacks.partData++; -}; +parser.onPartData = function () { + callbacks.partData++ +} -parser.onPartEnd = function() { - callbacks.partEnd++; -}; +parser.onPartEnd = function () { + callbacks.partEnd++ +} -parser.onEnd = function() { - callbacks.end++; -}; +parser.onEnd = function () { + callbacks.end++ +} -var start = +new Date(), - nparsed = parser.write(buffer), - duration = +new Date - start, - mbPerSec = (mb / (duration / 1000)).toFixed(2); +const start = +new Date() +const nparsed = parser.write(buffer) +const duration = +new Date() - start +const mbPerSec = (mb / (duration / 1000)).toFixed(2) -console.log(mbPerSec+' mb/sec'); +console.log(mbPerSec + ' mb/sec') -//assert.equal(nparsed, buffer.length); +// assert.equal(nparsed, buffer.length); -function createMultipartBuffer(boundary, size) { - var head = - '--'+boundary+'\r\n' - + 'content-disposition: form-data; name="field1"\r\n' - + '\r\n' - , tail = '\r\n--'+boundary+'--\r\n' - , buffer = Buffer.allocUnsafe(size); +function createMultipartBuffer (boundary, size) { + const head = + '--' + boundary + '\r\n' + + 'content-disposition: form-data; name="field1"\r\n' + + '\r\n' + const tail = '\r\n--' + boundary + '--\r\n' + const buffer = Buffer.allocUnsafe(size) - buffer.write(head, 'ascii', 0); - buffer.write(tail, 'ascii', buffer.length - tail.length); - return buffer; + buffer.write(head, 'ascii', 0) + buffer.write(tail, 'ascii', buffer.length - tail.length) + return buffer } -process.on('exit', function() { - /*for (var k in callbacks) { +process.on('exit', function () { + /* for (var k in callbacks) { assert.equal(0, callbacks[k], k+' count off by '+callbacks[k]); - }*/ -}); + } */ +}) diff --git a/bench/dicer/multipartser-bench-multipart-parser.js b/bench/dicer/multipartser-bench-multipart-parser.js index 40ca00b..8da324c 100644 --- a/bench/dicer/multipartser-bench-multipart-parser.js +++ b/bench/dicer/multipartser-bench-multipart-parser.js @@ -1,57 +1,55 @@ 'use strict' -var multipartser = require('multipartser'), - boundary = '-----------------------------168072824752491622650073', - parser = multipartser(), - mb = 100, - buffer = createMultipartBuffer(boundary, mb * 1024 * 1024), - callbacks = - { partBegin: -1, +/* eslint-disable */ +const multipartser = require('multipartser') +const boundary = '-----------------------------168072824752491622650073' +const parser = multipartser() +const mb = 100 +const buffer = createMultipartBuffer(boundary, mb * 1024 * 1024) +const callbacks = + { + partBegin: -1, partEnd: -1, headerField: -1, headerValue: -1, partData: -1, end: -1, - }; + } -parser.boundary( boundary ); +parser.boundary(boundary) -parser.on( 'part', function ( part ) { -}); +parser.on('part', function (part) { +}) -parser.on( 'end', function () { - //console.log( 'completed parsing' ); -}); +parser.on('end', function () { + // console.log( 'completed parsing' ); +}) -parser.on( 'error', function ( error ) { - console.error( error ); -}); +parser.on('error', function (error) { + console.error(error) +}) -var start = +new Date(), - nparsed = parser.data(buffer), - nend = parser.end(), - duration = +new Date - start, - mbPerSec = (mb / (duration / 1000)).toFixed(2); +const start = +new Date() +const duration = +new Date() - start +const mbPerSec = (mb / (duration / 1000)).toFixed(2) -console.log(mbPerSec+' mb/sec'); +console.log(mbPerSec + ' mb/sec') -//assert.equal(nparsed, buffer.length); +function createMultipartBuffer (boundary, size) { + const head = + '--' + boundary + '\r\n' + + 'content-disposition: form-data; name="field1"\r\n' + + '\r\n' + const tail = '\r\n--' + boundary + '--\r\n' + const buffer = Buffer.allocUnsafe(size) -function createMultipartBuffer(boundary, size) { - var head = - '--'+boundary+'\r\n' - + 'content-disposition: form-data; name="field1"\r\n' - + '\r\n' - , tail = '\r\n--'+boundary+'--\r\n' - , buffer = Buffer.allocUnsafe(size); - - buffer.write(head, 'ascii', 0); - buffer.write(tail, 'ascii', buffer.length - tail.length); - return buffer; + buffer.write(head, 'ascii', 0) + buffer.write(tail, 'ascii', buffer.length - tail.length) + return buffer } -process.on('exit', function() { - /*for (var k in callbacks) { +process.on('exit', function () { + /* for (var k in callbacks) { assert.equal(0, callbacks[k], k+' count off by '+callbacks[k]); - }*/ -}); + } */ +}) diff --git a/bench/dicer/multiparty-bench-multipart-parser.js b/bench/dicer/multiparty-bench-multipart-parser.js index ab79ec0..f86b063 100644 --- a/bench/dicer/multiparty-bench-multipart-parser.js +++ b/bench/dicer/multiparty-bench-multipart-parser.js @@ -1,78 +1,79 @@ 'use strict' -var assert = require('node:assert'), - Form = require('multiparty').Form, - boundary = '-----------------------------168072824752491622650073', - mb = 100, - buffer = createMultipartBuffer(boundary, mb * 1024 * 1024), - callbacks = - { partBegin: -1, +const assert = require('node:assert') +const Form = require('multiparty').Form +const boundary = '-----------------------------168072824752491622650073' +const mb = 100 +const buffer = createMultipartBuffer(boundary, mb * 1024 * 1024) +const callbacks = + { + partBegin: -1, partEnd: -1, headerField: -1, headerValue: -1, partData: -1, end: -1, - }; + } -var form = new Form({ boundary: boundary }); +const form = new Form({ boundary }) -hijack('onParseHeaderField', function() { - callbacks.headerField++; -}); +hijack('onParseHeaderField', function () { + callbacks.headerField++ +}) -hijack('onParseHeaderValue', function() { - callbacks.headerValue++; -}); +hijack('onParseHeaderValue', function () { + callbacks.headerValue++ +}) -hijack('onParsePartBegin', function() { - callbacks.partBegin++; -}); +hijack('onParsePartBegin', function () { + callbacks.partBegin++ +}) -hijack('onParsePartData', function() { - callbacks.partData++; -}); +hijack('onParsePartData', function () { + callbacks.partData++ +}) -hijack('onParsePartEnd', function() { - callbacks.partEnd++; -}); +hijack('onParsePartEnd', function () { + callbacks.partEnd++ +}) -form.on('finish', function() { - callbacks.end++; -}); +form.on('finish', function () { + callbacks.end++ +}) -var start = new Date(); -form.write(buffer, function(err) { - var duration = new Date() - start; - assert.ifError(err); - var mbPerSec = (mb / (duration / 1000)).toFixed(2); - console.log(mbPerSec+' mb/sec'); -}); +const start = new Date() +form.write(buffer, function (err) { + const duration = new Date() - start + assert.ifError(err) + const mbPerSec = (mb / (duration / 1000)).toFixed(2) + console.log(mbPerSec + ' mb/sec') +}) -//assert.equal(nparsed, buffer.length); +// assert.equal(nparsed, buffer.length); -function createMultipartBuffer(boundary, size) { - var head = - '--'+boundary+'\r\n' - + 'content-disposition: form-data; name="field1"\r\n' - + '\r\n' - , tail = '\r\n--'+boundary+'--\r\n' - , buffer = Buffer.allocUnsafe(size); +function createMultipartBuffer (boundary, size) { + const head = + '--' + boundary + '\r\n' + + 'content-disposition: form-data; name="field1"\r\n' + + '\r\n' + const tail = '\r\n--' + boundary + '--\r\n' + const buffer = Buffer.allocUnsafe(size) - buffer.write(head, 'ascii', 0); - buffer.write(tail, 'ascii', buffer.length - tail.length); - return buffer; + buffer.write(head, 'ascii', 0) + buffer.write(tail, 'ascii', buffer.length - tail.length) + return buffer } -process.on('exit', function() { - /*for (var k in callbacks) { +process.on('exit', function () { + /* for (var k in callbacks) { assert.equal(0, callbacks[k], k+' count off by '+callbacks[k]); - }*/ -}); + } */ +}) -function hijack(name, fn) { - var oldFn = form[name]; - form[name] = function() { - fn(); - return oldFn.apply(this, arguments); - }; +function hijack (name, fn) { + const oldFn = form[name] + form[name] = function () { + fn() + return oldFn.apply(this, arguments) + } } diff --git a/bench/dicer/parted-bench-multipart-parser.js b/bench/dicer/parted-bench-multipart-parser.js index e0a4670..9ac0e9e 100644 --- a/bench/dicer/parted-bench-multipart-parser.js +++ b/bench/dicer/parted-bench-multipart-parser.js @@ -1,65 +1,62 @@ 'use strict' +/* eslint-disable */ // A special, edited version of the multipart parser from parted is needed here // because otherwise it attempts to do some things above and beyond just parsing // -- like saving to disk and whatnot -var assert = require('node:assert'); -var Parser = require('./parted-multipart'), - boundary = '-----------------------------168072824752491622650073', - parser = new Parser('boundary=' + boundary), - mb = 100, - buffer = createMultipartBuffer(boundary, mb * 1024 * 1024), - callbacks = - { partBegin: -1, +const Parser = require('./parted-multipart') +const boundary = '-----------------------------168072824752491622650073' +const parser = new Parser('boundary=' + boundary) +const mb = 100 +const buffer = createMultipartBuffer(boundary, mb * 1024 * 1024) +const callbacks = + { + partBegin: -1, partEnd: -1, headerField: -1, headerValue: -1, partData: -1, end: -1, - }; + } +parser.on('header', function () { + // callbacks.headerField++; +}) -parser.on('header', function() { - //callbacks.headerField++; -}); +parser.on('data', function () { + // callbacks.partBegin++; +}) -parser.on('data', function() { - //callbacks.partBegin++; -}); +parser.on('part', function () { -parser.on('part', function() { +}) -}); +parser.on('end', function () { + // callbacks.end++; +}) -parser.on('end', function() { - //callbacks.end++; -}); +const start = +new Date() +const duration = +new Date() - start +const mbPerSec = (mb / (duration / 1000)).toFixed(2) -var start = +new Date(), - nparsed = parser.write(buffer), - duration = +new Date - start, - mbPerSec = (mb / (duration / 1000)).toFixed(2); +console.log(mbPerSec + ' mb/sec') -console.log(mbPerSec+' mb/sec'); +function createMultipartBuffer (boundary, size) { + const head = + '--' + boundary + '\r\n' + + 'content-disposition: form-data; name="field1"\r\n' + + '\r\n' + const tail = '\r\n--' + boundary + '--\r\n' + const buffer = Buffer.allocUnsafe(size) -//assert.equal(nparsed, buffer.length); - -function createMultipartBuffer(boundary, size) { - var head = - '--'+boundary+'\r\n' - + 'content-disposition: form-data; name="field1"\r\n' - + '\r\n' - , tail = '\r\n--'+boundary+'--\r\n' - , buffer = Buffer.allocUnsafe(size); - - buffer.write(head, 'ascii', 0); - buffer.write(tail, 'ascii', buffer.length - tail.length); - return buffer; + buffer.write(head, 'ascii', 0) + buffer.write(tail, 'ascii', buffer.length - tail.length) + return buffer } -process.on('exit', function() { - /*for (var k in callbacks) { +process.on('exit', function () { + /* for (var k in callbacks) { assert.equal(0, callbacks[k], k+' count off by '+callbacks[k]); - }*/ -}); + } */ +}) diff --git a/bench/dicer/parted-multipart.js b/bench/dicer/parted-multipart.js index f214ff4..20c6358 100644 --- a/bench/dicer/parted-multipart.js +++ b/bench/dicer/parted-multipart.js @@ -1,4 +1,5 @@ 'use strict' +/* eslint-disable */ /** * Parted (https://github.com/chjj/parted) @@ -6,273 +7,273 @@ * Copyright (c) 2011, Christopher Jeffrey. (MIT Licensed) */ -var fs = require('node:fs') - , path = require('node:path') - , EventEmitter = require('node:events').EventEmitter - , StringDecoder = require('node:string_decoder').StringDecoder - , set = require('qs').set - , each = Array.prototype.forEach; +const fs = require('node:fs') +const path = require('node:path') +const EventEmitter = require('node:events').EventEmitter +const StringDecoder = require('node:string_decoder').StringDecoder +const set = require('qs').set +const each = Array.prototype.forEach /** * Character Constants */ -var DASH = '-'.charCodeAt(0) - , CR = '\r'.charCodeAt(0) - , LF = '\n'.charCodeAt(0) - , COLON = ':'.charCodeAt(0) - , SPACE = ' '.charCodeAt(0); +const DASH = '-'.charCodeAt(0) +const CR = '\r'.charCodeAt(0) +const LF = '\n'.charCodeAt(0) +const COLON = ':'.charCodeAt(0) +const SPACE = ' '.charCodeAt(0) /** * Parser */ -var Parser = function(type, options) { +const Parser = function (type, options) { if (!(this instanceof Parser)) { - return new Parser(type, options); + return new Parser(type, options) } - EventEmitter.call(this); + EventEmitter.call(this) - this.writable = true; - this.readable = true; + this.writable = true + this.readable = true - this.options = options || {}; + this.options = options || {} - var key = grab(type, 'boundary'); + const key = grab(type, 'boundary') if (!key) { - return this._error('No boundary key found.'); + return this._error('No boundary key found.') } - this.key = Buffer.allocUnsafe('\r\n--' + key); + this.key = Buffer.allocUnsafe('\r\n--' + key) - this._key = {}; - each.call(this.key, function(ch) { - this._key[ch] = true; - }, this); + this._key = {} + each.call(this.key, function (ch) { + this._key[ch] = true + }, this) - this.state = 'start'; - this.pending = 0; - this.written = 0; - this.writtenDisk = 0; - this.buff = Buffer.allocUnsafe(200); + this.state = 'start' + this.pending = 0 + this.written = 0 + this.writtenDisk = 0 + this.buff = Buffer.allocUnsafe(200) - this.preamble = true; - this.epilogue = false; + this.preamble = true + this.epilogue = false - this._reset(); -}; + this._reset() +} -Parser.prototype.__proto__ = EventEmitter.prototype; +Parser.prototype.__proto__ = EventEmitter.prototype /** * Parsing */ -Parser.prototype.write = function(data) { - if (!this.writable - || this.epilogue) return; +Parser.prototype.write = function (data) { + if (!this.writable || + this.epilogue) return try { - this._parse(data); + this._parse(data) } catch (e) { - this._error(e); + this._error(e) } - return true; -}; + return true +} -Parser.prototype.end = function(data) { - if (!this.writable) return; +Parser.prototype.end = function (data) { + if (!this.writable) return - if (data) this.write(data); + if (data) this.write(data) if (!this.epilogue) { - return this._error('Message underflow.'); + return this._error('Message underflow.') } - return true; -}; + return true +} -Parser.prototype._parse = function(data) { - var i = 0 - , len = data.length - , buff = this.buff - , key = this.key - , ch - , val - , j; +Parser.prototype._parse = function (data) { + let i = 0 + let len = data.length + const buff = this.buff + const key = this.key + let ch + let val + let j for (; i < len; i++) { if (this.pos >= 200) { - return this._error('Potential buffer overflow.'); + return this._error('Potential buffer overflow.') } - ch = data[i]; + ch = data[i] switch (this.state) { case 'start': switch (ch) { case DASH: - this.pos = 3; - this.state = 'key'; - break; + this.pos = 3 + this.state = 'key' + break default: - break; + break } - break; + break case 'key': if (this.pos === key.length) { - this.state = 'key_end'; - i--; + this.state = 'key_end' + i-- } else if (ch !== key[this.pos]) { if (this.preamble) { - this.state = 'start'; - i--; + this.state = 'start' + i-- } else { - this.state = 'body'; - val = this.pos - i; + this.state = 'body' + val = this.pos - i if (val > 0) { - this._write(key.slice(0, val)); + this._write(key.slice(0, val)) } - i--; + i-- } } else { - this.pos++; + this.pos++ } - break; + break case 'key_end': switch (ch) { case CR: - this.state = 'key_line_end'; - break; + this.state = 'key_line_end' + break case DASH: - this.state = 'key_dash_end'; - break; + this.state = 'key_dash_end' + break default: - return this._error('Expected CR or DASH.'); + return this._error('Expected CR or DASH.') } - break; + break case 'key_line_end': switch (ch) { case LF: if (this.preamble) { - this.preamble = false; + this.preamble = false } else { - this._finish(); + this._finish() } - this.state = 'header_name'; - this.pos = 0; - break; + this.state = 'header_name' + this.pos = 0 + break default: - return this._error('Expected CR.'); + return this._error('Expected CR.') } - break; + break case 'key_dash_end': switch (ch) { case DASH: - this.epilogue = true; - this._finish(); - return; + this.epilogue = true + this._finish() + return default: - return this._error('Expected DASH.'); + return this._error('Expected DASH.') } case 'header_name': switch (ch) { case COLON: - this.header = buff.toString('ascii', 0, this.pos); - this.pos = 0; - this.state = 'header_val'; - break; + this.header = buff.toString('ascii', 0, this.pos) + this.pos = 0 + this.state = 'header_val' + break default: - buff[this.pos++] = ch | 32; - break; + buff[this.pos++] = ch | 32 + break } - break; + break case 'header_val': switch (ch) { case CR: - this.state = 'header_val_end'; - break; + this.state = 'header_val_end' + break case SPACE: if (this.pos === 0) { - break; + break } // FALL-THROUGH default: - buff[this.pos++] = ch; - break; + buff[this.pos++] = ch + break } - break; + break case 'header_val_end': switch (ch) { case LF: - val = buff.toString('ascii', 0, this.pos); - this._header(this.header, val); - this.pos = 0; - this.state = 'header_end'; - break; + val = buff.toString('ascii', 0, this.pos) + this._header(this.header, val) + this.pos = 0 + this.state = 'header_end' + break default: - return this._error('Expected LF.'); + return this._error('Expected LF.') } - break; + break case 'header_end': switch (ch) { case CR: - this.state = 'head_end'; - break; + this.state = 'head_end' + break default: - this.state = 'header_name'; - i--; - break; + this.state = 'header_name' + i-- + break } - break; + break case 'head_end': switch (ch) { case LF: - this.state = 'body'; - i++; - if (i >= len) return; - data = data.slice(i); - i = -1; - len = data.length; - break; + this.state = 'body' + i++ + if (i >= len) return + data = data.slice(i) + i = -1 + len = data.length + break default: - return this._error('Expected LF.'); + return this._error('Expected LF.') } - break; + break case 'body': switch (ch) { case CR: if (i > 0) { - this._write(data.slice(0, i)); + this._write(data.slice(0, i)) } - this.pos = 1; - this.state = 'key'; - data = data.slice(i); - i = 0; - len = data.length; - break; + this.pos = 1 + this.state = 'key' + data = data.slice(i) + i = 0 + len = data.length + break default: // boyer-moore-like algorithm // at felixge's suggestion while ((j = i + key.length - 1) < len) { - if (this._key[data[j]]) break; - i = j; + if (this._key[data[j]]) break + i = j } - break; + break } - break; + break } } if (this.state === 'body') { - this._write(data); + this._write(data) } -}; +} -Parser.prototype._header = function(name, val) { - /*if (name === 'content-disposition') { +Parser.prototype._header = function (name, val) { + /* if (name === 'content-disposition') { this.field = grab(val, 'name'); this.file = grab(val, 'filename'); @@ -282,13 +283,13 @@ Parser.prototype._header = function(name, val) { this.decode = new StringDecoder('utf8'); this.data = ''; } - }*/ + } */ - return this.emit('header', name, val); -}; + return this.emit('header', name, val) +} -Parser.prototype._write = function(data) { - /*if (this.data == null) { +Parser.prototype._write = function (data) { + /* if (this.data == null) { return this._error('No disposition.'); } @@ -298,69 +299,69 @@ Parser.prototype._write = function(data) { } else { this.data += this.decode.write(data); this.written += data.length; - }*/ - - this.emit('data', data); -}; - -Parser.prototype._reset = function() { - this.pos = 0; - this.decode = null; - this.field = null; - this.data = null; - this.file = null; - this.header = null; -}; - -Parser.prototype._error = function(err) { - this.destroy(); + } */ + + this.emit('data', data) +} + +Parser.prototype._reset = function () { + this.pos = 0 + this.decode = null + this.field = null + this.data = null + this.file = null + this.header = null +} + +Parser.prototype._error = function (err) { + this.destroy() this.emit('error', typeof err === 'string' ? new Error(err) - : err); -}; + : err) +} -Parser.prototype.destroy = function(err) { - this.writable = false; - this.readable = false; - this._reset(); -}; +Parser.prototype.destroy = function (err) { + this.writable = false + this.readable = false + this._reset() +} -Parser.prototype._finish = function() { - var self = this - , field = this.field - , data = this.data - , file = this.file - , part; +Parser.prototype._finish = function () { + const self = this + const field = this.field + const data = this.data + const file = this.file + let part - this.pending++; + this.pending++ - this._reset(); + this._reset() if (data && data.path) { - part = data.path; - data.end(next); + part = data.path + data.end(next) } else { - part = data; - next(); + part = data + next() } - function next() { - if (!self.readable) return; + function next () { + if (!self.readable) return - self.pending--; + self.pending-- - self.emit('part', field, part); + self.emit('part', field, part) if (data && data.path) { - self.emit('file', field, part, file); + self.emit('file', field, part, file) } if (self.epilogue && !self.pending) { - self.emit('end'); - self.destroy(); + self.emit('end') + self.destroy() } } -}; +} /** * Uploads @@ -368,119 +369,119 @@ Parser.prototype._finish = function() { Parser.root = process.platform === 'win32' ? 'C:/Temp' - : '/tmp'; + : '/tmp' /** * Middleware */ -Parser.middleware = function(options) { - options = options || {}; - return function(req, res, next) { +Parser.middleware = function (options) { + options = options || {} + return function (req, res, next) { if (options.ensureBody) { - req.body = {}; + req.body = {} } - if (req.method === 'GET' - || req.method === 'HEAD' - || req._multipart) return next(); + if (req.method === 'GET' || + req.method === 'HEAD' || + req._multipart) return next() - req._multipart = true; + req._multipart = true - var type = req.headers['content-type']; + let type = req.headers['content-type'] - if (type) type = type.split(';', 1)[0].trim().toLowerCase(); + if (type) type = type.split(';', 1)[0].trim().toLowerCase() if (type === 'multipart/form-data') { - Parser.handle(req, res, next, options); + Parser.handle(req, res, next, options) } else { - next(); + next() } - }; -}; + } +} /** * Handler */ -Parser.handle = function(req, res, next, options) { - var parser = new Parser(req.headers['content-type'], options) - , diskLimit = options.diskLimit - , limit = options.limit - , parts = {} - , files = {}; +Parser.handle = function (req, res, next, options) { + const parser = new Parser(req.headers['content-type'], options) + const diskLimit = options.diskLimit + const limit = options.limit + const parts = {} + const files = {} - parser.on('error', function(err) { - req.destroy(); - next(err); - }); + parser.on('error', function (err) { + req.destroy() + next(err) + }) - parser.on('part', function(field, part) { - set(parts, field, part); - }); + parser.on('part', function (field, part) { + set(parts, field, part) + }) - parser.on('file', function(field, path, name) { + parser.on('file', function (field, path, name) { set(files, field, { - path: path, - name: name, - toString: function() { - return path; + path, + name, + toString: function () { + return path } - }); - }); + }) + }) - parser.on('data', function() { + parser.on('data', function () { if (this.writtenDisk > diskLimit || this.written > limit) { - this.emit('error', new Error('Overflow.')); - this.destroy(); + this.emit('error', new Error('Overflow.')) + this.destroy() } - }); + }) - parser.on('end', next); + parser.on('end', next) - req.body = parts; - req.files = files; - req.pipe(parser); -}; + req.body = parts + req.files = files + req.pipe(parser) +} /** * Helpers */ -var isWindows = process.platform === 'win32'; +const isWindows = process.platform === 'win32' -var stream = function(name, dir) { - var ext = path.extname(name) || '' - , name = path.basename(name, ext) || '' - , dir = dir || Parser.root - , tag; +const stream = function (name, dir) { + const ext = path.extname(name) || '' + var name = path.basename(name, ext) || '' + var dir = dir || Parser.root + let tag - tag = Math.random().toString(36).substring(2); + tag = Math.random().toString(36).substring(2) - name = name.substring(0, 200) + '.' + tag; - name = path.join(dir, name) + ext.substring(0, 6); - name = name.replace(/\0/g, ''); + name = name.substring(0, 200) + '.' + tag + name = path.join(dir, name) + ext.substring(0, 6) + name = name.replace(/\0/g, '') if (isWindows) { - name = name.replace(/[:*<>|"?]/g, ''); + name = name.replace(/[:*<>|"?]/g, '') } - return fs.createWriteStream(name); -}; + return fs.createWriteStream(name) +} -var grab = function(str, name) { - if (!str) return; +var grab = function (str, name) { + if (!str) return - var rx = new RegExp('\\b' + name + '\\s*=\\s*("[^"]+"|\'[^\']+\'|[^;,]+)', 'i') - , cap = rx.exec(str); + const rx = new RegExp('\\b' + name + '\\s*=\\s*("[^"]+"|\'[^\']+\'|[^;,]+)', 'i') + const cap = rx.exec(str) if (cap) { - return cap[1].trim().replace(/^['"]|['"]$/g, ''); + return cap[1].trim().replace(/^['"]|['"]$/g, '') } -}; +} /** * Expose */ -module.exports = Parser; +module.exports = Parser diff --git a/bench/fastify-busboy-form-bench-latin1.js b/bench/fastify-busboy-form-bench-latin1.js index 7ca5f44..e199470 100644 --- a/bench/fastify-busboy-form-bench-latin1.js +++ b/bench/fastify-busboy-form-bench-latin1.js @@ -1,31 +1,31 @@ 'use strict' -const Busboy = require('../lib/main'); -const { createMultipartBufferForEncodingBench } = require("./createMultipartBufferForEncodingBench"); +const Busboy = require('../lib/main') +const { createMultipartBufferForEncodingBench } = require('./createMultipartBufferForEncodingBench') - for (var i = 0, il = 10000; i < il; i++) { // eslint-disable-line no-var - const boundary = '-----------------------------168072824752491622650073', - busboy = new Busboy({ - headers: { - 'content-type': 'multipart/form-data; boundary=' + boundary - } - }), - buffer = createMultipartBufferForEncodingBench(boundary, 100, 'iso-8859-1'), - mb = buffer.length / 1048576; +for (var i = 0, il = 10000; i < il; i++) { // eslint-disable-line no-var + const boundary = '-----------------------------168072824752491622650073' + const busboy = new Busboy({ + headers: { + 'content-type': 'multipart/form-data; boundary=' + boundary + } + }) + const buffer = createMultipartBufferForEncodingBench(boundary, 100, 'iso-8859-1') + const mb = buffer.length / 1048576 - busboy.on('file', (field, file, filename, encoding, mimetype) => { - file.resume() - }) + busboy.on('file', (field, file, filename, encoding, mimetype) => { + file.resume() + }) - busboy.on('error', function (err) { - }) - busboy.on('finish', function () { - }) + busboy.on('error', function () { + }) + busboy.on('finish', function () { + }) - const start = +new Date(); - busboy.write(buffer, () => { }); - busboy.end(); - const duration = +new Date - start; - const mbPerSec = (mb / (duration / 1000)).toFixed(2); - console.log(mbPerSec + ' mb/sec'); - } + const start = +new Date() + busboy.write(buffer, () => { }) + busboy.end() + const duration = +new Date() - start + const mbPerSec = (mb / (duration / 1000)).toFixed(2) + console.log(mbPerSec + ' mb/sec') +} diff --git a/bench/fastify-busboy-form-bench-utf8.js b/bench/fastify-busboy-form-bench-utf8.js index 6c35071..143d8d3 100644 --- a/bench/fastify-busboy-form-bench-utf8.js +++ b/bench/fastify-busboy-form-bench-utf8.js @@ -1,31 +1,31 @@ 'use strict' -const Busboy = require('../lib/main'); -const { createMultipartBufferForEncodingBench } = require("./createMultipartBufferForEncodingBench"); +const Busboy = require('../lib/main') +const { createMultipartBufferForEncodingBench } = require('./createMultipartBufferForEncodingBench') - for (var i = 0, il = 10000; i < il; i++) { // eslint-disable-line no-var - const boundary = '-----------------------------168072824752491622650073', - busboy = new Busboy({ - headers: { - 'content-type': 'multipart/form-data; boundary=' + boundary - } - }), - buffer = createMultipartBufferForEncodingBench(boundary, 100, 'utf-8'), - mb = buffer.length / 1048576; +for (var i = 0, il = 10000; i < il; i++) { // eslint-disable-line no-var + const boundary = '-----------------------------168072824752491622650073' + const busboy = new Busboy({ + headers: { + 'content-type': 'multipart/form-data; boundary=' + boundary + } + }) + const buffer = createMultipartBufferForEncodingBench(boundary, 100, 'utf-8') + const mb = buffer.length / 1048576 - busboy.on('file', (field, file, filename, encoding, mimetype) => { - file.resume() - }) + busboy.on('file', (field, file, filename, encoding, mimetype) => { + file.resume() + }) - busboy.on('error', function (err) { - }) - busboy.on('finish', function () { - }) + busboy.on('error', function () { + }) + busboy.on('finish', function () { + }) - const start = +new Date(); - busboy.write(buffer, () => { }); - busboy.end(); - const duration = +new Date - start; - const mbPerSec = (mb / (duration / 1000)).toFixed(2); - console.log(mbPerSec + ' mb/sec'); - } + const start = +new Date() + busboy.write(buffer, () => { }) + busboy.end() + const duration = +new Date() - start + const mbPerSec = (mb / (duration / 1000)).toFixed(2) + console.log(mbPerSec + ' mb/sec') +} diff --git a/bench/parse-params.js b/bench/parse-params.js index 439a372..54fd910 100644 --- a/bench/parse-params.js +++ b/bench/parse-params.js @@ -1,8 +1,8 @@ 'use strict' const parseParams = require('../lib/utils/parseParams') -const { Bench } = require('tinybench'); -const bench = new Bench(); +const { Bench } = require('tinybench') +const bench = new Bench() const simple = 'video/ogg' const complex = "'text/plain; filename*=utf-8''%c2%a3%20and%20%e2%82%ac%20rates'" diff --git a/deps/dicer/lib/dicer.d.ts b/deps/dicer/lib/dicer.d.ts index 3c5b896..88e8508 100644 --- a/deps/dicer/lib/dicer.d.ts +++ b/deps/dicer/lib/dicer.d.ts @@ -5,7 +5,7 @@ // TypeScript Version: 2.2 /// -import stream = require("stream"); +import stream = require('stream') // tslint:disable:unified-signatures @@ -20,145 +20,145 @@ import stream = require("stream"); * - on('trailer', (data: Buffer)) - Emitted when trailing data was found after the terminating boundary (as with the preamble, this can usually be ignored too). */ export class Dicer extends stream.Writable { - /** + /** * Creates and returns a new Dicer instance with the following valid config settings: * * @param config The configuration to use */ - constructor(config: Dicer.Config); - /** + constructor (config: Dicer.Config) + /** * Sets the boundary to use for parsing and performs some initialization needed for parsing. * You should only need to use this if you set headerFirst to true in the constructor and are parsing the boundary from the preamble header. * * @param boundary The boundary to use */ - setBoundary(boundary: string): void; - addListener(event: "finish", listener: () => void): this; - addListener(event: "part", listener: (stream: Dicer.PartStream) => void): this; - addListener(event: "preamble", listener: (stream: Dicer.PartStream) => void): this; - addListener(event: "trailer", listener: (data: Buffer) => void): this; - addListener(event: "close", listener: () => void): this; - addListener(event: "drain", listener: () => void): this; - addListener(event: "error", listener: (err: Error) => void): this; - addListener(event: "pipe", listener: (src: stream.Readable) => void): this; - addListener(event: "unpipe", listener: (src: stream.Readable) => void): this; - addListener(event: string, listener: (...args: any[]) => void): this; - on(event: "finish", listener: () => void): this; - on(event: "part", listener: (stream: Dicer.PartStream) => void): this; - on(event: "preamble", listener: (stream: Dicer.PartStream) => void): this; - on(event: "trailer", listener: (data: Buffer) => void): this; - on(event: "close", listener: () => void): this; - on(event: "drain", listener: () => void): this; - on(event: "error", listener: (err: Error) => void): this; - on(event: "pipe", listener: (src: stream.Readable) => void): this; - on(event: "unpipe", listener: (src: stream.Readable) => void): this; - on(event: string, listener: (...args: any[]) => void): this; - once(event: "finish", listener: () => void): this; - once(event: "part", listener: (stream: Dicer.PartStream) => void): this; - once(event: "preamble", listener: (stream: Dicer.PartStream) => void): this; - once(event: "trailer", listener: (data: Buffer) => void): this; - once(event: "close", listener: () => void): this; - once(event: "drain", listener: () => void): this; - once(event: "error", listener: (err: Error) => void): this; - once(event: "pipe", listener: (src: stream.Readable) => void): this; - once(event: "unpipe", listener: (src: stream.Readable) => void): this; - once(event: string, listener: (...args: any[]) => void): this; - prependListener(event: "finish", listener: () => void): this; - prependListener(event: "part", listener: (stream: Dicer.PartStream) => void): this; - prependListener(event: "preamble", listener: (stream: Dicer.PartStream) => void): this; - prependListener(event: "trailer", listener: (data: Buffer) => void): this; - prependListener(event: "close", listener: () => void): this; - prependListener(event: "drain", listener: () => void): this; - prependListener(event: "error", listener: (err: Error) => void): this; - prependListener(event: "pipe", listener: (src: stream.Readable) => void): this; - prependListener(event: "unpipe", listener: (src: stream.Readable) => void): this; - prependListener(event: string, listener: (...args: any[]) => void): this; - prependOnceListener(event: "finish", listener: () => void): this; - prependOnceListener(event: "part", listener: (stream: Dicer.PartStream) => void): this; - prependOnceListener(event: "preamble", listener: (stream: Dicer.PartStream) => void): this; - prependOnceListener(event: "trailer", listener: (data: Buffer) => void): this; - prependOnceListener(event: "close", listener: () => void): this; - prependOnceListener(event: "drain", listener: () => void): this; - prependOnceListener(event: "error", listener: (err: Error) => void): this; - prependOnceListener(event: "pipe", listener: (src: stream.Readable) => void): this; - prependOnceListener(event: "unpipe", listener: (src: stream.Readable) => void): this; - prependOnceListener(event: string, listener: (...args: any[]) => void): this; - removeListener(event: "finish", listener: () => void): this; - removeListener(event: "part", listener: (stream: Dicer.PartStream) => void): this; - removeListener(event: "preamble", listener: (stream: Dicer.PartStream) => void): this; - removeListener(event: "trailer", listener: (data: Buffer) => void): this; - removeListener(event: "close", listener: () => void): this; - removeListener(event: "drain", listener: () => void): this; - removeListener(event: "error", listener: (err: Error) => void): this; - removeListener(event: "pipe", listener: (src: stream.Readable) => void): this; - removeListener(event: "unpipe", listener: (src: stream.Readable) => void): this; - removeListener(event: string, listener: (...args: any[]) => void): this; + setBoundary (boundary: string): void + addListener (event: 'finish', listener: () => void): this + addListener (event: 'part', listener: (stream: Dicer.PartStream) => void): this + addListener (event: 'preamble', listener: (stream: Dicer.PartStream) => void): this + addListener (event: 'trailer', listener: (data: Buffer) => void): this + addListener (event: 'close', listener: () => void): this + addListener (event: 'drain', listener: () => void): this + addListener (event: 'error', listener: (err: Error) => void): this + addListener (event: 'pipe', listener: (src: stream.Readable) => void): this + addListener (event: 'unpipe', listener: (src: stream.Readable) => void): this + addListener (event: string, listener: (...args: any[]) => void): this + on (event: 'finish', listener: () => void): this + on (event: 'part', listener: (stream: Dicer.PartStream) => void): this + on (event: 'preamble', listener: (stream: Dicer.PartStream) => void): this + on (event: 'trailer', listener: (data: Buffer) => void): this + on (event: 'close', listener: () => void): this + on (event: 'drain', listener: () => void): this + on (event: 'error', listener: (err: Error) => void): this + on (event: 'pipe', listener: (src: stream.Readable) => void): this + on (event: 'unpipe', listener: (src: stream.Readable) => void): this + on (event: string, listener: (...args: any[]) => void): this + once (event: 'finish', listener: () => void): this + once (event: 'part', listener: (stream: Dicer.PartStream) => void): this + once (event: 'preamble', listener: (stream: Dicer.PartStream) => void): this + once (event: 'trailer', listener: (data: Buffer) => void): this + once (event: 'close', listener: () => void): this + once (event: 'drain', listener: () => void): this + once (event: 'error', listener: (err: Error) => void): this + once (event: 'pipe', listener: (src: stream.Readable) => void): this + once (event: 'unpipe', listener: (src: stream.Readable) => void): this + once (event: string, listener: (...args: any[]) => void): this + prependListener (event: 'finish', listener: () => void): this + prependListener (event: 'part', listener: (stream: Dicer.PartStream) => void): this + prependListener (event: 'preamble', listener: (stream: Dicer.PartStream) => void): this + prependListener (event: 'trailer', listener: (data: Buffer) => void): this + prependListener (event: 'close', listener: () => void): this + prependListener (event: 'drain', listener: () => void): this + prependListener (event: 'error', listener: (err: Error) => void): this + prependListener (event: 'pipe', listener: (src: stream.Readable) => void): this + prependListener (event: 'unpipe', listener: (src: stream.Readable) => void): this + prependListener (event: string, listener: (...args: any[]) => void): this + prependOnceListener (event: 'finish', listener: () => void): this + prependOnceListener (event: 'part', listener: (stream: Dicer.PartStream) => void): this + prependOnceListener (event: 'preamble', listener: (stream: Dicer.PartStream) => void): this + prependOnceListener (event: 'trailer', listener: (data: Buffer) => void): this + prependOnceListener (event: 'close', listener: () => void): this + prependOnceListener (event: 'drain', listener: () => void): this + prependOnceListener (event: 'error', listener: (err: Error) => void): this + prependOnceListener (event: 'pipe', listener: (src: stream.Readable) => void): this + prependOnceListener (event: 'unpipe', listener: (src: stream.Readable) => void): this + prependOnceListener (event: string, listener: (...args: any[]) => void): this + removeListener (event: 'finish', listener: () => void): this + removeListener (event: 'part', listener: (stream: Dicer.PartStream) => void): this + removeListener (event: 'preamble', listener: (stream: Dicer.PartStream) => void): this + removeListener (event: 'trailer', listener: (data: Buffer) => void): this + removeListener (event: 'close', listener: () => void): this + removeListener (event: 'drain', listener: () => void): this + removeListener (event: 'error', listener: (err: Error) => void): this + removeListener (event: 'pipe', listener: (src: stream.Readable) => void): this + removeListener (event: 'unpipe', listener: (src: stream.Readable) => void): this + removeListener (event: string, listener: (...args: any[]) => void): this } declare namespace Dicer { - interface Config { - /** + interface Config { + /** * This is the boundary used to detect the beginning of a new part. */ - boundary?: string | undefined; - /** + boundary?: string | undefined; + /** * If true, preamble header parsing will be performed first. */ - headerFirst?: boolean | undefined; - /** + headerFirst?: boolean | undefined; + /** * The maximum number of header key=>value pairs to parse Default: 2000 (same as node's http). */ - maxHeaderPairs?: number | undefined; - } + maxHeaderPairs?: number | undefined; + } - /** + /** * PartStream is a _ReadableStream_ * * PartStream (special) events: * - on('header', (header: object)) - An object containing the header for this particular part. Each property value is an array of one or more string values. */ - interface PartStream extends stream.Readable { - addListener(event: "header", listener: (header: object) => void): this; - addListener(event: "close", listener: () => void): this; - addListener(event: "data", listener: (chunk: Buffer | string) => void): this; - addListener(event: "end", listener: () => void): this; - addListener(event: "readable", listener: () => void): this; - addListener(event: "error", listener: (err: Error) => void): this; - addListener(event: string, listener: (...args: any[]) => void): this; - on(event: "header", listener: (header: object) => void): this; - on(event: "close", listener: () => void): this; - on(event: "data", listener: (chunk: Buffer | string) => void): this; - on(event: "end", listener: () => void): this; - on(event: "readable", listener: () => void): this; - on(event: "error", listener: (err: Error) => void): this; - on(event: string, listener: (...args: any[]) => void): this; - once(event: "header", listener: (header: object) => void): this; - once(event: "close", listener: () => void): this; - once(event: "data", listener: (chunk: Buffer | string) => void): this; - once(event: "end", listener: () => void): this; - once(event: "readable", listener: () => void): this; - once(event: "error", listener: (err: Error) => void): this; - once(event: string, listener: (...args: any[]) => void): this; - prependListener(event: "header", listener: (header: object) => void): this; - prependListener(event: "close", listener: () => void): this; - prependListener(event: "data", listener: (chunk: Buffer | string) => void): this; - prependListener(event: "end", listener: () => void): this; - prependListener(event: "readable", listener: () => void): this; - prependListener(event: "error", listener: (err: Error) => void): this; - prependListener(event: string, listener: (...args: any[]) => void): this; - prependOnceListener(event: "header", listener: (header: object) => void): this; - prependOnceListener(event: "close", listener: () => void): this; - prependOnceListener(event: "data", listener: (chunk: Buffer | string) => void): this; - prependOnceListener(event: "end", listener: () => void): this; - prependOnceListener(event: "readable", listener: () => void): this; - prependOnceListener(event: "error", listener: (err: Error) => void): this; - prependOnceListener(event: string, listener: (...args: any[]) => void): this; - removeListener(event: "header", listener: (header: object) => void): this; - removeListener(event: "close", listener: () => void): this; - removeListener(event: "data", listener: (chunk: Buffer | string) => void): this; - removeListener(event: "end", listener: () => void): this; - removeListener(event: "readable", listener: () => void): this; - removeListener(event: "error", listener: (err: Error) => void): this; - removeListener(event: string, listener: (...args: any[]) => void): this; - } -} \ No newline at end of file + interface PartStream extends stream.Readable { + addListener(event: 'header', listener: (header: object) => void): this; + addListener(event: 'close', listener: () => void): this; + addListener(event: 'data', listener: (chunk: Buffer | string) => void): this; + addListener(event: 'end', listener: () => void): this; + addListener(event: 'readable', listener: () => void): this; + addListener(event: 'error', listener: (err: Error) => void): this; + addListener(event: string, listener: (...args: any[]) => void): this; + on(event: 'header', listener: (header: object) => void): this; + on(event: 'close', listener: () => void): this; + on(event: 'data', listener: (chunk: Buffer | string) => void): this; + on(event: 'end', listener: () => void): this; + on(event: 'readable', listener: () => void): this; + on(event: 'error', listener: (err: Error) => void): this; + on(event: string, listener: (...args: any[]) => void): this; + once(event: 'header', listener: (header: object) => void): this; + once(event: 'close', listener: () => void): this; + once(event: 'data', listener: (chunk: Buffer | string) => void): this; + once(event: 'end', listener: () => void): this; + once(event: 'readable', listener: () => void): this; + once(event: 'error', listener: (err: Error) => void): this; + once(event: string, listener: (...args: any[]) => void): this; + prependListener(event: 'header', listener: (header: object) => void): this; + prependListener(event: 'close', listener: () => void): this; + prependListener(event: 'data', listener: (chunk: Buffer | string) => void): this; + prependListener(event: 'end', listener: () => void): this; + prependListener(event: 'readable', listener: () => void): this; + prependListener(event: 'error', listener: (err: Error) => void): this; + prependListener(event: string, listener: (...args: any[]) => void): this; + prependOnceListener(event: 'header', listener: (header: object) => void): this; + prependOnceListener(event: 'close', listener: () => void): this; + prependOnceListener(event: 'data', listener: (chunk: Buffer | string) => void): this; + prependOnceListener(event: 'end', listener: () => void): this; + prependOnceListener(event: 'readable', listener: () => void): this; + prependOnceListener(event: 'error', listener: (err: Error) => void): this; + prependOnceListener(event: string, listener: (...args: any[]) => void): this; + removeListener(event: 'header', listener: (header: object) => void): this; + removeListener(event: 'close', listener: () => void): this; + removeListener(event: 'data', listener: (chunk: Buffer | string) => void): this; + removeListener(event: 'end', listener: () => void): this; + removeListener(event: 'readable', listener: () => void): this; + removeListener(event: 'error', listener: (err: Error) => void): this; + removeListener(event: string, listener: (...args: any[]) => void): this; + } +} diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..89fd678 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,6 @@ +'use strict' + +module.exports = require('neostandard')({ + ignores: require('neostandard').resolveIgnoresFromGitignore(), + ts: true +}) diff --git a/lib/main.d.ts b/lib/main.d.ts index 4551863..7c6c513 100644 --- a/lib/main.d.ts +++ b/lib/main.d.ts @@ -3,6 +3,9 @@ // Igor Savin /// +import * as http from 'node:http' +import { Readable, Writable } from 'node:stream' + declare module 'stream' { interface Readable { /** @@ -14,35 +17,32 @@ declare module 'stream' { removeListener(event: 'limit', listener: () => void): this; } } +export { Dicer } from '../deps/dicer/lib/dicer' -import * as http from 'node:http'; -import { Readable, Writable } from 'node:stream'; -export { Dicer } from "../deps/dicer/lib/dicer"; - -export const Busboy: BusboyConstructor; -export default Busboy; +export const Busboy: BusboyConstructor +export default Busboy export interface BusboyConfig { - /** + /** * These are the HTTP headers of the incoming request, which are used by individual parsers. */ - headers: BusboyHeaders; - /** + headers: BusboyHeaders; + /** * `highWaterMark` to use for this Busboy instance. * @default WritableStream default. */ - highWaterMark?: number | undefined; - /** + highWaterMark?: number | undefined; + /** * highWaterMark to use for file streams. * @default ReadableStream default. */ - fileHwm?: number | undefined; - /** + fileHwm?: number | undefined; + /** * Default character set to use when one isn't defined. * @default 'utf8' */ - defCharset?: string | undefined; - /** + defCharset?: string | undefined; + /** * Detect if a Part is a file. * * By default a file is detected if contentType @@ -51,107 +51,137 @@ export interface BusboyConfig { * * Modify this to handle e.g. Blobs. */ - isPartAFile?: (fieldName: string | undefined, contentType: string | undefined, fileName: string | undefined) => boolean; - /** + isPartAFile?: (fieldName: string | undefined, contentType: string | undefined, fileName: string | undefined) => boolean; + /** * If paths in the multipart 'filename' field shall be preserved. * @default false */ - preservePath?: boolean | undefined; - /** + preservePath?: boolean | undefined; + /** * Various limits on incoming data. */ - limits?: + limits?: | { - /** + /** * Max field name size (in bytes) * @default 100 bytes */ - fieldNameSize?: number | undefined; - /** + fieldNameSize?: number | undefined; + /** * Max field value size (in bytes) * @default 1MB */ - fieldSize?: number | undefined; - /** + fieldSize?: number | undefined; + /** * Max number of non-file fields * @default Infinity */ - fields?: number | undefined; - /** + fields?: number | undefined; + /** * For multipart forms, the max file size (in bytes) * @default Infinity */ - fileSize?: number | undefined; - /** + fileSize?: number | undefined; + /** * For multipart forms, the max number of file fields * @default Infinity */ - files?: number | undefined; - /** + files?: number | undefined; + /** * For multipart forms, the max number of parts (fields + files) * @default Infinity */ - parts?: number | undefined; - /** + parts?: number | undefined; + /** * For multipart forms, the max number of header key=>value pairs to parse * @default 2000 */ - headerPairs?: number | undefined; + headerPairs?: number | undefined; - /** + /** * For multipart forms, the max size of a header part * @default 81920 */ - headerSize?: number | undefined; + headerSize?: number | undefined; } | undefined; } -export type BusboyHeaders = { 'content-type': string } & http.IncomingHttpHeaders; +export type BusboyHeaders = { 'content-type': string } & http.IncomingHttpHeaders export interface BusboyFileStream extends - Readable { + Readable { - truncated: boolean; + truncated: boolean; - /** + /** * The number of bytes that have been read so far. */ - bytesRead: number; + bytesRead: number; } -export interface Busboy extends Writable { - addListener(event: Event, listener: BusboyEvents[Event]): this; +export interface BusboyInstance extends Writable { + addListener( + event: Event, + listener: BusboyEvents[Event] + ): this; - addListener(event: string | symbol, listener: (...args: any[]) => void): this; + addListener(event: string | symbol, listener: (...args: any[]) => void): this; - on(event: Event, listener: BusboyEvents[Event]): this; + on( + event: Event, + listener: BusboyEvents[Event] + ): this; - on(event: string | symbol, listener: (...args: any[]) => void): this; + on(event: string | symbol, listener: (...args: any[]) => void): this; - once(event: Event, listener: BusboyEvents[Event]): this; + once( + event: Event, + listener: BusboyEvents[Event] + ): this; - once(event: string | symbol, listener: (...args: any[]) => void): this; + once(event: string | symbol, listener: (...args: any[]) => void): this; - removeListener(event: Event, listener: BusboyEvents[Event]): this; + removeListener( + event: Event, + listener: BusboyEvents[Event] + ): this; - removeListener(event: string | symbol, listener: (...args: any[]) => void): this; + removeListener( + event: string | symbol, + listener: (...args: any[]) => void + ): this; - off(event: Event, listener: BusboyEvents[Event]): this; + off( + event: Event, + listener: BusboyEvents[Event] + ): this; - off(event: string | symbol, listener: (...args: any[]) => void): this; + off(event: string | symbol, listener: (...args: any[]) => void): this; - prependListener(event: Event, listener: BusboyEvents[Event]): this; + prependListener( + event: Event, + listener: BusboyEvents[Event] + ): this; - prependListener(event: string | symbol, listener: (...args: any[]) => void): this; + prependListener( + event: string | symbol, + listener: (...args: any[]) => void + ): this; - prependOnceListener(event: Event, listener: BusboyEvents[Event]): this; + prependOnceListener( + event: Event, + listener: BusboyEvents[Event] + ): this; - prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this; + prependOnceListener( + event: string | symbol, + listener: (...args: any[]) => void + ): this; } export interface BusboyEvents { - /** + /** * Emitted for each new file form field found. * * * Note: if you listen for this event, you should always handle the `stream` no matter if you care about the @@ -165,43 +195,42 @@ export interface BusboyEvents { * @param listener.transferEncoding Contains the 'Content-Transfer-Encoding' value for the file stream. * @param listener.mimeType Contains the 'Content-Type' value for the file stream. */ - file: ( - fieldname: string, - stream: BusboyFileStream, - filename: string, - transferEncoding: string, - mimeType: string, - ) => void; - /** + file: ( + fieldname: string, + stream: BusboyFileStream, + filename: string, + transferEncoding: string, + mimeType: string, + ) => void; + /** * Emitted for each new non-file field found. */ - field: ( - fieldname: string, - value: string, - fieldnameTruncated: boolean, - valueTruncated: boolean, - transferEncoding: string, - mimeType: string, - ) => void; - finish: () => void; - /** + field: ( + fieldname: string, + value: string, + fieldnameTruncated: boolean, + valueTruncated: boolean, + transferEncoding: string, + mimeType: string, + ) => void; + finish: () => void; + /** * Emitted when specified `parts` limit has been reached. No more 'file' or 'field' events will be emitted. */ - partsLimit: () => void; - /** + partsLimit: () => void; + /** * Emitted when specified `files` limit has been reached. No more 'file' events will be emitted. */ - filesLimit: () => void; - /** + filesLimit: () => void; + /** * Emitted when specified `fields` limit has been reached. No more 'field' events will be emitted. */ - fieldsLimit: () => void; - error: (error: unknown) => void; + fieldsLimit: () => void; + error: (error: unknown) => void; } export interface BusboyConstructor { - (options: BusboyConfig): Busboy; + (options: BusboyConfig): BusboyInstance; - new(options: BusboyConfig): Busboy; + new(options: BusboyConfig): BusboyInstance; } - diff --git a/lib/utils/parseParams.js b/lib/utils/parseParams.js index d867f4d..09238aa 100644 --- a/lib/utils/parseParams.js +++ b/lib/utils/parseParams.js @@ -1,4 +1,3 @@ -/* eslint-disable object-property-newline */ 'use strict' const decodeText = require('./decodeText') @@ -6,103 +5,490 @@ const decodeText = require('./decodeText') const RE_ENCODED = /%[a-fA-F0-9][a-fA-F0-9]/g const EncodedLookup = { - '%00': '\x00', '%01': '\x01', '%02': '\x02', '%03': '\x03', '%04': '\x04', - '%05': '\x05', '%06': '\x06', '%07': '\x07', '%08': '\x08', '%09': '\x09', - '%0a': '\x0a', '%0A': '\x0a', '%0b': '\x0b', '%0B': '\x0b', '%0c': '\x0c', - '%0C': '\x0c', '%0d': '\x0d', '%0D': '\x0d', '%0e': '\x0e', '%0E': '\x0e', - '%0f': '\x0f', '%0F': '\x0f', '%10': '\x10', '%11': '\x11', '%12': '\x12', - '%13': '\x13', '%14': '\x14', '%15': '\x15', '%16': '\x16', '%17': '\x17', - '%18': '\x18', '%19': '\x19', '%1a': '\x1a', '%1A': '\x1a', '%1b': '\x1b', - '%1B': '\x1b', '%1c': '\x1c', '%1C': '\x1c', '%1d': '\x1d', '%1D': '\x1d', - '%1e': '\x1e', '%1E': '\x1e', '%1f': '\x1f', '%1F': '\x1f', '%20': '\x20', - '%21': '\x21', '%22': '\x22', '%23': '\x23', '%24': '\x24', '%25': '\x25', - '%26': '\x26', '%27': '\x27', '%28': '\x28', '%29': '\x29', '%2a': '\x2a', - '%2A': '\x2a', '%2b': '\x2b', '%2B': '\x2b', '%2c': '\x2c', '%2C': '\x2c', - '%2d': '\x2d', '%2D': '\x2d', '%2e': '\x2e', '%2E': '\x2e', '%2f': '\x2f', - '%2F': '\x2f', '%30': '\x30', '%31': '\x31', '%32': '\x32', '%33': '\x33', - '%34': '\x34', '%35': '\x35', '%36': '\x36', '%37': '\x37', '%38': '\x38', - '%39': '\x39', '%3a': '\x3a', '%3A': '\x3a', '%3b': '\x3b', '%3B': '\x3b', - '%3c': '\x3c', '%3C': '\x3c', '%3d': '\x3d', '%3D': '\x3d', '%3e': '\x3e', - '%3E': '\x3e', '%3f': '\x3f', '%3F': '\x3f', '%40': '\x40', '%41': '\x41', - '%42': '\x42', '%43': '\x43', '%44': '\x44', '%45': '\x45', '%46': '\x46', - '%47': '\x47', '%48': '\x48', '%49': '\x49', '%4a': '\x4a', '%4A': '\x4a', - '%4b': '\x4b', '%4B': '\x4b', '%4c': '\x4c', '%4C': '\x4c', '%4d': '\x4d', - '%4D': '\x4d', '%4e': '\x4e', '%4E': '\x4e', '%4f': '\x4f', '%4F': '\x4f', - '%50': '\x50', '%51': '\x51', '%52': '\x52', '%53': '\x53', '%54': '\x54', - '%55': '\x55', '%56': '\x56', '%57': '\x57', '%58': '\x58', '%59': '\x59', - '%5a': '\x5a', '%5A': '\x5a', '%5b': '\x5b', '%5B': '\x5b', '%5c': '\x5c', - '%5C': '\x5c', '%5d': '\x5d', '%5D': '\x5d', '%5e': '\x5e', '%5E': '\x5e', - '%5f': '\x5f', '%5F': '\x5f', '%60': '\x60', '%61': '\x61', '%62': '\x62', - '%63': '\x63', '%64': '\x64', '%65': '\x65', '%66': '\x66', '%67': '\x67', - '%68': '\x68', '%69': '\x69', '%6a': '\x6a', '%6A': '\x6a', '%6b': '\x6b', - '%6B': '\x6b', '%6c': '\x6c', '%6C': '\x6c', '%6d': '\x6d', '%6D': '\x6d', - '%6e': '\x6e', '%6E': '\x6e', '%6f': '\x6f', '%6F': '\x6f', '%70': '\x70', - '%71': '\x71', '%72': '\x72', '%73': '\x73', '%74': '\x74', '%75': '\x75', - '%76': '\x76', '%77': '\x77', '%78': '\x78', '%79': '\x79', '%7a': '\x7a', - '%7A': '\x7a', '%7b': '\x7b', '%7B': '\x7b', '%7c': '\x7c', '%7C': '\x7c', - '%7d': '\x7d', '%7D': '\x7d', '%7e': '\x7e', '%7E': '\x7e', '%7f': '\x7f', - '%7F': '\x7f', '%80': '\x80', '%81': '\x81', '%82': '\x82', '%83': '\x83', - '%84': '\x84', '%85': '\x85', '%86': '\x86', '%87': '\x87', '%88': '\x88', - '%89': '\x89', '%8a': '\x8a', '%8A': '\x8a', '%8b': '\x8b', '%8B': '\x8b', - '%8c': '\x8c', '%8C': '\x8c', '%8d': '\x8d', '%8D': '\x8d', '%8e': '\x8e', - '%8E': '\x8e', '%8f': '\x8f', '%8F': '\x8f', '%90': '\x90', '%91': '\x91', - '%92': '\x92', '%93': '\x93', '%94': '\x94', '%95': '\x95', '%96': '\x96', - '%97': '\x97', '%98': '\x98', '%99': '\x99', '%9a': '\x9a', '%9A': '\x9a', - '%9b': '\x9b', '%9B': '\x9b', '%9c': '\x9c', '%9C': '\x9c', '%9d': '\x9d', - '%9D': '\x9d', '%9e': '\x9e', '%9E': '\x9e', '%9f': '\x9f', '%9F': '\x9f', - '%a0': '\xa0', '%A0': '\xa0', '%a1': '\xa1', '%A1': '\xa1', '%a2': '\xa2', - '%A2': '\xa2', '%a3': '\xa3', '%A3': '\xa3', '%a4': '\xa4', '%A4': '\xa4', - '%a5': '\xa5', '%A5': '\xa5', '%a6': '\xa6', '%A6': '\xa6', '%a7': '\xa7', - '%A7': '\xa7', '%a8': '\xa8', '%A8': '\xa8', '%a9': '\xa9', '%A9': '\xa9', - '%aa': '\xaa', '%Aa': '\xaa', '%aA': '\xaa', '%AA': '\xaa', '%ab': '\xab', - '%Ab': '\xab', '%aB': '\xab', '%AB': '\xab', '%ac': '\xac', '%Ac': '\xac', - '%aC': '\xac', '%AC': '\xac', '%ad': '\xad', '%Ad': '\xad', '%aD': '\xad', - '%AD': '\xad', '%ae': '\xae', '%Ae': '\xae', '%aE': '\xae', '%AE': '\xae', - '%af': '\xaf', '%Af': '\xaf', '%aF': '\xaf', '%AF': '\xaf', '%b0': '\xb0', - '%B0': '\xb0', '%b1': '\xb1', '%B1': '\xb1', '%b2': '\xb2', '%B2': '\xb2', - '%b3': '\xb3', '%B3': '\xb3', '%b4': '\xb4', '%B4': '\xb4', '%b5': '\xb5', - '%B5': '\xb5', '%b6': '\xb6', '%B6': '\xb6', '%b7': '\xb7', '%B7': '\xb7', - '%b8': '\xb8', '%B8': '\xb8', '%b9': '\xb9', '%B9': '\xb9', '%ba': '\xba', - '%Ba': '\xba', '%bA': '\xba', '%BA': '\xba', '%bb': '\xbb', '%Bb': '\xbb', - '%bB': '\xbb', '%BB': '\xbb', '%bc': '\xbc', '%Bc': '\xbc', '%bC': '\xbc', - '%BC': '\xbc', '%bd': '\xbd', '%Bd': '\xbd', '%bD': '\xbd', '%BD': '\xbd', - '%be': '\xbe', '%Be': '\xbe', '%bE': '\xbe', '%BE': '\xbe', '%bf': '\xbf', - '%Bf': '\xbf', '%bF': '\xbf', '%BF': '\xbf', '%c0': '\xc0', '%C0': '\xc0', - '%c1': '\xc1', '%C1': '\xc1', '%c2': '\xc2', '%C2': '\xc2', '%c3': '\xc3', - '%C3': '\xc3', '%c4': '\xc4', '%C4': '\xc4', '%c5': '\xc5', '%C5': '\xc5', - '%c6': '\xc6', '%C6': '\xc6', '%c7': '\xc7', '%C7': '\xc7', '%c8': '\xc8', - '%C8': '\xc8', '%c9': '\xc9', '%C9': '\xc9', '%ca': '\xca', '%Ca': '\xca', - '%cA': '\xca', '%CA': '\xca', '%cb': '\xcb', '%Cb': '\xcb', '%cB': '\xcb', - '%CB': '\xcb', '%cc': '\xcc', '%Cc': '\xcc', '%cC': '\xcc', '%CC': '\xcc', - '%cd': '\xcd', '%Cd': '\xcd', '%cD': '\xcd', '%CD': '\xcd', '%ce': '\xce', - '%Ce': '\xce', '%cE': '\xce', '%CE': '\xce', '%cf': '\xcf', '%Cf': '\xcf', - '%cF': '\xcf', '%CF': '\xcf', '%d0': '\xd0', '%D0': '\xd0', '%d1': '\xd1', - '%D1': '\xd1', '%d2': '\xd2', '%D2': '\xd2', '%d3': '\xd3', '%D3': '\xd3', - '%d4': '\xd4', '%D4': '\xd4', '%d5': '\xd5', '%D5': '\xd5', '%d6': '\xd6', - '%D6': '\xd6', '%d7': '\xd7', '%D7': '\xd7', '%d8': '\xd8', '%D8': '\xd8', - '%d9': '\xd9', '%D9': '\xd9', '%da': '\xda', '%Da': '\xda', '%dA': '\xda', - '%DA': '\xda', '%db': '\xdb', '%Db': '\xdb', '%dB': '\xdb', '%DB': '\xdb', - '%dc': '\xdc', '%Dc': '\xdc', '%dC': '\xdc', '%DC': '\xdc', '%dd': '\xdd', - '%Dd': '\xdd', '%dD': '\xdd', '%DD': '\xdd', '%de': '\xde', '%De': '\xde', - '%dE': '\xde', '%DE': '\xde', '%df': '\xdf', '%Df': '\xdf', '%dF': '\xdf', - '%DF': '\xdf', '%e0': '\xe0', '%E0': '\xe0', '%e1': '\xe1', '%E1': '\xe1', - '%e2': '\xe2', '%E2': '\xe2', '%e3': '\xe3', '%E3': '\xe3', '%e4': '\xe4', - '%E4': '\xe4', '%e5': '\xe5', '%E5': '\xe5', '%e6': '\xe6', '%E6': '\xe6', - '%e7': '\xe7', '%E7': '\xe7', '%e8': '\xe8', '%E8': '\xe8', '%e9': '\xe9', - '%E9': '\xe9', '%ea': '\xea', '%Ea': '\xea', '%eA': '\xea', '%EA': '\xea', - '%eb': '\xeb', '%Eb': '\xeb', '%eB': '\xeb', '%EB': '\xeb', '%ec': '\xec', - '%Ec': '\xec', '%eC': '\xec', '%EC': '\xec', '%ed': '\xed', '%Ed': '\xed', - '%eD': '\xed', '%ED': '\xed', '%ee': '\xee', '%Ee': '\xee', '%eE': '\xee', - '%EE': '\xee', '%ef': '\xef', '%Ef': '\xef', '%eF': '\xef', '%EF': '\xef', - '%f0': '\xf0', '%F0': '\xf0', '%f1': '\xf1', '%F1': '\xf1', '%f2': '\xf2', - '%F2': '\xf2', '%f3': '\xf3', '%F3': '\xf3', '%f4': '\xf4', '%F4': '\xf4', - '%f5': '\xf5', '%F5': '\xf5', '%f6': '\xf6', '%F6': '\xf6', '%f7': '\xf7', - '%F7': '\xf7', '%f8': '\xf8', '%F8': '\xf8', '%f9': '\xf9', '%F9': '\xf9', - '%fa': '\xfa', '%Fa': '\xfa', '%fA': '\xfa', '%FA': '\xfa', '%fb': '\xfb', - '%Fb': '\xfb', '%fB': '\xfb', '%FB': '\xfb', '%fc': '\xfc', '%Fc': '\xfc', - '%fC': '\xfc', '%FC': '\xfc', '%fd': '\xfd', '%Fd': '\xfd', '%fD': '\xfd', - '%FD': '\xfd', '%fe': '\xfe', '%Fe': '\xfe', '%fE': '\xfe', '%FE': '\xfe', - '%ff': '\xff', '%Ff': '\xff', '%fF': '\xff', '%FF': '\xff' + '%00': '\x00', + '%01': '\x01', + '%02': '\x02', + '%03': '\x03', + '%04': '\x04', + '%05': '\x05', + '%06': '\x06', + '%07': '\x07', + '%08': '\x08', + '%09': '\x09', + '%0a': '\x0a', + '%0A': '\x0a', + '%0b': '\x0b', + '%0B': '\x0b', + '%0c': '\x0c', + '%0C': '\x0c', + '%0d': '\x0d', + '%0D': '\x0d', + '%0e': '\x0e', + '%0E': '\x0e', + '%0f': '\x0f', + '%0F': '\x0f', + '%10': '\x10', + '%11': '\x11', + '%12': '\x12', + '%13': '\x13', + '%14': '\x14', + '%15': '\x15', + '%16': '\x16', + '%17': '\x17', + '%18': '\x18', + '%19': '\x19', + '%1a': '\x1a', + '%1A': '\x1a', + '%1b': '\x1b', + '%1B': '\x1b', + '%1c': '\x1c', + '%1C': '\x1c', + '%1d': '\x1d', + '%1D': '\x1d', + '%1e': '\x1e', + '%1E': '\x1e', + '%1f': '\x1f', + '%1F': '\x1f', + '%20': '\x20', + '%21': '\x21', + '%22': '\x22', + '%23': '\x23', + '%24': '\x24', + '%25': '\x25', + '%26': '\x26', + '%27': '\x27', + '%28': '\x28', + '%29': '\x29', + '%2a': '\x2a', + '%2A': '\x2a', + '%2b': '\x2b', + '%2B': '\x2b', + '%2c': '\x2c', + '%2C': '\x2c', + '%2d': '\x2d', + '%2D': '\x2d', + '%2e': '\x2e', + '%2E': '\x2e', + '%2f': '\x2f', + '%2F': '\x2f', + '%30': '\x30', + '%31': '\x31', + '%32': '\x32', + '%33': '\x33', + '%34': '\x34', + '%35': '\x35', + '%36': '\x36', + '%37': '\x37', + '%38': '\x38', + '%39': '\x39', + '%3a': '\x3a', + '%3A': '\x3a', + '%3b': '\x3b', + '%3B': '\x3b', + '%3c': '\x3c', + '%3C': '\x3c', + '%3d': '\x3d', + '%3D': '\x3d', + '%3e': '\x3e', + '%3E': '\x3e', + '%3f': '\x3f', + '%3F': '\x3f', + '%40': '\x40', + '%41': '\x41', + '%42': '\x42', + '%43': '\x43', + '%44': '\x44', + '%45': '\x45', + '%46': '\x46', + '%47': '\x47', + '%48': '\x48', + '%49': '\x49', + '%4a': '\x4a', + '%4A': '\x4a', + '%4b': '\x4b', + '%4B': '\x4b', + '%4c': '\x4c', + '%4C': '\x4c', + '%4d': '\x4d', + '%4D': '\x4d', + '%4e': '\x4e', + '%4E': '\x4e', + '%4f': '\x4f', + '%4F': '\x4f', + '%50': '\x50', + '%51': '\x51', + '%52': '\x52', + '%53': '\x53', + '%54': '\x54', + '%55': '\x55', + '%56': '\x56', + '%57': '\x57', + '%58': '\x58', + '%59': '\x59', + '%5a': '\x5a', + '%5A': '\x5a', + '%5b': '\x5b', + '%5B': '\x5b', + '%5c': '\x5c', + '%5C': '\x5c', + '%5d': '\x5d', + '%5D': '\x5d', + '%5e': '\x5e', + '%5E': '\x5e', + '%5f': '\x5f', + '%5F': '\x5f', + '%60': '\x60', + '%61': '\x61', + '%62': '\x62', + '%63': '\x63', + '%64': '\x64', + '%65': '\x65', + '%66': '\x66', + '%67': '\x67', + '%68': '\x68', + '%69': '\x69', + '%6a': '\x6a', + '%6A': '\x6a', + '%6b': '\x6b', + '%6B': '\x6b', + '%6c': '\x6c', + '%6C': '\x6c', + '%6d': '\x6d', + '%6D': '\x6d', + '%6e': '\x6e', + '%6E': '\x6e', + '%6f': '\x6f', + '%6F': '\x6f', + '%70': '\x70', + '%71': '\x71', + '%72': '\x72', + '%73': '\x73', + '%74': '\x74', + '%75': '\x75', + '%76': '\x76', + '%77': '\x77', + '%78': '\x78', + '%79': '\x79', + '%7a': '\x7a', + '%7A': '\x7a', + '%7b': '\x7b', + '%7B': '\x7b', + '%7c': '\x7c', + '%7C': '\x7c', + '%7d': '\x7d', + '%7D': '\x7d', + '%7e': '\x7e', + '%7E': '\x7e', + '%7f': '\x7f', + '%7F': '\x7f', + '%80': '\x80', + '%81': '\x81', + '%82': '\x82', + '%83': '\x83', + '%84': '\x84', + '%85': '\x85', + '%86': '\x86', + '%87': '\x87', + '%88': '\x88', + '%89': '\x89', + '%8a': '\x8a', + '%8A': '\x8a', + '%8b': '\x8b', + '%8B': '\x8b', + '%8c': '\x8c', + '%8C': '\x8c', + '%8d': '\x8d', + '%8D': '\x8d', + '%8e': '\x8e', + '%8E': '\x8e', + '%8f': '\x8f', + '%8F': '\x8f', + '%90': '\x90', + '%91': '\x91', + '%92': '\x92', + '%93': '\x93', + '%94': '\x94', + '%95': '\x95', + '%96': '\x96', + '%97': '\x97', + '%98': '\x98', + '%99': '\x99', + '%9a': '\x9a', + '%9A': '\x9a', + '%9b': '\x9b', + '%9B': '\x9b', + '%9c': '\x9c', + '%9C': '\x9c', + '%9d': '\x9d', + '%9D': '\x9d', + '%9e': '\x9e', + '%9E': '\x9e', + '%9f': '\x9f', + '%9F': '\x9f', + '%a0': '\xa0', + '%A0': '\xa0', + '%a1': '\xa1', + '%A1': '\xa1', + '%a2': '\xa2', + '%A2': '\xa2', + '%a3': '\xa3', + '%A3': '\xa3', + '%a4': '\xa4', + '%A4': '\xa4', + '%a5': '\xa5', + '%A5': '\xa5', + '%a6': '\xa6', + '%A6': '\xa6', + '%a7': '\xa7', + '%A7': '\xa7', + '%a8': '\xa8', + '%A8': '\xa8', + '%a9': '\xa9', + '%A9': '\xa9', + '%aa': '\xaa', + '%Aa': '\xaa', + '%aA': '\xaa', + '%AA': '\xaa', + '%ab': '\xab', + '%Ab': '\xab', + '%aB': '\xab', + '%AB': '\xab', + '%ac': '\xac', + '%Ac': '\xac', + '%aC': '\xac', + '%AC': '\xac', + '%ad': '\xad', + '%Ad': '\xad', + '%aD': '\xad', + '%AD': '\xad', + '%ae': '\xae', + '%Ae': '\xae', + '%aE': '\xae', + '%AE': '\xae', + '%af': '\xaf', + '%Af': '\xaf', + '%aF': '\xaf', + '%AF': '\xaf', + '%b0': '\xb0', + '%B0': '\xb0', + '%b1': '\xb1', + '%B1': '\xb1', + '%b2': '\xb2', + '%B2': '\xb2', + '%b3': '\xb3', + '%B3': '\xb3', + '%b4': '\xb4', + '%B4': '\xb4', + '%b5': '\xb5', + '%B5': '\xb5', + '%b6': '\xb6', + '%B6': '\xb6', + '%b7': '\xb7', + '%B7': '\xb7', + '%b8': '\xb8', + '%B8': '\xb8', + '%b9': '\xb9', + '%B9': '\xb9', + '%ba': '\xba', + '%Ba': '\xba', + '%bA': '\xba', + '%BA': '\xba', + '%bb': '\xbb', + '%Bb': '\xbb', + '%bB': '\xbb', + '%BB': '\xbb', + '%bc': '\xbc', + '%Bc': '\xbc', + '%bC': '\xbc', + '%BC': '\xbc', + '%bd': '\xbd', + '%Bd': '\xbd', + '%bD': '\xbd', + '%BD': '\xbd', + '%be': '\xbe', + '%Be': '\xbe', + '%bE': '\xbe', + '%BE': '\xbe', + '%bf': '\xbf', + '%Bf': '\xbf', + '%bF': '\xbf', + '%BF': '\xbf', + '%c0': '\xc0', + '%C0': '\xc0', + '%c1': '\xc1', + '%C1': '\xc1', + '%c2': '\xc2', + '%C2': '\xc2', + '%c3': '\xc3', + '%C3': '\xc3', + '%c4': '\xc4', + '%C4': '\xc4', + '%c5': '\xc5', + '%C5': '\xc5', + '%c6': '\xc6', + '%C6': '\xc6', + '%c7': '\xc7', + '%C7': '\xc7', + '%c8': '\xc8', + '%C8': '\xc8', + '%c9': '\xc9', + '%C9': '\xc9', + '%ca': '\xca', + '%Ca': '\xca', + '%cA': '\xca', + '%CA': '\xca', + '%cb': '\xcb', + '%Cb': '\xcb', + '%cB': '\xcb', + '%CB': '\xcb', + '%cc': '\xcc', + '%Cc': '\xcc', + '%cC': '\xcc', + '%CC': '\xcc', + '%cd': '\xcd', + '%Cd': '\xcd', + '%cD': '\xcd', + '%CD': '\xcd', + '%ce': '\xce', + '%Ce': '\xce', + '%cE': '\xce', + '%CE': '\xce', + '%cf': '\xcf', + '%Cf': '\xcf', + '%cF': '\xcf', + '%CF': '\xcf', + '%d0': '\xd0', + '%D0': '\xd0', + '%d1': '\xd1', + '%D1': '\xd1', + '%d2': '\xd2', + '%D2': '\xd2', + '%d3': '\xd3', + '%D3': '\xd3', + '%d4': '\xd4', + '%D4': '\xd4', + '%d5': '\xd5', + '%D5': '\xd5', + '%d6': '\xd6', + '%D6': '\xd6', + '%d7': '\xd7', + '%D7': '\xd7', + '%d8': '\xd8', + '%D8': '\xd8', + '%d9': '\xd9', + '%D9': '\xd9', + '%da': '\xda', + '%Da': '\xda', + '%dA': '\xda', + '%DA': '\xda', + '%db': '\xdb', + '%Db': '\xdb', + '%dB': '\xdb', + '%DB': '\xdb', + '%dc': '\xdc', + '%Dc': '\xdc', + '%dC': '\xdc', + '%DC': '\xdc', + '%dd': '\xdd', + '%Dd': '\xdd', + '%dD': '\xdd', + '%DD': '\xdd', + '%de': '\xde', + '%De': '\xde', + '%dE': '\xde', + '%DE': '\xde', + '%df': '\xdf', + '%Df': '\xdf', + '%dF': '\xdf', + '%DF': '\xdf', + '%e0': '\xe0', + '%E0': '\xe0', + '%e1': '\xe1', + '%E1': '\xe1', + '%e2': '\xe2', + '%E2': '\xe2', + '%e3': '\xe3', + '%E3': '\xe3', + '%e4': '\xe4', + '%E4': '\xe4', + '%e5': '\xe5', + '%E5': '\xe5', + '%e6': '\xe6', + '%E6': '\xe6', + '%e7': '\xe7', + '%E7': '\xe7', + '%e8': '\xe8', + '%E8': '\xe8', + '%e9': '\xe9', + '%E9': '\xe9', + '%ea': '\xea', + '%Ea': '\xea', + '%eA': '\xea', + '%EA': '\xea', + '%eb': '\xeb', + '%Eb': '\xeb', + '%eB': '\xeb', + '%EB': '\xeb', + '%ec': '\xec', + '%Ec': '\xec', + '%eC': '\xec', + '%EC': '\xec', + '%ed': '\xed', + '%Ed': '\xed', + '%eD': '\xed', + '%ED': '\xed', + '%ee': '\xee', + '%Ee': '\xee', + '%eE': '\xee', + '%EE': '\xee', + '%ef': '\xef', + '%Ef': '\xef', + '%eF': '\xef', + '%EF': '\xef', + '%f0': '\xf0', + '%F0': '\xf0', + '%f1': '\xf1', + '%F1': '\xf1', + '%f2': '\xf2', + '%F2': '\xf2', + '%f3': '\xf3', + '%F3': '\xf3', + '%f4': '\xf4', + '%F4': '\xf4', + '%f5': '\xf5', + '%F5': '\xf5', + '%f6': '\xf6', + '%F6': '\xf6', + '%f7': '\xf7', + '%F7': '\xf7', + '%f8': '\xf8', + '%F8': '\xf8', + '%f9': '\xf9', + '%F9': '\xf9', + '%fa': '\xfa', + '%Fa': '\xfa', + '%fA': '\xfa', + '%FA': '\xfa', + '%fb': '\xfb', + '%Fb': '\xfb', + '%fB': '\xfb', + '%FB': '\xfb', + '%fc': '\xfc', + '%Fc': '\xfc', + '%fC': '\xfc', + '%FC': '\xfc', + '%fd': '\xfd', + '%Fd': '\xfd', + '%fD': '\xfd', + '%FD': '\xfd', + '%fe': '\xfe', + '%Fe': '\xfe', + '%fE': '\xfe', + '%FE': '\xfe', + '%ff': '\xff', + '%Ff': '\xff', + '%fF': '\xff', + '%FF': '\xff' } function encodedReplacer (match) { diff --git a/package.json b/package.json index 6b0c871..1078b44 100644 --- a/package.json +++ b/package.json @@ -23,9 +23,8 @@ "bench:busboy": "cd benchmarks && npm install && npm run benchmark-fastify", "bench:dicer": "node bench/dicer/dicer-bench-multipart-parser.js", "coveralls": "nyc report --reporter=lcov", - "lint": "npm run lint:standard", - "lint:fix": "standard --fix", - "lint:standard": "standard --verbose | snazzy", + "lint": "eslint", + "lint:fix": "eslint --fix", "test:unit": "c8 --statements 98 --branches 97 --functions 96 --lines 98 node --test", "test:types": "tsd", "test": "npm run test:unit && npm run test:types" @@ -36,7 +35,8 @@ "c8": "^11.0.0", "photofinish": "^1.8.0", "snazzy": "^9.0.0", - "standard": "^17.1.0", + "eslint": "^9.39.0", + "neostandard": "^0.12.0", "tinybench": "^6.0.0", "tsd": "^0.33.0", "tslib": "^2.8.1", diff --git a/test-types/dicer.test-d.ts b/test-types/dicer.test-d.ts index c4f38ee..b7f2005 100644 --- a/test-types/dicer.test-d.ts +++ b/test-types/dicer.test-d.ts @@ -1,81 +1,82 @@ -import { Dicer } from "../lib/main"; -import * as fs from "fs"; -import * as stream from "stream"; +/* eslint-disable @typescript-eslint/no-unused-vars */ +import { Dicer } from '../lib/main' +import * as fs from 'fs' +import * as stream from 'stream' -function testDicerSyntax() { - const opts: Dicer.Config = { - boundary: "testing", - }; - const dicer = new Dicer(opts); - const opts2: Dicer.Config = { - headerFirst: true, - maxHeaderPairs: 1, - }; - const opts3: Dicer.Config = { - boundary: "more-testing", - headerFirst: false, - maxHeaderPairs: 8, - }; - dicer.setBoundary("new-testing-boundary"); - dicer.on("part", handleDicerPartStream); - dicer.on("finish", () => { - console.log("dicer parsing finished"); - }); - dicer.on("preamble", part => { - console.log("dicer preamble to new part"); - }); - dicer.on("trailer", data => { - console.log(`dicer trailing data found: ${data.length} bytes`); - }); - dicer.on("close", () => { - console.log("dicer close"); - }); - dicer.on("drain", () => { - console.log("dicer drain"); - }); - dicer.on("error", err => { - console.error(`dicer error: ${err.message || JSON.stringify(err)}`); - }); - dicer.on("finish", () => { - console.log("dicer finish"); - }); - dicer.on("pipe", (src: stream.Readable) => { - console.log("dicer pipe"); - }); - dicer.on("unpipe", (src: stream.Readable) => { - console.log("dicer unpipe"); - }); - const inputFileStream = fs.createReadStream("in-test-file.txt"); - inputFileStream.pipe(dicer); +function testDicerSyntax () { + const opts: Dicer.Config = { + boundary: 'testing', + } + const dicer = new Dicer(opts) + const opts2: Dicer.Config = { + headerFirst: true, + maxHeaderPairs: 1, + } + const opts3: Dicer.Config = { + boundary: 'more-testing', + headerFirst: false, + maxHeaderPairs: 8, + } + dicer.setBoundary('new-testing-boundary') + dicer.on('part', handleDicerPartStream) + dicer.on('finish', () => { + console.log('dicer parsing finished') + }) + dicer.on('preamble', part => { + console.log('dicer preamble to new part') + }) + dicer.on('trailer', data => { + console.log(`dicer trailing data found: ${data.length} bytes`) + }) + dicer.on('close', () => { + console.log('dicer close') + }) + dicer.on('drain', () => { + console.log('dicer drain') + }) + dicer.on('error', err => { + console.error(`dicer error: ${err.message || JSON.stringify(err)}`) + }) + dicer.on('finish', () => { + console.log('dicer finish') + }) + dicer.on('pipe', (src: stream.Readable) => { + console.log('dicer pipe') + }) + dicer.on('unpipe', (src: stream.Readable) => { + console.log('dicer unpipe') + }) + const inputFileStream = fs.createReadStream('in-test-file.txt') + inputFileStream.pipe(dicer) } /** * Handle a part found by a Dicer parser * * @param part Part found */ -function handleDicerPartStream(part: Dicer.PartStream) { - console.log("dicer part found"); - const outputFileStream = fs.createWriteStream("out-test-file.txt"); - part.on("readable", () => { - console.log("part readable"); - }); - part.on("header", header => { - console.log(`part header found:\n${JSON.stringify(header)}`); - }); - part.on("data", () => { - console.log("part data"); - }); - part.on("finish", () => { - console.log("part finished"); - }); - part.on("error", err => { - console.error(`part error: ${err.message || JSON.stringify(err)}`); - }); - part.on("end", () => { - console.log("part ended"); - }); - part.on("close", () => { - console.log("part closed"); - }); - part.pipe(outputFileStream); +function handleDicerPartStream (part: Dicer.PartStream) { + console.log('dicer part found') + const outputFileStream = fs.createWriteStream('out-test-file.txt') + part.on('readable', () => { + console.log('part readable') + }) + part.on('header', header => { + console.log(`part header found:\n${JSON.stringify(header)}`) + }) + part.on('data', () => { + console.log('part data') + }) + part.on('finish', () => { + console.log('part finished') + }) + part.on('error', err => { + console.error(`part error: ${err.message || JSON.stringify(err)}`) + }) + part.on('end', () => { + console.log('part ended') + }) + part.on('close', () => { + console.log('part closed') + }) + part.pipe(outputFileStream) } diff --git a/test-types/main.test-d.ts b/test-types/main.test-d.ts index 0125c9b..c705220 100644 --- a/test-types/main.test-d.ts +++ b/test-types/main.test-d.ts @@ -1,241 +1,236 @@ -import BusboyDefault, { BusboyConstructor, BusboyConfig, BusboyHeaders, Busboy, BusboyEvents, BusboyFileStream } from '..'; -import {expectError, expectType} from "tsd"; -import BusboyESM from ".."; +/* eslint-disable import-x/no-duplicates */ +/* eslint-disable no-new */ +import BusboyDefault, { Busboy, BusboyFileStream } from '..' +import { expectError, expectType } from 'tsd' +import BusboyESM from '..' -// test type exports -type Constructor = BusboyConstructor; -type Config = BusboyConfig; -type Headers = BusboyHeaders; -type Events = BusboyEvents; -type BB = Busboy; +expectType>(new BusboyESM({ headers: { 'content-type': 'foo' } })) +expectType>(new Busboy({ headers: { 'content-type': 'foo' } })) -expectType(new BusboyESM({ headers: { 'content-type': 'foo' } })); -expectType(new Busboy({ headers: { 'content-type': 'foo' } })); - -expectError(new BusboyDefault({})); -const busboy = BusboyDefault({ headers: { 'content-type': 'foo' } }); // $ExpectType Busboy -new BusboyDefault({ headers: { 'content-type': 'foo' } }); // $ExpectType Busboy -new BusboyDefault({ headers: { 'content-type': 'foo' }, highWaterMark: 1000 }); // $ExpectType Busboy -new BusboyDefault({ headers: { 'content-type': 'foo' }, fileHwm: 1000 }); // $ExpectType Busboy -new BusboyDefault({ headers: { 'content-type': 'foo' }, defCharset: 'utf8' }); // $ExpectType Busboy -new BusboyDefault({ headers: { 'content-type': 'foo' }, preservePath: true }); // $ExpectType Busboy -new BusboyDefault({ headers: { 'content-type': 'foo' }, limits: { fieldNameSize: 200 } }); // $ExpectType Busboy -new BusboyDefault({ headers: { 'content-type': 'foo' }, limits: { fieldSize: 200 } }); // $ExpectType Busboy -new BusboyDefault({ headers: { 'content-type': 'foo' }, limits: { fields: 200 } }); // $ExpectType Busboy -new BusboyDefault({ headers: { 'content-type': 'foo' }, limits: { fileSize: 200 } }); // $ExpectType Busboy -new BusboyDefault({ headers: { 'content-type': 'foo' }, limits: { files: 200 } }); // $ExpectType Busboy -new BusboyDefault({ headers: { 'content-type': 'foo' }, limits: { parts: 200 } }); // $ExpectType Busboy -new BusboyDefault({ headers: { 'content-type': 'foo' }, limits: { headerPairs: 200 } }); // $ExpectType Busboy -new BusboyDefault({ headers: { 'content-type': 'foo' }, limits: { headerSize: 200 } }); // $ExpectType Busboy -new BusboyDefault({ headers: { 'content-type': 'foo' }, isPartAFile: (fieldName, contentType, fileName) => fieldName === 'my-special-field' || fileName !== 'not-so-special.txt' }); // $ExpectType Busboy -new BusboyDefault({ headers: { 'content-type': 'foo' }, isPartAFile: (fieldName, contentType, fileName) => fileName !== undefined }); // $ExpectType Busboy +expectError(new BusboyDefault({})) +const busboy = BusboyDefault({ headers: { 'content-type': 'foo' } }) // $ExpectType Busboy +new BusboyDefault({ headers: { 'content-type': 'foo' } }) // $ExpectType Busboy +new BusboyDefault({ headers: { 'content-type': 'foo' }, highWaterMark: 1000 }) // $ExpectType Busboy +new BusboyDefault({ headers: { 'content-type': 'foo' }, fileHwm: 1000 }) // $ExpectType Busboy +new BusboyDefault({ headers: { 'content-type': 'foo' }, defCharset: 'utf8' }) // $ExpectType Busboy +new BusboyDefault({ headers: { 'content-type': 'foo' }, preservePath: true }) // $ExpectType Busboy +new BusboyDefault({ headers: { 'content-type': 'foo' }, limits: { fieldNameSize: 200 } }) // $ExpectType Busboy +new BusboyDefault({ headers: { 'content-type': 'foo' }, limits: { fieldSize: 200 } }) // $ExpectType Busboy +new BusboyDefault({ headers: { 'content-type': 'foo' }, limits: { fields: 200 } }) // $ExpectType Busboy +new BusboyDefault({ headers: { 'content-type': 'foo' }, limits: { fileSize: 200 } }) // $ExpectType Busboy +new BusboyDefault({ headers: { 'content-type': 'foo' }, limits: { files: 200 } }) // $ExpectType Busboy +new BusboyDefault({ headers: { 'content-type': 'foo' }, limits: { parts: 200 } }) // $ExpectType Busboy +new BusboyDefault({ headers: { 'content-type': 'foo' }, limits: { headerPairs: 200 } }) // $ExpectType Busboy +new BusboyDefault({ headers: { 'content-type': 'foo' }, limits: { headerSize: 200 } }) // $ExpectType Busboy +new BusboyDefault({ headers: { 'content-type': 'foo' }, isPartAFile: (fieldName, contentType, fileName) => fieldName === 'my-special-field' || fileName !== 'not-so-special.txt' }) // $ExpectType Busboy +new BusboyDefault({ headers: { 'content-type': 'foo' }, isPartAFile: (fieldName, contentType, fileName) => fileName !== undefined }) // $ExpectType Busboy busboy.addListener('file', (fieldname, file, filename, encoding, mimetype) => { - expectType (fieldname) - expectType(file); - expectType(filename); - expectType(encoding); - expectType(mimetype); -}); + expectType(fieldname) + expectType(file) + expectType(filename) + expectType(encoding) + expectType(mimetype) +}) busboy.addListener('field', (fieldname, val, fieldnameTruncated, valTruncated, encoding, mimetype) => { - expectType (fieldname); - expectType (val); - expectType (fieldnameTruncated); - expectType (valTruncated); - expectType (encoding); - expectType (mimetype); -}); -busboy.addListener('partsLimit', () => {}); -busboy.addListener('filesLimit', () => {}); -busboy.addListener('fieldsLimit', () => {}); + expectType(fieldname) + expectType(val) + expectType(fieldnameTruncated) + expectType(valTruncated) + expectType(encoding) + expectType(mimetype) +}) +busboy.addListener('partsLimit', () => {}) +busboy.addListener('filesLimit', () => {}) +busboy.addListener('fieldsLimit', () => {}) busboy.addListener('error', e => { - expectType (e); -}); -busboy.addListener('finish', () => {}); + expectType(e) +}) +busboy.addListener('finish', () => {}) // test fallback busboy.on('foo', foo => { - expectType (foo); -}); + expectType(foo) +}) busboy.on(Symbol('foo'), foo => { - expectType(foo); -}); + expectType(foo) +}) busboy.on('file', (fieldname, file, filename, encoding, mimetype) => { - expectType (fieldname); - expectType (file); - expectType (filename); - expectType (encoding); - expectType (mimetype); -}); + expectType(fieldname) + expectType(file) + expectType(filename) + expectType(encoding) + expectType(mimetype) +}) busboy.on('field', (fieldname, val, fieldnameTruncated, valTruncated, encoding, mimetype) => { - expectType (fieldname); - expectType (val); - expectType (fieldnameTruncated); - expectType (valTruncated); - expectType (encoding); - expectType (mimetype); -}); -busboy.on('partsLimit', () => {}); -busboy.on('filesLimit', () => {}); -busboy.on('fieldsLimit', () => {}); + expectType(fieldname) + expectType(val) + expectType(fieldnameTruncated) + expectType(valTruncated) + expectType(encoding) + expectType(mimetype) +}) +busboy.on('partsLimit', () => {}) +busboy.on('filesLimit', () => {}) +busboy.on('fieldsLimit', () => {}) busboy.on('error', e => { - expectType (e); -}); -busboy.on('finish', () => {}); + expectType(e) +}) +busboy.on('finish', () => {}) // test fallback busboy.on('foo', foo => { - expectType (foo); -}); + expectType(foo) +}) busboy.on(Symbol('foo'), foo => { - expectType (foo); -}); + expectType(foo) +}) busboy.once('file', (fieldname, file, filename, encoding, mimetype) => { - expectType (fieldname); - expectType (file); - expectType (filename); - expectType (encoding); - expectType (mimetype); -}); + expectType(fieldname) + expectType(file) + expectType(filename) + expectType(encoding) + expectType(mimetype) +}) busboy.once('field', (fieldname, val, fieldnameTruncated, valTruncated, encoding, mimetype) => { - expectType (fieldname); - expectType (val); - expectType (fieldnameTruncated); - expectType (valTruncated); - expectType (encoding); - expectType (mimetype); -}); -busboy.once('partsLimit', () => {}); -busboy.once('filesLimit', () => {}); -busboy.once('fieldsLimit', () => {}); + expectType(fieldname) + expectType(val) + expectType(fieldnameTruncated) + expectType(valTruncated) + expectType(encoding) + expectType(mimetype) +}) +busboy.once('partsLimit', () => {}) +busboy.once('filesLimit', () => {}) +busboy.once('fieldsLimit', () => {}) busboy.once('error', e => { - expectType (e); -}); -busboy.once('finish', () => {}); + expectType(e) +}) +busboy.once('finish', () => {}) // test fallback busboy.once('foo', foo => { - expectType (foo); -}); + expectType(foo) +}) busboy.once(Symbol('foo'), foo => { - expectType (foo); -}); + expectType(foo) +}) busboy.removeListener('file', (fieldname, file, filename, encoding, mimetype) => { - expectType (fieldname); - expectType (file); - expectType (filename); - expectType (encoding); - expectType (mimetype); -}); + expectType(fieldname) + expectType(file) + expectType(filename) + expectType(encoding) + expectType(mimetype) +}) busboy.removeListener('field', (fieldname, val, fieldnameTruncated, valTruncated, encoding, mimetype) => { - expectType (fieldname); - expectType (val); - expectType (fieldnameTruncated); - expectType (valTruncated); - expectType (encoding); - expectType (mimetype); -}); -busboy.removeListener('partsLimit', () => {}); -busboy.removeListener('filesLimit', () => {}); -busboy.removeListener('fieldsLimit', () => {}); + expectType(fieldname) + expectType(val) + expectType(fieldnameTruncated) + expectType(valTruncated) + expectType(encoding) + expectType(mimetype) +}) +busboy.removeListener('partsLimit', () => {}) +busboy.removeListener('filesLimit', () => {}) +busboy.removeListener('fieldsLimit', () => {}) busboy.removeListener('error', e => { - expectType (e); -}); -busboy.removeListener('finish', () => {}); + expectType(e) +}) +busboy.removeListener('finish', () => {}) // test fallback busboy.removeListener('foo', foo => { - expectType (foo); -}); + expectType(foo) +}) busboy.removeListener(Symbol('foo'), foo => { - expectType (foo); -}); + expectType(foo) +}) busboy.off('file', (fieldname, file, filename, encoding, mimetype) => { - expectType (fieldname); - expectType (file); - expectType (filename); - expectType (encoding); - expectType (mimetype); -}); + expectType(fieldname) + expectType(file) + expectType(filename) + expectType(encoding) + expectType(mimetype) +}) busboy.off('field', (fieldname, val, fieldnameTruncated, valTruncated, encoding, mimetype) => { - expectType (fieldname); - expectType (val); - expectType (fieldnameTruncated); - expectType (valTruncated); - expectType (encoding); - expectType (mimetype); -}); -busboy.off('partsLimit', () => {}); -busboy.off('filesLimit', () => {}); -busboy.off('fieldsLimit', () => {}); + expectType(fieldname) + expectType(val) + expectType(fieldnameTruncated) + expectType(valTruncated) + expectType(encoding) + expectType(mimetype) +}) +busboy.off('partsLimit', () => {}) +busboy.off('filesLimit', () => {}) +busboy.off('fieldsLimit', () => {}) busboy.off('error', e => { - expectType (e); -}); -busboy.off('finish', () => {}); + expectType(e) +}) +busboy.off('finish', () => {}) // test fallback busboy.off('foo', foo => { - expectType (foo); -}); + expectType(foo) +}) busboy.off(Symbol('foo'), foo => { - expectType (foo); -}); + expectType(foo) +}) busboy.prependListener('file', (fieldname, file, filename, encoding, mimetype) => { - expectType (fieldname); - expectType (file); - expectType (filename); - expectType (encoding); - expectType (mimetype); -}); + expectType(fieldname) + expectType(file) + expectType(filename) + expectType(encoding) + expectType(mimetype) +}) busboy.prependListener('field', (fieldname, val, fieldnameTruncated, valTruncated, encoding, mimetype) => { - expectType (fieldname); - expectType (val); - expectType (fieldnameTruncated); - expectType (valTruncated); - expectType (encoding); - expectType (mimetype); -}); -busboy.prependListener('partsLimit', () => {}); -busboy.prependListener('filesLimit', () => {}); -busboy.prependListener('fieldsLimit', () => {}); + expectType(fieldname) + expectType(val) + expectType(fieldnameTruncated) + expectType(valTruncated) + expectType(encoding) + expectType(mimetype) +}) +busboy.prependListener('partsLimit', () => {}) +busboy.prependListener('filesLimit', () => {}) +busboy.prependListener('fieldsLimit', () => {}) busboy.prependListener('error', e => { - expectType (e); -}); -busboy.prependListener('finish', () => {}); + expectType(e) +}) +busboy.prependListener('finish', () => {}) // test fallback busboy.prependListener('foo', foo => { - expectType (foo); -}); + expectType(foo) +}) busboy.prependListener(Symbol('foo'), foo => { - expectType (foo); -}); + expectType(foo) +}) busboy.prependOnceListener('file', (fieldname, file, filename, encoding, mimetype) => { - expectType (fieldname); - expectType (file); - expectType (filename); - expectType (encoding); - expectType (mimetype); -}); + expectType(fieldname) + expectType(file) + expectType(filename) + expectType(encoding) + expectType(mimetype) +}) busboy.prependOnceListener('field', (fieldname, val, fieldnameTruncated, valTruncated, encoding, mimetype) => { - expectType (fieldname); - expectType (val); - expectType (fieldnameTruncated); - expectType (valTruncated); - expectType (encoding); - expectType (mimetype); -}); -busboy.prependOnceListener('partsLimit', () => {}); -busboy.prependOnceListener('filesLimit', () => {}); -busboy.prependOnceListener('fieldsLimit', () => {}); + expectType(fieldname) + expectType(val) + expectType(fieldnameTruncated) + expectType(valTruncated) + expectType(encoding) + expectType(mimetype) +}) +busboy.prependOnceListener('partsLimit', () => {}) +busboy.prependOnceListener('filesLimit', () => {}) +busboy.prependOnceListener('fieldsLimit', () => {}) busboy.prependOnceListener('error', e => { - expectType (e); -}); -busboy.prependOnceListener('finish', () => {}); + expectType(e) +}) +busboy.prependOnceListener('finish', () => {}) // test fallback busboy.prependOnceListener('foo', foo => { - expectType (foo); -}); + expectType(foo) +}) busboy.prependOnceListener(Symbol('foo'), foo => { - expectType (foo); -}); + expectType(foo) +}) diff --git a/tsconfig.json b/tsconfig.json index eec9314..4cc6e43 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,14 +1,14 @@ { "compilerOptions": { "outDir": "dist", - "module": "commonjs", - "target": "es2015", + "module": "Node16", + "target": "es2022", "sourceMap": false, "declaration": true, "declarationMap": false, "types": ["node"], "strict": true, - "moduleResolution": "node", + "moduleResolution": "Node16", "noUnusedLocals": false, "noUnusedParameters": false, "noFallthroughCasesInSwitch": true, @@ -22,9 +22,5 @@ "esModuleInterop": true, "forceConsistentCasingInFileNames": true }, - "exclude": [ - "node_modules", - "test", - "dist" - ] + "exclude": ["node_modules", "test", "dist"] }