formidable
Advanced tools
Comparing version 3.2.5 to 3.3.2
{ | ||
"name": "formidable", | ||
"version": "3.2.5", | ||
"version": "3.3.2", | ||
"license": "MIT", | ||
@@ -16,6 +16,8 @@ "description": "A node.js module for parsing form data, especially file uploads.", | ||
"access": "public", | ||
"tag": "v3" | ||
"tag": "latest" | ||
}, | ||
"scripts": { | ||
"bench": "node benchmark", | ||
"bench2prep": "node benchmark/server.js", | ||
"bench2": "bombardier --body-file=\"./README.md\" --method=POST --duration=10s --connections=100 http://localhost:3000/api/upload", | ||
"fmt": "yarn run fmt:prepare '**/*'", | ||
@@ -29,10 +31,12 @@ "fmt:prepare": "prettier --write", | ||
"pretest": "del-cli ./test/tmp && make-dir ./test/tmp", | ||
"test": "node --experimental-vm-modules ./node_modules/jest/bin/jest.js --coverage", | ||
"test": "npm run test-jest && npm run test-node", | ||
"test-jest": "node --experimental-vm-modules ./node_modules/jest/bin/jest.js --testPathPattern=test/ --coverage", | ||
"test-node": "node --test test-node/", | ||
"pretest:ci": "yarn run pretest", | ||
"test:ci": "node --experimental-vm-modules node_modules/.bin/nyc jest --coverage" | ||
"test:ci": "node --experimental-vm-modules node_modules/.bin/nyc jest --testPathPattern=test/ --coverage && node --experimental-vm-modules node_modules/.bin/nyc node --test test-node/" | ||
}, | ||
"dependencies": { | ||
"dezalgo": "1.0.3", | ||
"hexoid": "1.0.0", | ||
"once": "1.4.0" | ||
"dezalgo": "^1.0.4", | ||
"hexoid": "^1.0.0", | ||
"once": "^1.4.0" | ||
}, | ||
@@ -39,0 +43,0 @@ "devDependencies": { |
@@ -23,3 +23,3 @@ <p align="center"> | ||
[![Minimum Required Nodejs][nodejs-img]][npmv-url] | ||
[![Tidelift Subcsription][tidelift-img]][tidelift-url] | ||
[![Tidelift Subscription][tidelift-img]][tidelift-url] | ||
[![Buy me a Kofi][kofi-img]][kofi-url] | ||
@@ -81,10 +81,10 @@ [![Renovate App Status][renovateapp-img]][renovateapp-url] | ||
# v2 | ||
npm install formidable | ||
npm install formidable@v2 | ||
# v3 | ||
npm install formidable | ||
npm install formidable@v3 | ||
``` | ||
_**Note:** In the near future v3 will be published on the `latest` NPM dist-tag. Future not ready releases will be published on `*-next` dist-tags for the corresponding version._ | ||
_**Note:** Future not ready releases will be published on `*-next` dist-tags for the corresponding version._ | ||
@@ -103,3 +103,3 @@ | ||
import http from 'node:http'; | ||
import formidable from 'formidable'; | ||
import formidable, {errors as formidableErrors} from 'formidable'; | ||
@@ -113,2 +113,6 @@ const server = http.createServer((req, res) => { | ||
if (err) { | ||
// example to check for a very specific error | ||
if (err.code === formidableErrors.maxFieldsExceeded) { | ||
} | ||
res.writeHead(err.httpCode || 400, { 'Content-Type': 'text/plain' }); | ||
@@ -347,3 +351,5 @@ res.end(String(err)); | ||
- `options.createDirsFromUploads` **{boolean}** - default false. If true, makes direct folder uploads possible. Use `<input type="file" name="folders" webkitdirectory directory multiple>` to create a form to upload folders. Has to be used with the options `options.uploadDir` and `options.filename` where `options.filename` has to return a string with the character `/` for folders to be created. The base will be `options.uploadDir`. | ||
#### `options.filename` **{function}** function (name, ext, part, form) -> string | ||
@@ -495,3 +501,3 @@ | ||
A method that allows you to extend the Formidable library. By default we include | ||
4 plugins, which esentially are adapters to plug the different built-in parsers. | ||
4 plugins, which essentially are adapters to plug the different built-in parsers. | ||
@@ -653,3 +659,3 @@ **The plugins added by this method are always enabled.** | ||
// file.newFilename generated hexoid or what options.filename returned | ||
// file.filepath default pathnme as per options.uploadDir and options.filename | ||
// file.filepath default pathname as per options.uploadDir and options.filename | ||
// file.filepath = CUSTOM_PATH // to change the final path | ||
@@ -656,0 +662,0 @@ }); |
@@ -6,2 +6,3 @@ /* eslint-disable class-methods-use-this */ | ||
import path from 'node:path'; | ||
import fsPromises from 'node:fs/promises'; | ||
import { EventEmitter } from 'node:events'; | ||
@@ -29,2 +30,3 @@ import { StringDecoder } from 'node:string_decoder'; | ||
allowEmptyFiles: false, | ||
createDirsFromUploads: false, | ||
keepExtensions: false, | ||
@@ -47,2 +49,28 @@ encoding: 'utf-8', | ||
const decorateForceSequential = function (promiseCreator) { | ||
/* forces a function that returns a promise to be sequential | ||
useful for fs for example */ | ||
let lastPromise = Promise.resolve(); | ||
return async function (...x) { | ||
const promiseWeAreWaitingFor = lastPromise; | ||
let currentPromise; | ||
let callback; | ||
// we need to change lastPromise before await anything, | ||
// otherwise 2 calls might wait the same thing | ||
lastPromise = new Promise(function (resolve) { | ||
callback = resolve; | ||
}); | ||
await promiseWeAreWaitingFor; | ||
currentPromise = promiseCreator(...x); | ||
currentPromise.then(callback).catch(callback); | ||
return currentPromise; | ||
}; | ||
}; | ||
const createNecessaryDirectoriesAsync = decorateForceSequential(function (filePath) { | ||
const directoryname = path.dirname(filePath); | ||
return fsPromises.mkdir(directoryname, { recursive: true }); | ||
}); | ||
const invalidExtensionChar = (c) => { | ||
@@ -156,3 +184,3 @@ const code = c.charCodeAt(0); | ||
parse(req, cb) { | ||
async parse(req, cb) { | ||
this.req = req; | ||
@@ -193,3 +221,3 @@ | ||
// Parse headers and setup the parser, ready to start listening for data. | ||
this.writeHeaders(req.headers); | ||
await this.writeHeaders(req.headers); | ||
@@ -224,6 +252,6 @@ // Start listening for data. | ||
writeHeaders(headers) { | ||
async writeHeaders(headers) { | ||
this.headers = headers; | ||
this._parseContentLength(); | ||
this._parseContentType(); | ||
await this._parseContentType(); | ||
@@ -267,6 +295,6 @@ if (!this._parser) { | ||
// this method can be overwritten by the user | ||
this._handlePart(part); | ||
return this._handlePart(part); | ||
} | ||
_handlePart(part) { | ||
async _handlePart(part) { | ||
if (part.originalFilename && typeof part.originalFilename !== 'string') { | ||
@@ -328,3 +356,3 @@ this._error( | ||
const filepath = this._joinDirectoryName(newFilename); | ||
const file = this._newFile({ | ||
const file = await this._newFile({ | ||
newFilename, | ||
@@ -370,3 +398,3 @@ filepath, | ||
new FormidableError( | ||
`options.allowEmptyFiles is false, file size should be greather than 0`, | ||
`options.allowEmptyFiles is false, file size should be greater than 0`, | ||
errors.noEmptyFiles, | ||
@@ -408,3 +436,3 @@ 400, | ||
// eslint-disable-next-line max-statements | ||
_parseContentType() { | ||
async _parseContentType() { | ||
if (this.bytesExpected === 0) { | ||
@@ -430,6 +458,6 @@ this._parser = new DummyParser(this, this.options); | ||
const results = []; | ||
this._plugins.forEach((plugin, idx) => { | ||
await Promise.all(this._plugins.map(async (plugin, idx) => { | ||
let pluginReturn = null; | ||
try { | ||
pluginReturn = plugin(this, this.options) || this; | ||
pluginReturn = await plugin(this, this.options) || this; | ||
} catch (err) { | ||
@@ -450,3 +478,3 @@ // directly throw from the `form.parse` method; | ||
this.emit('plugin', idx, pluginReturn); | ||
}); | ||
})); | ||
this.emit('pluginsResults', results); | ||
@@ -486,19 +514,31 @@ } | ||
_newFile({ filepath, originalFilename, mimetype, newFilename }) { | ||
return this.options.fileWriteStreamHandler | ||
? new VolatileFile({ | ||
newFilename, | ||
filepath, | ||
originalFilename, | ||
mimetype, | ||
createFileWriteStream: this.options.fileWriteStreamHandler, | ||
hashAlgorithm: this.options.hashAlgorithm, | ||
}) | ||
: new PersistentFile({ | ||
newFilename, | ||
filepath, | ||
originalFilename, | ||
mimetype, | ||
hashAlgorithm: this.options.hashAlgorithm, | ||
}); | ||
async _newFile({ filepath, originalFilename, mimetype, newFilename }) { | ||
if (this.options.fileWriteStreamHandler) { | ||
return new VolatileFile({ | ||
newFilename, | ||
filepath, | ||
originalFilename, | ||
mimetype, | ||
createFileWriteStream: this.options.fileWriteStreamHandler, | ||
hashAlgorithm: this.options.hashAlgorithm, | ||
}); | ||
} | ||
if (this.options.createDirsFromUploads) { | ||
try { | ||
await createNecessaryDirectoriesAsync(filepath); | ||
} catch (errorCreatingDir) { | ||
this._error(new FormidableError( | ||
`cannot create directory`, | ||
errors.cannotCreateDir, | ||
409, | ||
)); | ||
} | ||
} | ||
return new PersistentFile({ | ||
newFilename, | ||
filepath, | ||
originalFilename, | ||
mimetype, | ||
hashAlgorithm: this.options.hashAlgorithm, | ||
}); | ||
} | ||
@@ -505,0 +545,0 @@ |
@@ -19,2 +19,3 @@ const missingPlugin = 1000; | ||
const pluginFailed = 1017; | ||
const cannotCreateDir = 1018; | ||
@@ -48,4 +49,5 @@ const FormidableError = class extends Error { | ||
pluginFailed, | ||
cannotCreateDir, | ||
}; | ||
export default FormidableError; |
@@ -240,3 +240,3 @@ /* eslint-disable no-fallthrough */ | ||
if (index === 0) { | ||
// boyer-moore derrived algorithm to safely skip non-boundary data | ||
// boyer-moore derived algorithm to safely skip non-boundary data | ||
i += boundaryEnd; | ||
@@ -243,0 +243,0 @@ while (i < this.bufferLength && !(buffer[i] in boundaryChars)) { |
@@ -54,3 +54,3 @@ /* eslint-disable no-underscore-dangle */ | ||
// eslint-disable-next-line max-statements, consistent-return | ||
parser.on('data', ({ name, buffer, start, end }) => { | ||
parser.on('data', async ({ name, buffer, start, end }) => { | ||
if (name === 'partBegin') { | ||
@@ -128,3 +128,3 @@ part = new Stream(); | ||
encoding. So we should always work with a number of bytes that | ||
can be divided by 4, it will result in a number of buytes that | ||
can be divided by 4, it will result in a number of bytes that | ||
can be divided vy 3. | ||
@@ -164,4 +164,5 @@ */ | ||
} | ||
this.onPart(part); | ||
this._parser.pause(); | ||
await this.onPart(part); | ||
this._parser.resume(); | ||
} else if (name === 'end') { | ||
@@ -168,0 +169,0 @@ this.ended = true; |
@@ -7,3 +7,3 @@ /* eslint-disable no-underscore-dangle */ | ||
// the `options` is also available through the `options` / `formidable.options` | ||
export default function plugin(formidable, options) { | ||
export default async function plugin(formidable, options) { | ||
// the `this` context is always formidable, as the first argument of a plugin | ||
@@ -16,3 +16,3 @@ // but this allows us to customize/test each plugin | ||
if (/octet-stream/i.test(self.headers['content-type'])) { | ||
init.call(self, self, options); | ||
await init.call(self, self, options); | ||
} | ||
@@ -25,3 +25,3 @@ return self; | ||
// to test the plugin you can pass custom `this` context to it (and so `this.options`) | ||
function init(_self, _opts) { | ||
async function init(_self, _opts) { | ||
this.type = octetStreamType; | ||
@@ -37,3 +37,3 @@ const originalFilename = this.headers['x-file-name']; | ||
const filepath = this._joinDirectoryName(newFilename); | ||
const file = this._newFile({ | ||
const file = await this._newFile({ | ||
newFilename, | ||
@@ -40,0 +40,0 @@ filepath, |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
93933
1612
861
+ Addeddezalgo@1.0.4(transitive)
- Removeddezalgo@1.0.3(transitive)
Updateddezalgo@^1.0.4
Updatedhexoid@^1.0.0
Updatedonce@^1.4.0