Showing preview only (505K chars total). Download the full file or copy to clipboard to get everything.
Repository: node-formidable/formidable
Branch: master
Commit: 44768be86149
Files: 120
Total size: 472.6 KB
Directory structure:
gitextract_b0r5txre/
├── .all-contributorsrc
├── .editorconfig
├── .eslintignore
├── .eslintrc.cjs
├── .github/
│ ├── .kodiak.toml
│ ├── dependabot.yml
│ └── workflows/
│ ├── codeql-analysis.yml
│ └── main.yml
├── .gitignore
├── .prettierignore
├── .prettierrc.js
├── CHANGELOG.md
├── LICENSE
├── README.md
├── README_pt_BR.md
├── VERSION_NOTES.md
├── benchmark/
│ ├── 2022-11-30-i5-9600k.txt
│ ├── e2e.txt
│ ├── index.js
│ └── server.js
├── examples/
│ ├── express-middleware.js
│ ├── forceBuffer.js
│ ├── json.js
│ ├── log-file-content-to-console.js
│ ├── multipart-parser.js
│ ├── multiples.js
│ ├── store-files-on-s3.js
│ ├── upload-multiple-files.js
│ ├── urlencoded-no-enctype.js
│ ├── with-express.js
│ ├── with-http.js
│ └── with-koa2.js
├── nyc.config.js
├── package.json
├── pnpm-lock.yaml
├── src/
│ ├── Formidable.js
│ ├── FormidableError.js
│ ├── PersistentFile.js
│ ├── VolatileFile.js
│ ├── helpers/
│ │ ├── firstValues.js
│ │ └── readBooleans.js
│ ├── index.js
│ ├── parsers/
│ │ ├── Dummy.js
│ │ ├── JSON.js
│ │ ├── Multipart.js
│ │ ├── OctetStream.js
│ │ ├── Querystring.js
│ │ ├── StreamingQuerystring.js
│ │ └── index.js
│ └── plugins/
│ ├── index.js
│ ├── json.js
│ ├── multipart.js
│ ├── octetstream.js
│ └── querystring.js
├── test/
│ ├── fixture/
│ │ ├── file/
│ │ │ ├── funkyfilename.txt
│ │ │ ├── plain.txt
│ │ │ └── second-plaintext.txt
│ │ ├── http/
│ │ │ ├── encoding/
│ │ │ │ ├── beta-sticker-1.png.http
│ │ │ │ ├── binaryfile.tar.gz.http
│ │ │ │ ├── blank.gif.http
│ │ │ │ ├── menu_separator.png.http
│ │ │ │ └── plain.txt.http
│ │ │ ├── misc/
│ │ │ │ ├── boundary-substring-json.http
│ │ │ │ ├── empty-multipart.http
│ │ │ │ ├── empty-multipart2.http
│ │ │ │ ├── empty-urlencoded.http
│ │ │ │ ├── empty.http
│ │ │ │ └── minimal.http
│ │ │ ├── no-filename/
│ │ │ │ ├── filename-name.http
│ │ │ │ └── generic.http
│ │ │ ├── preamble/
│ │ │ │ ├── crlf.http
│ │ │ │ └── preamble.http
│ │ │ ├── special-chars-in-filename/
│ │ │ │ ├── info.md
│ │ │ │ ├── line-separator.http
│ │ │ │ ├── osx-chrome-13.http
│ │ │ │ ├── osx-firefox-3.6.http
│ │ │ │ ├── osx-safari-5.http
│ │ │ │ ├── xp-chrome-12.http
│ │ │ │ ├── xp-ie-7.http
│ │ │ │ ├── xp-ie-8.http
│ │ │ │ └── xp-safari-5.http
│ │ │ └── workarounds/
│ │ │ ├── missing-hyphens1.http
│ │ │ └── missing-hyphens2.http
│ │ ├── js/
│ │ │ ├── encoding.js
│ │ │ ├── misc.js
│ │ │ ├── no-filename.js
│ │ │ ├── preamble.js
│ │ │ ├── special-chars-in-filename.js
│ │ │ └── workarounds.js
│ │ ├── multi_video.upload
│ │ └── multipart.js
│ ├── integration/
│ │ ├── file-write-stream-handler-option.test.js
│ │ ├── fixtures.test.js
│ │ ├── json.test.js
│ │ ├── octet-stream.test.js
│ │ └── store-files-option.test.js
│ ├── standalone/
│ │ ├── connection-aborted.test.js
│ │ ├── content-transfer-encoding.test.js
│ │ ├── issue-46.test.js
│ │ └── keep-alive-error.test.js
│ ├── tools/
│ │ └── base64.html
│ └── unit/
│ ├── custom-plugins.test.js
│ ├── formidable.test.js
│ ├── multipart-parser.test.js
│ ├── persistent-file.disabled-test.js
│ ├── querystring-parser.test.js
│ └── volatile-file.test.js
├── test-legacy/
│ ├── .DS_Store
│ ├── README.md
│ ├── common.js
│ ├── integration/
│ │ └── test-multipart-parser.js
│ ├── simple/
│ │ ├── test-file.js
│ │ └── test-incoming-form.js
│ └── system/
│ └── test-multi-video-upload.js
├── test-node/
│ └── standalone/
│ ├── createDirsFromUploads.test.js
│ ├── end-event-emitted-twice.test.js
│ ├── multipart_parser.test.js
│ └── promise.test.js
└── tool/
├── record.js
└── rollup.config.js
================================================
FILE CONTENTS
================================================
================================================
FILE: .all-contributorsrc
================================================
{
"projectName": "node-formidable",
"projectOwner": "node-formidable",
"repoType": "github",
"repoHost": "https://github.com",
"imageSize": 100,
"contributorsPerLine": 6,
"commitConvention": "angular",
"commit": true,
"skipCi": true,
"files": [
"README.md"
],
"contributors": [
{
"login": "felixge",
"name": "Felix Geisendörfer",
"avatar_url": "https://avatars3.githubusercontent.com/u/15000?s=460&v=4",
"profile": "https://twitter.com/felixge",
"contributions": [
"code",
"design",
"ideas",
"doc"
]
},
{
"login": "tunnckoCore",
"name": "Charlike Mike Reagent",
"avatar_url": "https://avatars3.githubusercontent.com/u/5038030?v=4",
"profile": "https://tunnckoCore.com",
"contributions": [
"bug",
"infra",
"design",
"code",
"doc",
"example",
"ideas",
"maintenance",
"test"
]
},
{
"login": "kedarv",
"name": "Kedar",
"avatar_url": "https://avatars1.githubusercontent.com/u/1365665?v=4",
"profile": "https://github.com/kedarv",
"contributions": [
"code",
"test",
"question",
"bug"
]
},
{
"login": "GrosSacASac",
"name": "Walle Cyril",
"avatar_url": "https://avatars0.githubusercontent.com/u/5721194?v=4",
"profile": "https://github.com/GrosSacASac",
"contributions": [
"question",
"bug",
"code",
"financial",
"ideas",
"maintenance"
]
},
{
"login": "xarguments",
"name": "Xargs",
"avatar_url": "https://avatars2.githubusercontent.com/u/40522463?v=4",
"profile": "https://github.com/xarguments",
"contributions": [
"question",
"bug",
"code",
"maintenance"
]
},
{
"login": "Amit-A",
"name": "Amit-A",
"avatar_url": "https://avatars1.githubusercontent.com/u/7987238?v=4",
"profile": "https://github.com/Amit-A",
"contributions": [
"question",
"bug",
"code"
]
},
{
"login": "charmander",
"name": "Charmander",
"avatar_url": "https://avatars1.githubusercontent.com/u/1889843?v=4",
"profile": "https://charmander.me/",
"contributions": [
"question",
"bug",
"code",
"ideas",
"maintenance"
]
},
{
"login": "DylanPiercey",
"name": "Dylan Piercey",
"avatar_url": "https://avatars2.githubusercontent.com/u/4985201?v=4",
"profile": "https://twitter.com/dylan_piercey",
"contributions": [
"ideas"
]
},
{
"login": "ad-m",
"name": "Adam Dobrawy",
"avatar_url": "https://avatars1.githubusercontent.com/u/3618479?v=4",
"profile": "http://ochrona.jawne.info.pl",
"contributions": [
"bug",
"doc"
]
},
{
"login": "amitrohatgi",
"name": "amitrohatgi",
"avatar_url": "https://avatars3.githubusercontent.com/u/12177021?v=4",
"profile": "https://github.com/amitrohatgi",
"contributions": [
"ideas"
]
},
{
"login": "fengxinming",
"name": "Jesse Feng",
"avatar_url": "https://avatars2.githubusercontent.com/u/6262382?v=4",
"profile": "https://github.com/fengxinming",
"contributions": [
"bug"
]
},
{
"login": "quantumsheep",
"name": "Nathanael Demacon",
"avatar_url": "https://avatars1.githubusercontent.com/u/7271496?v=4",
"profile": "https://qtmsheep.com",
"contributions": [
"question",
"code",
"review"
]
},
{
"login": "MunMunMiao",
"name": "MunMunMiao",
"avatar_url": "https://avatars1.githubusercontent.com/u/18216142?v=4",
"profile": "https://github.com/MunMunMiao",
"contributions": [
"bug"
]
},
{
"login": "gabipetrovay",
"name": "Gabriel Petrovay",
"avatar_url": "https://avatars0.githubusercontent.com/u/1170398?v=4",
"profile": "https://github.com/gabipetrovay",
"contributions": [
"bug",
"code"
]
},
{
"login": "Elzair",
"name": "Philip Woods",
"avatar_url": "https://avatars0.githubusercontent.com/u/2352818?v=4",
"profile": "https://github.com/Elzair",
"contributions": [
"code",
"ideas"
]
},
{
"login": "dmolim",
"name": "Dmitry Ivonin",
"avatar_url": "https://avatars2.githubusercontent.com/u/7090374?v=4",
"profile": "https://github.com/dmolim",
"contributions": [
"doc"
]
},
{
"login": "masterkain",
"name": "Claudio Poli",
"avatar_url": "https://avatars1.githubusercontent.com/u/12844?v=4",
"profile": "https://audiobox.fm",
"contributions": [
"code"
]
}
]
}
================================================
FILE: .editorconfig
================================================
# http://editorconfig.org/
root = true
[*]
indent_style = space
indent_size = 2
tab_width = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = true
================================================
FILE: .eslintignore
================================================
# Ignore everything!
*
# de-ignores: add here what you want to be committed
!*.*js*
!*.ts*
!*.md*
!**/src
!**/src/**
!**/test
!**/test/**
!**/*tests*
!**/*tests*/**
!**/benchmark*
!**/benchmark*/**
!**/example*
!**/example*/**
# re-ignores: add here what you want to be ignored again
test/tmp
================================================
FILE: .eslintrc.cjs
================================================
'use strict';
const airbnbBase = require('eslint-config-airbnb-base');
// eslint-disable-next-line import/no-dynamic-require
const bestPractices = require(airbnbBase.extends[0]);
const ignoredProps = bestPractices.rules[
'no-param-reassign'
][1].ignorePropertyModificationsFor.concat(
'err',
'x',
'_',
'opts',
'options',
'settings',
'config',
'cfg',
);
// Additional rules that are specific and overriding previous
const additionalChanges = {
strict: 'off',
// Enforce using named functions when regular function is used,
// otherwise use arrow functions
'func-names': ['error', 'always'],
// Always use parens (for consistency).
// https://eslint.org/docs/rules/arrow-parens
'arrow-parens': ['error', 'always', { requireForBlockBody: true }],
'prefer-arrow-callback': [
'error',
{ allowNamedFunctions: true, allowUnboundThis: true },
],
// http://eslint.org/docs/rules/max-params
'max-params': ['error', { max: 3 }],
// http://eslint.org/docs/rules/max-statements
'max-statements': ['error', { max: 20 }],
// http://eslint.org/docs/rules/max-statements-per-line
'max-statements-per-line': ['error', { max: 1 }],
// http://eslint.org/docs/rules/max-nested-callbacks
'max-nested-callbacks': ['error', { max: 4 }],
// http://eslint.org/docs/rules/max-depth
'max-depth': ['error', { max: 4 }],
// enforces no braces where they can be omitted
// https://eslint.org/docs/rules/arrow-body-style
// Never enable for object literal.
'arrow-body-style': [
'error',
'as-needed',
{ requireReturnForObjectLiteral: false },
],
// Allow functions to be use before define because:
// 1) they are hoisted,
// 2) because ensure read flow is from top to bottom
// 3) logically order of the code.
// 4) the only addition is 'typedefs' option, see overrides for TS files
'no-use-before-define': [
'error',
{
functions: false,
classes: true,
variables: true,
},
],
// Same as AirBnB, but adds `opts`, `options`, `x` and `err` to exclusions!
// disallow reassignment of function parameters
// disallow parameter object manipulation except for specific exclusions
// rule: https://eslint.org/docs/rules/no-param-reassign.html
'no-param-reassign': [
'error',
{
props: true,
ignorePropertyModificationsFor: ignoredProps,
},
],
// disallow declaration of variables that are not used in the code
'no-unused-vars': [
'error',
{
ignoreRestSiblings: true, // airbnb's default
vars: 'all', // airbnb's default
varsIgnorePattern: '^(?:$$|xx|_|__|[iI]gnor(?:e|ing|ed))',
args: 'after-used', // airbnb's default
argsIgnorePattern: '^(?:$$|xx|_|__|[iI]gnor(?:e|ing|ed))',
// catch blocks are handled by Unicorns
caughtErrors: 'none',
// caughtErrorsIgnorePattern: '^(?:$$|xx|_|__|[iI]gnor(?:e|ing|ed))',
},
],
};
const importRules = {
'import/namespace': ['error', { allowComputed: true }],
'import/no-absolute-path': 'error',
'import/no-webpack-loader-syntax': 'error',
'import/no-self-import': 'error',
// Enable this sometime in the future when Node.js has ES2015 module support
// 'import/no-cycle': 'error',
// Disabled as it doesn't work with TypeScript
// 'import/newline-after-import': 'error',
'import/no-amd': 'error',
'import/no-duplicates': 'error',
// Enable this sometime in the future when Node.js has ES2015 module support
// 'import/unambiguous': 'error',
// Enable this sometime in the future when Node.js has ES2015 module support
// 'import/no-commonjs': 'error',
// Looks useful, but too unstable at the moment
// 'import/no-deprecated': 'error',
'import/no-extraneous-dependencies': 'off',
'import/no-mutable-exports': 'error',
'import/no-named-as-default-member': 'error',
'import/no-named-as-default': 'error',
// Disabled because it's buggy and it also doesn't work with TypeScript
// 'import/no-unresolved': [
// 'error',
// {
// commonjs: true
// }
// ],
'import/order': 'error',
'import/no-unassigned-import': [
'error',
{ allow: ['@babel/polyfill', '@babel/register'] },
],
'import/prefer-default-export': 'off',
// Ensure more web-compat
// ! note that it doesn't work in CommonJS
// https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/extensions.md
'import/extensions': 'off',
// ? Always use named exports. Enable?
// 'import/no-default-export': 'error',
// ? enable?
'import/exports-last': 'off',
// todo: Enable in future.
// Ensures everything is tested (all exports should be used).
// For cases when you don't want or can't test, add eslint-ignore comment!
// see: https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-unused-modules.md
'import/no-unused-modules': 'off',
'import/no-useless-path-segments': ['error', { noUselessIndex: false }],
};
module.exports = {
env: {
es6: true,
es2020: true,
jest: true,
node: true,
commonjs: true,
},
extends: ['eslint:recommended', 'airbnb-base', 'plugin:prettier/recommended'],
plugins: ['prettier'],
rules: {
...additionalChanges,
...importRules,
},
};
================================================
FILE: .github/.kodiak.toml
================================================
# .kodiak.toml
# Minimal config. version is the only required field.
version = 1
[merge]
automerge_label = "ship it"
require_automerge_label = true
block_on_neutral_required_check_runs = true
blocking_labels = ["wip", "do not merge"]
delete_branch_on_merge = true
notify_on_conflict = true
optimistic_updates = false
prioritize_ready_to_merge = true
[merge.message]
title = "pull_request_title"
body = "pull_request_body"
body_type = "markdown"
include_pr_number = true
include_coauthors = true
include_pull_request_url = true
cut_body_after = "<!-- COMMIT_BODY_TEXT_BEGIN -->"
cut_body_before = "<!-- COMMIT_BODY_TEXT_END -->"
[merge.automerge_dependencies]
# only auto merge "minor" and "patch" version upgrades.
# do not automerge "major" version upgrades.
versions = ["minor", "patch"]
usernames = ["dependabot", "renovate"]
[approve]
auto_approve_usernames = ["dependabot", "renovate"]
[update]
always = true
require_automerge_label = true
================================================
FILE: .github/dependabot.yml
================================================
# Versions and updates, dependabot.yml
version: 2
updates:
# Maintain dependencies for GitHub Actions
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
# Maintain dependencies for npm
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "daily"
time: "02:00"
# No one cares about dependency labels, they should be auto-merged
labels: []
allow:
# Allow both direct and indirect updates for all packages
- dependency-type: "all"
rebase-strategy: "auto"
# reviewers: []
================================================
FILE: .github/workflows/codeql-analysis.yml
================================================
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ master ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ master ]
schedule:
- cron: '0 2 * * *'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'javascript' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://git.io/codeql-language-support
steps:
- name: Checkout repository
uses: actions/checkout@v5
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v3
# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
================================================
FILE: .github/workflows/main.yml
================================================
name: ci
# on:
# push:
# branches: [ master ]
# pull_request:
# branches: [ master ]
# jobs:
# # lint:
# # name: Lint
# # runs-on: ubuntu-latest
# # steps:
# # - uses: actions/checkout@v5
# # - name: Set up Node.js
# # uses: actions/setup-node@v5
# # with:
# # node-version: '20'
# # cache: 'npm'
# # - name: Install dependencies
# # run: npm install
# # - name: Run lint
# # run: npm run lint
# test:
# name: Test on ${{ matrix.os }}
# runs-on: ${{ matrix.os }}
# strategy:
# fail-fast: false
# matrix:
# os: [ubuntu-latest, macos-latest]
# node-version: ['lts/*']
# steps:
# - uses: actions/checkout@v5
# - name: Set up Node.js ${{ matrix.node-version }}
# uses: actions/setup-node@v5
# with:
# node-version: ${{ matrix.node-version }}
# cache: 'npm'
# - name: Install dependencies
# run: npm install
# - name: Run tests
# run: npm test
on:
push:
branches:
- '*'
pull_request:
branches:
- '*'
jobs:
build-and-test:
name: Test on ${{ matrix.os }} with Node.js ${{matrix.node-version}}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
node-version: [18, 20, 22, 'lts/*']
steps:
- name: Checkout
uses: actions/checkout@v5
- uses: pnpm/action-setup@v4
name: Install pnpm
with:
run_install: false
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v5
with:
node-version: ${{ matrix.node-version }}
cache: pnpm
- name: Install dependencies
run: pnpm install
- name: Run tests
run: pnpm test
================================================
FILE: .gitignore
================================================
# Ignore everything!
*
*~*
# de-ignores: add here what you want to be committed
!logo.png
!logo.jpg
!test-legacy
!tool
!*.*js*
!*.ts*
!*.md*
!.*rc
!.*ignore
!LICENSE
!.editorconfig
!package.json
!yarn.lock
!pnpm-lock.yaml
!**/src
!**/src/**
!**/test
!**/test/**
!**/test-node
!**/test-node/**
!**/*tests*
!**/*tests*/**
!**/.github
!**/.github/**
!**/example*
!**/example*/**
!**/benchmark*
!**/benchmark*/**
# re-ignores: add here what you want to be ignored again
test/tmp
# !src/*.js
# !src/*.ts
# !test
# !test/*.js
# !test/*.ts
# !test/**/*.js
# !test/**/*.ts
# !*/__tests__
# *.tsbuildinfo
# .*cache
# *.cache
# test/tmp
# *.upload
# *.un~
# # Build environment
# dist
# # Package managers lockfiles
# package-lock.json
# shrinkwrap.json
# # Logs
# logs
# *.log
# *~
# # Runtime data
# pids
# *.pid
# *.seed
# *.pid.lock
# # Directory for instrumented libs generated by jscoverage/JSCover
# lib-cov
# # Coverage directory used by tools like istanbul
# /coverage
# # nyc test coverage
# .nyc_output
# # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
# .grunt
# # Bower dependency directory (https://bower.io/)
# bower_components
# # node-waf configuration
# .lock-wscript
# # Compiled binary addons (https://nodejs.org/api/addons.html)
# build/Release
# # Dependency directories
# node_modules/
# jspm_packages/
# # TypeScript v1 declaration files
# typings/
# # Optional npm cache directory
# .npm
# # Optional eslint cache
# .eslintcache
# # Optional REPL history
# .node_repl_history
# # Output of 'npm pack'
# *.tgz
# # Yarn Integrity file
# .yarn-integrity
# # dotenv environment variables file
# .env
# # next.js build output
# .next
benchmark/testuploads/
================================================
FILE: .prettierignore
================================================
# Ignore everything!
*
# de-ignores: add here what you want to be committed
!*.*js*
!*.ts*
!*.md*
!*.y*ml
!**/src
!**/src/**
!**/test
!**/test/**
!**/*tests*
!**/*tests*/**
!**/.github
!**/.github/**
!**/benchmark*
!**/benchmark*/**/*.js
!**/example*
!**/example*/**
# re-ignores: add here what you want to be ignored again
test/tmp
test/fixture/file
test/fixture/http
*.upload
CHANGELOG.md
# CHANGELOG.md
# LICENSE*
# dist
# test/tmp
# test/fixture/http
# test/fixture/file
# test/fixture/multi*
# test/tools
# # fixtures
# # __fixture__
# # __fixtures__
# *.map
# *.lock
# *.js.snap
# coverage
# *.ico
# *.png
# *.svg
# *.jpeg
# *.jpg
# !.all-contributorsrc
# !.*rc.js
# !.verb*.md
# patches
# **/static/**/*.css
# *.tsbuildinfo
# .*cache
# *.cache
# # Package managers lockfiles
# package-lock.json
# shrinkwrap.json
# pnpm-lock.json
# # Logs
# logs
# *.log
# *~
# # Runtime data
# pids
# *.pid
# *.seed
# *.pid.lock
# # Directory for instrumented libs generated by jscoverage/JSCover
# lib-cov
# # Coverage directory used by tools like istanbul
# coverage
# # nyc test coverage
# .nyc_output
# # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
# .grunt
# # Bower dependency directory (https://bower.io/)
# bower_components
# # node-waf configuration
# .lock-wscript
# # Compiled binary addons (https://nodejs.org/api/addons.html)
# build/Release
# # Dependency directories
# node_modules/
# jspm_packages/
# # TypeScript v1 declaration files
# typings/
# # Optional npm cache directory
# .npm
# # Optional eslint cache
# .eslintcache
# # Optional REPL history
# .node_repl_history
# # Output of 'npm pack'
# *.tgz
# # Yarn Integrity file
# .yarn-integrity
# # dotenv environment variables file
# .env
# # next.js build output
# .next
================================================
FILE: .prettierrc.js
================================================
'use strict';
const config = require('@tunnckocore/prettier-config');
module.exports = {
...config,
overrides: [
{
files: ['**/*.md*'],
options: {
proseWrap: 'always',
printWidth: 80,
},
},
{
files: ['**/.all-contributorsrc'],
options: {
parser: 'json-stringify',
singleQuote: false,
},
},
],
};
================================================
FILE: CHANGELOG.md
================================================
# Changelog
### 3.5.4
- fix the `os.machine` breaking some dependents, fix [#994](https://github.com/node-formidable/formidable/issues/994)
- add Node 16, 18, 20, 22 to CI/CD
### 3.5.3
- security report by ZAST.AI help for some vulnerabilities addressing (primarily the random names generation)
- update failing tests
- update CI/CD workflows and actions;
- update CodeQL github action for security analysis
- update readme, links and badges
- update to use cuid2 (battle-tested `@paralleldrive/cuid2` package) for better random names - should not be breaking anything since it's still 25 characters long, but a lot safer and faster.
### 3.5.2
* fix: ([#982](https://github.com/node-formidable/formidable/pull/982)) make it easier to import hexoid with webpack
### 3.5.1
* fix: ([#945](https://github.com/node-formidable/formidable/pull/945)) multipart parser fix: flush or fail always (don't hang)
### 3.5.0
* feature: ([#944](https://github.com/node-formidable/formidable/pull/944)) Dual package: Can be imported as ES module and required as commonjs module
### 3.4.0
* feature: ([#940](https://github.com/node-formidable/formidable/pull/940)) form.parse returns a promise if no callback is provided
* it resolves with an array `[fields, files]`
### 3.3.2
* feature: ([#855](https://github.com/node-formidable/formidable/pull/855)) add options.createDirsFromUploads, see README for usage
* form.parse is an async function (ignore the promise)
* benchmarks: add e2e becnhmark with as many request as possible per second
* npm run to display all the commands
* mark as latest on npm
### 3.2.5
* fix: ([#881](https://github.com/node-formidable/formidable/pull/881)) fail earlier when maxFiles is exceeded
### 3.2.4
* fix: ([#857](https://github.com/node-formidable/formidable/pull/857)) improve keep extension
* The code from before 3.2.4 already removed some characters from the file extension. But not always. So it was inconsistent.
* The new code cuts the file extension at the first invalid character (invalid in a file extension).
* The characters that are considered invalid inside a file extension are all except the . numbers and a-Z.
* This change only has an effect if filename option is not used and keepextension option is used
### 3.2.3
* fix: ([#852](https://github.com/node-formidable/formidable/pull/852)) end event is emitted once
### 3.2.2
* refactor: ([#801](https://github.com/node-formidable/formidable/pull/801))
### 3.2.1
* fix: do not let empty file on error ([#796](https://github.com/node-formidable/formidable/pull/796))
* it was probably due to the fact that .destroy on a file stream does not always complete on time
### 3.2.0
* feat: maxFileSize option is now per file (as the name suggests) ([#791](https://github.com/node-formidable/formidable/pull/791))
* feat: add maxFiles option, default Infinity
* feat: add maxTotalFileSize, default is maxFileSize (for backwards compatibility)
* fix: minFileSize is per file
* fix: allowEmptyFiles fix in cases where one file is not empty
* fix: allowEmptyFiles false option by default
* fix: rename wrongly named error
* refactor: rename wrongly named maxFileSize into maxTotalFileSize
### 3.1.5
* fix: PersistentFile.toString ([#796](https://github.com/node-formidable/formidable/pull/796))
### 3.1.4
* fix: add missing pluginFailed error ([#794](https://github.com/node-formidable/formidable/pull/794))
* refactor: use explicit node imports (#786)
### 3.1.1
* feat: handle top level json array, string and number
### 3.1.0
* feat: add firstValues, readBooleans helpers
### 3.0.0
* feat: remove options.multiples ([#730](https://github.com/node-formidable/formidable/pull/730))
* use modern URLSearchParams https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams internally
* files and fields values are always arrays
* fields with [] in the name do not receive special treatment
* remove unused qs and querystring dependency
* feat: Use ES modules ([#727](https://github.com/node-formidable/formidable/pull/727))
* options.enabledPlugins must contain the plugin themselves instead of the plugins names
### 2.0.0
* feat: files are detected if a mimetype is present (previously it was based on filename)
* feat: add options.filter ([#716](https://github.com/node-formidable/formidable/pull/716))
* feat: add code and httpCode to most errors ([#686](https://github.com/node-formidable/formidable/pull/686))
* rename: option.hash into option.hashAlgorithm ([#689](https://github.com/node-formidable/formidable/pull/689))
* rename: file.path into file.filepath ([#689](https://github.com/node-formidable/formidable/pull/689))
* rename: file.type into file.mimetype ([#689](https://github.com/node-formidable/formidable/pull/689))
* refactor: split file.name into file.newFilename and file.originalFilename ([#689](https://github.com/node-formidable/formidable/pull/689))
* feat: prevent directory traversal attacks by default ([#689](https://github.com/node-formidable/formidable/pull/689))
* meta: stop including test files in npm ([7003c](https://github.com/node-formidable/formidable/commit/7003cd6133f90c384081accb51743688d5e1f4be))
* fix: handle invalid filenames ([d0a34](https://github.com/node-formidable/formidable/commit/d0a3484b048b8c177e62d66aecb03f5928f7a857))
* feat: add fileWriteStreamHandler option
* feat: add allowEmptyFiles and minFileSize options
* feat: Array support for fields and files ([#380](https://github.com/node-formidable/node-formidable/pull/380), [#340](https://github.com/node-formidable/node-formidable/pull/340), [#367](https://github.com/node-formidable/node-formidable/pull/367), [#33](https://github.com/node-formidable/node-formidable/issues/33), [#498](https://github.com/node-formidable/node-formidable/issues/498), [#280](https://github.com/node-formidable/node-formidable/issues/280), [#483](https://github.com/node-formidable/node-formidable/issues/483))
* possible partial fix of [#386](https://github.com/node-formidable/node-formidable/pull/386) with #380 (need tests and better implementation)
* refactor: use hasOwnProperty in check against files/fields ([#522](https://github.com/node-formidable/node-formidable/pull/522))
* meta: do not promote `IncomingForm` and add `exports.default` ([#529](https://github.com/node-formidable/node-formidable/pull/529))
* meta: Improve examples and tests ([#523](https://github.com/node-formidable/node-formidable/pull/523))
* refactor: First step of Code quality improvements ([#525](https://github.com/node-formidable/node-formidable/pull/525))
* chore(funding): remove patreon & add npm funding field ([#525](https://github.com/node-formidable/node-formidable/pull/532)
* feat: use Modern Streams API ([#531](https://github.com/node-formidable/node-formidable/pull/531))
* fix: urlencoded parsing to emit end [#543](https://github.com/node-formidable/node-formidable/pull/543), introduced in [#531](https://github.com/node-formidable/node-formidable/pull/531)
* fix(tests): include multipart and qs parser unit tests, part of [#415](https://github.com/node-formidable/node-formidable/issues/415)
* fix: reorganize exports + move parsers to `src/parsers/`
* fix: update docs and examples [#544](https://github.com/node-formidable/node-formidable/pull/544) ([#248](https://github.com/node-formidable/node-formidable/issues/248), [#335](https://github.com/node-formidable/node-formidable/issues/335), [#371](https://github.com/node-formidable/node-formidable/issues/371), [#372](https://github.com/node-formidable/node-formidable/issues/372), [#387](https://github.com/node-formidable/node-formidable/issues/387), partly [#471](https://github.com/node-formidable/node-formidable/issues/471), [#535](https://github.com/node-formidable/node-formidable/issues/535))
* feat: introduce Plugins API, fix silent failing tests ([#545](https://github.com/node-formidable/node-formidable/pull/545), [#391](https://github.com/node-formidable/node-formidable/pull/391), [#407](https://github.com/node-formidable/node-formidable/pull/407), [#386](https://github.com/node-formidable/node-formidable/pull/386), [#374](https://github.com/node-formidable/node-formidable/pull/374), [#521](https://github.com/node-formidable/node-formidable/pull/521), [#267](https://github.com/node-formidable/node-formidable/pull/267))
* fix: exposing file writable stream errors ([#520](https://github.com/node-formidable/node-formidable/pull/520), [#316](https://github.com/node-formidable/node-formidable/pull/316), [#469](https://github.com/node-formidable/node-formidable/pull/469), [#470](https://github.com/node-formidable/node-formidable/pull/470))
* feat: custom file (re)naming, thru options.filename ([#591](https://github.com/node-formidable/node-formidable/pull/591), [#84](https://github.com/node-formidable/node-formidable/issues/84), [#86](https://github.com/node-formidable/node-formidable/issues/86), [#94](https://github.com/node-formidable/node-formidable/issues/94), [#154](https://github.com/node-formidable/node-formidable/issues/154), [#158](https://github.com/node-formidable/node-formidable/issues/158), [#488](https://github.com/node-formidable/node-formidable/issues/488), [#595](https://github.com/node-formidable/node-formidable/issues/595))
### v1.2.1 (2018-03-20)
* `maxFileSize` option with default of 200MB (Charlike Mike Reagent, Nima Shahri)
* Simplified buffering in JSON parser to avoid denial of service attack (Kornel)
* Fixed upload file cleanup on aborted requests (liaoweiqiang)
* Fixed error handling of closed _writeStream (Vitalii)
### v1.1.1 (2017-01-15)
* Fix DeprecationWarning about os.tmpDir() (Christian)
* Update `buffer.write` order of arguments for Node 7 (Kornel Lesiński)
* JSON Parser emits error events to the IncomingForm (alessio.montagnani)
* Improved Content-Disposition parsing (Sebastien)
* Access WriteStream of fs during runtime instead of include time (Jonas Amundsen)
* Use built-in toString to convert buffer to hex (Charmander)
* Add hash to json if present (Nick Stamas)
* Add license to package.json (Simen Bekkhus)
### v1.0.14 (2013-05-03)
* Add failing hash tests. (Ben Trask)
* Enable hash calculation again (Eugene Girshov)
* Test for immediate data events (Tim Smart)
* Re-arrange IncomingForm#parse (Tim Smart)
### v1.0.13
* Only update hash if update method exists (Sven Lito)
* According to travis v0.10 needs to go quoted (Sven Lito)
* Bumping build node versions (Sven Lito)
* Additional fix for empty requests (Eugene Girshov)
* Change the default to 1000, to match the new Node behaviour. (OrangeDog)
* Add ability to control maxKeys in the querystring parser. (OrangeDog)
* Adjust test case to work with node 0.9.x (Eugene Girshov)
* Update package.json (Sven Lito)
* Path adjustment according to eb4468b (Markus Ast)
### v1.0.12
* Emit error on aborted connections (Eugene Girshov)
* Add support for empty requests (Eugene Girshov)
* Fix name/filename handling in Content-Disposition (jesperp)
* Tolerate malformed closing boundary in multipart (Eugene Girshov)
* Ignore preamble in multipart messages (Eugene Girshov)
* Add support for application/json (Mike Frey, Carlos Rodriguez)
* Add support for Base64 encoding (Elmer Bulthuis)
* Add File#toJSON (TJ Holowaychuk)
* Remove support for Node.js 0.4 & 0.6 (Andrew Kelley)
* Documentation improvements (Sven Lito, Andre Azevedo)
* Add support for application/octet-stream (Ion Lupascu, Chris Scribner)
* Use os.tmpdir() to get tmp directory (Andrew Kelley)
* Improve package.json (Andrew Kelley, Sven Lito)
* Fix benchmark script (Andrew Kelley)
* Fix scope issue in incoming_forms (Sven Lito)
* Fix file handle leak on error (OrangeDog)
---
[First commit, #3270eb4b1f8b (May 4th, 2010)](https://github.com/node-formidable/formidable/commit/3270eb4b1f8bb667b8c12f64c36a4e7b854216d8)
================================================
FILE: LICENSE
================================================
The MIT License (MIT)
Copyright (c) 2011-present Felix Geisendörfer, and contributors.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
<p align="center">
<img alt="npm formidable package logo" src="https://raw.githubusercontent.com/node-formidable/formidable/master/logo.png" />
</p>
# formidable [![npm version][npmv-img]][npmv-url] [![MIT license][license-img]][license-url] [![Libera Manifesto][libera-manifesto-img]][libera-manifesto-url] [![Twitter][twitter-img]][twitter-url]
> A Node.js module for parsing form data, especially file uploads.
[![Code style][codestyle-img]][codestyle-url]
[![linux build status][linux-build-img]][build-url]
[![macos build status][macos-build-img]][build-url]
<!-- [![codecoverage][codecov-img]][codecov-url] -->
If you have any _how-to_ kind of questions, please read the [Contributing
Guide][contributing-url] and [Code of Conduct][code_of_conduct-url]
documents.<br /> For bugs reports and feature requests, [please create an
issue][open-issue-url] or ping [@wgw_eth / @wgw_lol][twitter-url]
at Twitter.
[![Conventional Commits][ccommits-img]][ccommits-url]
[![Minimum Required Nodejs][nodejs-img]][npmv-url]
[![Buy me a Kofi][kofi-img]][kofi-url]
[![Make A Pull Request][prs-welcome-img]][prs-welcome-url]
<!-- [![Tidelift Subscription][tidelift-img]][tidelift-url] -->
<!-- [![Renovate App Status][renovateapp-img]][renovateapp-url] -->
This project is [semantically versioned](https://semver.org) and if you want support in migrating between versions you can schedule us for training or support us through donations, so we can prioritize.
> [!CAUTION]
> As of April 2025, old versions like v1 and v2 are still the most used, while they are deprecated for years -- they are also vulnerable to attacks if you are not implementing it properly. **Please upgrade!** We are here to help, and AI Editors & Agents could help a lot in such codemod-like migrations.
> [!TIP]
> If you are starting a fresh project, you can check out the `formidable-mini` which is a super minimal version of Formidable (not quite configurable yet, but when it does it could become the basis for `formidable@v4`), using web standards like FormData API and File API, and you can use it to stream uploads directly to S3 or other such services.
<!-- This project is [semantically versioned](https://semver.org) and available as
part of the [Tidelift Subscription][tidelift-url] for professional grade
assurances, enhanced support and security.
[Learn more.](https://tidelift.com/subscription/pkg/npm-formidable?utm_source=npm-formidable&utm_medium=referral&utm_campaign=enterprise)
_The maintainers of `formidable` and thousands of other packages are working
with Tidelift to deliver commercial support and maintenance for the Open Source
dependencies you use to build your applications. Save time, reduce risk, and
improve code health, while paying the maintainers of the exact dependencies you
use._ -->
[![][npm-weekly-img]][npmv-url] [![][npm-monthly-img]][npmv-url]
[![][npm-yearly-img]][npmv-url] [![][npm-alltime-img]][npmv-url]
## Project Status: Maintained
> [!NOTE]
> Check [VERSION NOTES](https://github.com/node-formidable/formidable/blob/master/VERSION_NOTES.md) for more information on v1, v2, and v3 plans, NPM dist-tags and branches._
This module was initially developed by
[**@felixge**](https://github.com/felixge) for
[Transloadit](http://transloadit.com/), a service focused on uploading and
encoding images and videos. It has been battle-tested against hundreds of GBs of
file uploads from a large variety of clients and is considered production-ready
and is used in production for years.
Currently, we are few maintainers trying to deal with it. :) More contributors
are always welcome! :heart: Jump on
[issue #412](https://github.com/felixge/node-formidable/issues/412) which is
closed, but if you are interested we can discuss it and add you after strict
rules, like enabling Two-Factor Auth in your npm and GitHub accounts.
## Highlights
- [Fast (~900-2500 mb/sec)](#benchmarks) & streaming multipart parser
- Automatically writing file uploads to disk (optional, see
[`options.fileWriteStreamHandler`](#options))
- [Plugins API](#useplugin-plugin) - allowing custom parsers and plugins
- Low memory footprint
- Graceful error handling
- Very high test coverage
## Install
This package is a dual ESM/commonjs package.
> [!NOTE]
> This project requires `Node.js >= 20`. Install it using [yarn](https://yarnpkg.com) or [npm](https://npmjs.com).<br /> _We highly recommend to use Yarn when you think to contribute to this project._
This is a low-level package, and if you're using a high-level framework it _may_
already be included. Check the examples below and the [examples/](https://github.com/node-formidable/formidable/tree/master/examples) folder.
```
# v2
npm install formidable@v2
# v3
npm install formidable
npm install formidable@v3
```
_**Note:** Future not ready releases will be published on `*-next` dist-tags for the corresponding version._
## Examples
For more examples look at the `examples/` directory.
### with Node.js http module
Parse an incoming file upload, with the
[Node.js's built-in `http` module](https://nodejs.org/api/http.html).
```js
import http from 'node:http';
import formidable, {errors as formidableErrors} from 'formidable';
const server = http.createServer(async (req, res) => {
if (req.url === '/api/upload' && req.method.toLowerCase() === 'post') {
// parse a file upload
const form = formidable({});
let fields;
let files;
try {
[fields, files] = await form.parse(req);
} catch (err) {
// example to check for a very specific error
if (err.code === formidableErrors.maxFieldsExceeded) {
}
console.error(err);
res.writeHead(err.httpCode || 400, { 'Content-Type': 'text/plain' });
res.end(String(err));
return;
}
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ fields, files }, null, 2));
return;
}
// show a file upload form
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end(`
<h2>With Node.js <code>"http"</code> module</h2>
<form action="/api/upload" enctype="multipart/form-data" method="post">
<div>Text field title: <input type="text" name="title" /></div>
<div>File: <input type="file" name="multipleFiles" multiple="multiple" /></div>
<input type="submit" value="Upload" />
</form>
`);
});
server.listen(8080, () => {
console.log('Server listening on http://localhost:8080/ ...');
});
```
### with Express.js
There are multiple variants to do this, but Formidable just need Node.js Request
stream, so something like the following example should work just fine, without
any third-party [Express.js](https://ghub.now.sh/express) middleware.
Or try the
[examples/with-express.js](https://github.com/node-formidable/formidable/blob/master/examples/with-express.js)
```js
import express from 'express';
import formidable from 'formidable';
const app = express();
app.get('/', (req, res) => {
res.send(`
<h2>With <code>"express"</code> npm package</h2>
<form action="/api/upload" enctype="multipart/form-data" method="post">
<div>Text field title: <input type="text" name="title" /></div>
<div>File: <input type="file" name="someExpressFiles" multiple="multiple" /></div>
<input type="submit" value="Upload" />
</form>
`);
});
app.post('/api/upload', (req, res, next) => {
const form = formidable({});
form.parse(req, (err, fields, files) => {
if (err) {
next(err);
return;
}
res.json({ fields, files });
});
});
app.listen(3000, () => {
console.log('Server listening on http://localhost:3000 ...');
});
```
### with Koa and Formidable
Of course, with [Koa v1, v2 or future v3](https://ghub.now.sh/koa) the things
are very similar. You can use `formidable` manually as shown below or through
the [koa-better-body](https://ghub.now.sh/koa-better-body) package which is
using `formidable` under the hood and support more features and different
request bodies, check its documentation for more info.
_Note: this example is assuming Koa v2. Be aware that you should pass `ctx.req`
which is Node.js's Request, and **NOT** the `ctx.request` which is Koa's Request
object - there is a difference._
```js
import Koa from 'Koa';
import formidable from 'formidable';
const app = new Koa();
app.on('error', (err) => {
console.error('server error', err);
});
app.use(async (ctx, next) => {
if (ctx.url === '/api/upload' && ctx.method.toLowerCase() === 'post') {
const form = formidable({});
// not very elegant, but that's for now if you don't want to use `koa-better-body`
// or other middlewares.
await new Promise((resolve, reject) => {
form.parse(ctx.req, (err, fields, files) => {
if (err) {
reject(err);
return;
}
ctx.set('Content-Type', 'application/json');
ctx.status = 200;
ctx.state = { fields, files };
ctx.body = JSON.stringify(ctx.state, null, 2);
resolve();
});
});
await next();
return;
}
// show a file upload form
ctx.set('Content-Type', 'text/html');
ctx.status = 200;
ctx.body = `
<h2>With <code>"koa"</code> npm package</h2>
<form action="/api/upload" enctype="multipart/form-data" method="post">
<div>Text field title: <input type="text" name="title" /></div>
<div>File: <input type="file" name="koaFiles" multiple="multiple" /></div>
<input type="submit" value="Upload" />
</form>
`;
});
app.use((ctx) => {
console.log('The next middleware is called');
console.log('Results:', ctx.state);
});
app.listen(3000, () => {
console.log('Server listening on http://localhost:3000 ...');
});
```
## Benchmarks
The benchmark is quite old, from the old codebase. But maybe quite true though.
Previously the numbers was around ~500 mb/sec. Currently with moving to the new
Node.js Streams API it's faster. You can clearly see the differences between the
Node versions.
_Note: a lot better benchmarking could and should be done in future._
Benchmarked on 8GB RAM, Xeon X3440 (2.53 GHz, 4 cores, 8 threads)
```
~/github/node-formidable master
❯ nve --parallel 8 10 12 13 node benchmark/bench-multipart-parser.js
⬢ Node 8
1261.08 mb/sec
⬢ Node 10
1113.04 mb/sec
⬢ Node 12
2107.00 mb/sec
⬢ Node 13
2566.42 mb/sec
```

## API
### Formidable / IncomingForm
All shown are equivalent.
_Please pass [`options`](#options) to the function/constructor, not by assigning
them to the instance `form`_
```js
import formidable from 'formidable';
const form = formidable(options);
```
### Options
See it's defaults in [src/Formidable.js DEFAULT_OPTIONS](./src/Formidable.js)
(the `DEFAULT_OPTIONS` constant).
- `options.encoding` **{string}** - default `'utf-8'`; sets encoding for
incoming form fields,
- `options.uploadDir` **{string}** - default `os.tmpdir()`; the directory for
placing file uploads in. You can move them later by using `fs.rename()`.
- `options.keepExtensions` **{boolean}** - default `false`; to include the
extensions of the original files or not
- `options.allowEmptyFiles` **{boolean}** - default `false`; allow upload empty
files
- `options.minFileSize` **{number}** - default `1` (1byte); the minium size of
uploaded file.
- `options.maxFiles` **{number}** - default `Infinity`;
limit the amount of uploaded files, set Infinity for unlimited
- `options.maxFileSize` **{number}** - default `200 * 1024 * 1024` (200mb);
limit the size of each uploaded file.
- `options.maxTotalFileSize` **{number}** - default `options.maxFileSize`;
limit the size of the batch of uploaded files.
- `options.maxFields` **{number}** - default `1000`; limit the number of fields, set Infinity for unlimited
- `options.maxFieldsSize` **{number}** - default `20 * 1024 * 1024` (20mb);
limit the amount of memory all fields together (except files) can allocate in
bytes.
- `options.hashAlgorithm` **{string | false}** - default `false`; include checksums calculated
for incoming files, set this to some hash algorithm, see
[crypto.createHash](https://nodejs.org/api/crypto.html#crypto_crypto_createhash_algorithm_options)
for available algorithms
- `options.fileWriteStreamHandler` **{function}** - default `null`, which by
default writes to host machine file system every file parsed; The function
should return an instance of a
[Writable stream](https://nodejs.org/api/stream.html#stream_class_stream_writable)
that will receive the uploaded file data. With this option, you can have any
custom behavior regarding where the uploaded file data will be streamed for.
If you are looking to write the file uploaded in other types of cloud storages
(AWS S3, Azure blob storage, Google cloud storage) or private file storage,
this is the option you're looking for. When this option is defined the default
behavior of writing the file in the host machine file system is lost.
- `options.filename` **{function}** - default `undefined` Use it to control
newFilename. Must return a string. Will be joined with options.uploadDir.
- `options.filter` **{function}** - default function that always returns true.
Use it to filter files before they are uploaded. Must return a boolean. Will not make the form.parse error
- `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
where part can be decomposed as
```js
const { originalFilename, mimetype} = part;
```
_**Note:** If this size of combined fields, or size of some file is exceeded, an
`'error'` event is fired._
```js
// The amount of bytes received for this form so far.
form.bytesReceived;
```
```js
// The expected number of bytes in this form.
form.bytesExpected;
```
#### `options.filter` **{function}** function ({name, originalFilename, mimetype}) -> boolean
Behaves like Array.filter: Returning false will simply ignore the file and go to the next.
```js
const options = {
filter: function ({name, originalFilename, mimetype}) {
// keep only images
return mimetype && mimetype.includes("image");
}
};
```
**Note:** use an outside variable to cancel all uploads upon the first error
**Note:** use form.emit('error') to make form.parse error
```js
let cancelUploads = false;// create variable at the same scope as form
const options = {
filter: function ({name, originalFilename, mimetype}) {
// keep only images
const valid = mimetype && mimetype.includes("image");
if (!valid) {
form.emit('error', new formidableErrors.default('invalid type', 0, 400)); // optional make form.parse error
cancelUploads = true; //variable to make filter return false after the first problem
}
return valid && !cancelUploads;
}
};
```
### .parse(request, ?callback)
Parses an incoming Node.js `request` containing form data. If `callback` is not provided a promise is returned.
```js
const form = formidable({ uploadDir: __dirname });
form.parse(req, (err, fields, files) => {
console.log('fields:', fields);
console.log('files:', files);
});
// with Promise
const [fields, files] = await form.parse(req);
```
You may overwrite this method if you are interested in directly accessing the
multipart stream. Doing so will disable any `'field'` / `'file'` events
processing which would occur otherwise, making you fully responsible for
handling the processing.
About `uploadDir`, given the following directory structure
```
project-name
├── src
│ └── server.js
│
└── uploads
└── image.jpg
```
`__dirname` would be the same directory as the source file itself (src)
```js
`${__dirname}/../uploads`
```
to put files in uploads.
Omitting `__dirname` would make the path relative to the current working directory. This would be the same if server.js is launched from src but not project-name.
`null` will use default which is `os.tmpdir()`
Note: If the directory does not exist, the uploaded files are __silently discarded__. To make sure it exists:
```js
import {createNecessaryDirectoriesSync} from "filesac";
const uploadPath = `${__dirname}/../uploads`;
createNecessaryDirectoriesSync(`${uploadPath}/x`);
```
In the example below, we listen on couple of events and direct them to the
`data` listener, so you can do whatever you choose there, based on whether its
before the file been emitted, the header value, the header name, on field, on
file and etc.
Or the other way could be to just override the `form.onPart` as it's shown a bit
later.
```js
form.once('error', console.error);
form.on('fileBegin', (formname, file) => {
form.emit('data', { name: 'fileBegin', formname, value: file });
});
form.on('file', (formname, file) => {
form.emit('data', { name: 'file', formname, value: file });
});
form.on('field', (fieldName, fieldValue) => {
form.emit('data', { name: 'field', key: fieldName, value: fieldValue });
});
form.once('end', () => {
console.log('Done!');
});
// If you want to customize whatever you want...
form.on('data', ({ name, key, value, buffer, start, end, formname, ...more }) => {
if (name === 'partBegin') {
}
if (name === 'partData') {
}
if (name === 'headerField') {
}
if (name === 'headerValue') {
}
if (name === 'headerEnd') {
}
if (name === 'headersEnd') {
}
if (name === 'field') {
console.log('field name:', key);
console.log('field value:', value);
}
if (name === 'file') {
console.log('file:', formname, value);
}
if (name === 'fileBegin') {
console.log('fileBegin:', formname, value);
}
});
```
### .use(plugin: Plugin)
A method that allows you to extend the Formidable library. By default we include
4 plugins, which essentially are adapters to plug the different built-in parsers.
**The plugins added by this method are always enabled.**
_See [src/plugins/](./src/plugins/) for more detailed look on default plugins._
The `plugin` param has such signature:
```typescript
function(formidable: Formidable, options: Options): void;
```
The architecture is simple. The `plugin` is a function that is passed with the
Formidable instance (the `form` across the README examples) and the options.
**Note:** the plugin function's `this` context is also the same instance.
```js
const form = formidable({ keepExtensions: true });
form.use((self, options) => {
// self === this === form
console.log('woohoo, custom plugin');
// do your stuff; check `src/plugins` for inspiration
});
form.parse(req, (error, fields, files) => {
console.log('done!');
});
```
**Important to note**, is that inside plugin `this.options`, `self.options` and
`options` MAY or MAY NOT be the same. General best practice is to always use the
`this`, so you can later test your plugin independently and more easily.
If you want to disable some parsing capabilities of Formidable, you can disable
the plugin which corresponds to the parser. For example, if you want to disable
multipart parsing (so the [src/parsers/Multipart.js](./src/parsers/Multipart.js)
which is used in [src/plugins/multipart.js](./src/plugins/multipart.js)), then
you can remove it from the `options.enabledPlugins`, like so
```js
import formidable, {octetstream, querystring, json} from "formidable";
const form = formidable({
hashAlgorithm: 'sha1',
enabledPlugins: [octetstream, querystring, json],
});
```
**Be aware** that the order _MAY_ be important too. The names corresponds 1:1 to
files in [src/plugins/](./src/plugins) folder.
Pull requests for new built-in plugins MAY be accepted - for example, more
advanced querystring parser. Add your plugin as a new file in `src/plugins/`
folder (lowercased) and follow how the other plugins are made.
### form.onPart
If you want to use Formidable to only handle certain parts for you, you can do
something similar. Or see
[#387](https://github.com/node-formidable/node-formidable/issues/387) for
inspiration, you can for example validate the mime-type.
```js
const form = formidable();
form.onPart = (part) => {
part.on('data', (buffer) => {
// do whatever you want here
});
};
```
For example, force Formidable to be used only on non-file "parts" (i.e., html
fields)
```js
const form = formidable();
form.onPart = function (part) {
// let formidable handle only non-file parts
if (part.originalFilename === '' || !part.mimetype) {
// used internally, please do not override!
form._handlePart(part);
}
};
```
### File
```ts
export interface File {
// The size of the uploaded file in bytes.
// If the file is still being uploaded (see `'fileBegin'` event),
// this property says how many bytes of the file have been written to disk yet.
file.size: number;
// The path this file is being written to. You can modify this in the `'fileBegin'` event in
// case you are unhappy with the way formidable generates a temporary path for your files.
file.filepath: string;
// The name this file had according to the uploading client.
file.originalFilename: string | null;
// calculated based on options provided
file.newFilename: string | null;
// The mime type of this file, according to the uploading client.
file.mimetype: string | null;
// A Date object (or `null`) containing the time this file was last written to.
// Mostly here for compatibility with the [W3C File API Draft](http://dev.w3.org/2006/webapi/FileAPI/).
file.mtime: Date | null;
file.hashAlgorithm: false | |'sha1' | 'md5' | 'sha256'
// If `options.hashAlgorithm` calculation was set, you can read the hex digest out of this var (at the end it will be a string)
file.hash: string | object | null;
}
```
#### file.toJSON()
This method returns a JSON-representation of the file, allowing you to
`JSON.stringify()` the file which is useful for logging and responding to
requests.
### Events
#### `'progress'`
Emitted after each incoming chunk of data that has been parsed. Can be used to
roll your own progress bar. **Warning** Use this only for server side progress bar. On the client side better use `XMLHttpRequest` with `xhr.upload.onprogress =`
```js
form.on('progress', (bytesReceived, bytesExpected) => {});
```
#### `'field'`
Emitted whenever a field / value pair has been received.
```js
form.on('field', (name, value) => {});
```
#### `'fileBegin'`
Emitted whenever a new file is detected in the upload stream. Use this event if
you want to stream the file to somewhere else while buffering the upload on the
file system.
```js
form.on('fileBegin', (formName, file) => {
// accessible here
// formName the name in the form (<input name="thisname" type="file">) or http filename for octetstream
// file.originalFilename http filename or null if there was a parsing error
// file.newFilename generated hexoid or what options.filename returned
// file.filepath default pathname as per options.uploadDir and options.filename
// file.filepath = CUSTOM_PATH // to change the final path
});
```
#### `'file'`
Emitted whenever a field / file pair has been received. `file` is an instance of
`File`.
```js
form.on('file', (formname, file) => {
// same as fileBegin, except
// it is too late to change file.filepath
// file.hash is available if options.hash was used
});
```
#### `'error'`
Emitted when there is an error processing the incoming form. A request that
experiences an error is automatically paused, you will have to manually call
`request.resume()` if you want the request to continue firing `'data'` events.
May have `error.httpCode` and `error.code` attached.
```js
form.on('error', (err) => {});
```
#### `'aborted'`
Emitted when the request was aborted by the user. Right now this can be due to a
'timeout' or 'close' event on the socket. After this event is emitted, an
`error` event will follow. In the future there will be a separate 'timeout'
event (needs a change in the node core).
```js
form.on('aborted', () => {});
```
#### `'end'`
Emitted when the entire request has been received, and all contained files have
finished flushing to disk. This is a great place for you to send your response.
```js
form.on('end', () => {});
```
### Helpers
#### firstValues
Gets first values of fields, like pre 3.0.0 without multiples pass in a list of optional exceptions where arrays of strings is still wanted (`<select multiple>` for example)
```js
import { firstValues } from 'formidable/src/helpers/firstValues.js';
// ...
form.parse(request, async (error, fieldsMultiple, files) => {
if (error) {
//...
}
const exceptions = ['thisshouldbeanarray'];
const fieldsSingle = firstValues(form, fieldsMultiple, exceptions);
// ...
```
#### readBooleans
Html form input type="checkbox" only send the value "on" if checked,
convert it to booleans for each input that is expected to be sent as a checkbox, only use after firstValues or similar was called.
```js
import { firstValues } from 'formidable/src/helpers/firstValues.js';
import { readBooleans } from 'formidable/src/helpers/readBooleans.js';
// ...
form.parse(request, async (error, fieldsMultiple, files) => {
if (error) {
//...
}
const fieldsSingle = firstValues(form, fieldsMultiple);
const expectedBooleans = ['checkbox1', 'wantsNewsLetter', 'hasACar'];
const fieldsWithBooleans = readBooleans(fieldsSingle, expectedBooleans);
// ...
```
## Changelog
[./CHANGELOG.md](./CHANGELOG.md)
## Ports & Credits
- [multipart-parser](http://github.com/FooBarWidget/multipart-parser): a C++
parser based on formidable
- [Ryan Dahl](https://x.com/rough__sea) for his work on
[http-parser](http://github.com/ry/http-parser) which heavily inspired the
initial `multipart_parser.js`.
## Contributing
If the documentation is unclear or has a typo, please click on the page's `Edit`
button (pencil icon) and suggest a correction. If you would like to help us fix
a bug or add a new feature, please check our [Contributing
Guide][contributing-url]. Pull requests are welcome!
Thanks goes to these wonderful people
([emoji key](https://allcontributors.org/docs/en/emoji-key)):
<!-- ALL-CONTRIBUTORS-LIST:START -->
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<table>
<tr>
<td align="center"><a href="https://twitter.com/felixge"><img src="https://avatars3.githubusercontent.com/u/15000?s=460&v=4" width="100px;" alt=""/><br /><sub><b>Felix Geisendörfer</b></sub></a><br /><a href="https://github.com/node-formidable/node-formidable/commits?author=felixge" title="Code">💻</a> <a href="#design-felixge" title="Design">🎨</a> <a href="#ideas-felixge" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/node-formidable/node-formidable/commits?author=felixge" title="Documentation">📖</a></td>
<td align="center"><a href="https://tunnckoCore.com"><img src="https://avatars3.githubusercontent.com/u/5038030?v=4" width="100px;" alt=""/><br /><sub><b>Charlike Mike Reagent</b></sub></a><br /><a href="https://github.com/node-formidable/node-formidable/issues?q=author%3AtunnckoCore" title="Bug reports">🐛</a> <a href="#infra-tunnckoCore" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#design-tunnckoCore" title="Design">🎨</a> <a href="https://github.com/node-formidable/node-formidable/commits?author=tunnckoCore" title="Code">💻</a> <a href="https://github.com/node-formidable/node-formidable/commits?author=tunnckoCore" title="Documentation">📖</a> <a href="#example-tunnckoCore" title="Examples">💡</a> <a href="#ideas-tunnckoCore" title="Ideas, Planning, & Feedback">🤔</a> <a href="#maintenance-tunnckoCore" title="Maintenance">🚧</a> <a href="https://github.com/node-formidable/node-formidable/commits?author=tunnckoCore" title="Tests">⚠️</a></td>
<td align="center"><a href="https://github.com/kedarv"><img src="https://avatars1.githubusercontent.com/u/1365665?v=4" width="100px;" alt=""/><br /><sub><b>Kedar</b></sub></a><br /><a href="https://github.com/node-formidable/node-formidable/commits?author=kedarv" title="Code">💻</a> <a href="https://github.com/node-formidable/node-formidable/commits?author=kedarv" title="Tests">⚠️</a> <a href="#question-kedarv" title="Answering Questions">💬</a> <a href="https://github.com/node-formidable/node-formidable/issues?q=author%3Akedarv" title="Bug reports">🐛</a></td>
<td align="center"><a href="https://github.com/GrosSacASac"><img src="https://avatars0.githubusercontent.com/u/5721194?v=4" width="100px;" alt=""/><br /><sub><b>Walle Cyril</b></sub></a><br /><a href="#question-GrosSacASac" title="Answering Questions">💬</a> <a href="https://github.com/node-formidable/node-formidable/issues?q=author%3AGrosSacASac" title="Bug reports">🐛</a> <a href="https://github.com/node-formidable/node-formidable/commits?author=GrosSacASac" title="Code">💻</a> <a href="#financial-GrosSacASac" title="Financial">💵</a> <a href="#ideas-GrosSacASac" title="Ideas, Planning, & Feedback">🤔</a> <a href="#maintenance-GrosSacASac" title="Maintenance">🚧</a></td>
<td align="center"><a href="https://github.com/xarguments"><img src="https://avatars2.githubusercontent.com/u/40522463?v=4" width="100px;" alt=""/><br /><sub><b>Xargs</b></sub></a><br /><a href="#question-xarguments" title="Answering Questions">💬</a> <a href="https://github.com/node-formidable/node-formidable/issues?q=author%3Axarguments" title="Bug reports">🐛</a> <a href="https://github.com/node-formidable/node-formidable/commits?author=xarguments" title="Code">💻</a> <a href="#maintenance-xarguments" title="Maintenance">🚧</a></td>
<td align="center"><a href="https://github.com/Amit-A"><img src="https://avatars1.githubusercontent.com/u/7987238?v=4" width="100px;" alt=""/><br /><sub><b>Amit-A</b></sub></a><br /><a href="#question-Amit-A" title="Answering Questions">💬</a> <a href="https://github.com/node-formidable/node-formidable/issues?q=author%3AAmit-A" title="Bug reports">🐛</a> <a href="https://github.com/node-formidable/node-formidable/commits?author=Amit-A" title="Code">💻</a></td>
</tr>
<tr>
<td align="center"><a href="https://charmander.me/"><img src="https://avatars1.githubusercontent.com/u/1889843?v=4" width="100px;" alt=""/><br /><sub><b>Charmander</b></sub></a><br /><a href="#question-charmander" title="Answering Questions">💬</a> <a href="https://github.com/node-formidable/node-formidable/issues?q=author%3Acharmander" title="Bug reports">🐛</a> <a href="https://github.com/node-formidable/node-formidable/commits?author=charmander" title="Code">💻</a> <a href="#ideas-charmander" title="Ideas, Planning, & Feedback">🤔</a> <a href="#maintenance-charmander" title="Maintenance">🚧</a></td>
<td align="center"><a href="https://twitter.com/dylan_piercey"><img src="https://avatars2.githubusercontent.com/u/4985201?v=4" width="100px;" alt=""/><br /><sub><b>Dylan Piercey</b></sub></a><br /><a href="#ideas-DylanPiercey" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center"><a href="http://ochrona.jawne.info.pl"><img src="https://avatars1.githubusercontent.com/u/3618479?v=4" width="100px;" alt=""/><br /><sub><b>Adam Dobrawy</b></sub></a><br /><a href="https://github.com/node-formidable/node-formidable/issues?q=author%3Aad-m" title="Bug reports">🐛</a> <a href="https://github.com/node-formidable/node-formidable/commits?author=ad-m" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/amitrohatgi"><img src="https://avatars3.githubusercontent.com/u/12177021?v=4" width="100px;" alt=""/><br /><sub><b>amitrohatgi</b></sub></a><br /><a href="#ideas-amitrohatgi" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center"><a href="https://github.com/fengxinming"><img src="https://avatars2.githubusercontent.com/u/6262382?v=4" width="100px;" alt=""/><br /><sub><b>Jesse Feng</b></sub></a><br /><a href="https://github.com/node-formidable/node-formidable/issues?q=author%3Afengxinming" title="Bug reports">🐛</a></td>
<td align="center"><a href="https://qtmsheep.com"><img src="https://avatars1.githubusercontent.com/u/7271496?v=4" width="100px;" alt=""/><br /><sub><b>Nathanael Demacon</b></sub></a><br /><a href="#question-quantumsheep" title="Answering Questions">💬</a> <a href="https://github.com/node-formidable/node-formidable/commits?author=quantumsheep" title="Code">💻</a> <a href="https://github.com/node-formidable/node-formidable/pulls?q=is%3Apr+reviewed-by%3Aquantumsheep" title="Reviewed Pull Requests">👀</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/MunMunMiao"><img src="https://avatars1.githubusercontent.com/u/18216142?v=4" width="100px;" alt=""/><br /><sub><b>MunMunMiao</b></sub></a><br /><a href="https://github.com/node-formidable/node-formidable/issues?q=author%3AMunMunMiao" title="Bug reports">🐛</a></td>
<td align="center"><a href="https://github.com/gabipetrovay"><img src="https://avatars0.githubusercontent.com/u/1170398?v=4" width="100px;" alt=""/><br /><sub><b>Gabriel Petrovay</b></sub></a><br /><a href="https://github.com/node-formidable/node-formidable/issues?q=author%3Agabipetrovay" title="Bug reports">🐛</a> <a href="https://github.com/node-formidable/node-formidable/commits?author=gabipetrovay" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/Elzair"><img src="https://avatars0.githubusercontent.com/u/2352818?v=4" width="100px;" alt=""/><br /><sub><b>Philip Woods</b></sub></a><br /><a href="https://github.com/node-formidable/node-formidable/commits?author=Elzair" title="Code">💻</a> <a href="#ideas-Elzair" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center"><a href="https://github.com/dmolim"><img src="https://avatars2.githubusercontent.com/u/7090374?v=4" width="100px;" alt=""/><br /><sub><b>Dmitry Ivonin</b></sub></a><br /><a href="https://github.com/node-formidable/node-formidable/commits?author=dmolim" title="Documentation">📖</a></td>
<td align="center"><a href="https://audiobox.fm"><img src="https://avatars1.githubusercontent.com/u/12844?v=4" width="100px;" alt=""/><br /><sub><b>Claudio Poli</b></sub></a><br /><a href="https://github.com/node-formidable/node-formidable/commits?author=masterkain" title="Code">💻</a></td>
</tr>
</table>
<!-- markdownlint-enable -->
<!-- prettier-ignore-end -->
<!-- ALL-CONTRIBUTORS-LIST:END -->
From a [Felix blog post](https://felixge.de/2013/03/11/the-pull-request-hack/):
- [Sven Lito](https://github.com/svnlto) for fixing bugs and merging patches
- [egirshov](https://github.com/egirshov) for contributing many improvements to the node-formidable multipart parser
- [Andrew Kelley](https://github.com/superjoe30) for also helping with fixing bugs and making improvements
- [Mike Frey](https://github.com/mikefrey) for contributing JSON support
## License
Formidable is licensed under the [MIT License][license-url].
<!-- badges -->
<!-- prettier-ignore-start -->
[codestyle-url]: https://github.com/airbnb/javascript
[codestyle-img]: https://badgen.net/badge/code%20style/airbnb%20%2B%20prettier/ff5a5f?icon=airbnb&cache=300
[codecov-url]: https://codecov.io/gh/node-formidable/formidable
[codecov-img]: https://badgen.net/codecov/c/github/node-formidable/formidable/master?icon=codecov
[npmv-canary-img]: https://badgen.net/npm/v/formidable/canary?icon=npm
[npmv-dev-img]: https://badgen.net/npm/v/formidable/dev?icon=npm
[npmv-img]: https://badgen.net/npm/v/formidable?icon=npm
[npmv-url]: https://npmjs.com/package/formidable
[license-img]: https://badgen.net/npm/license/formidable
[license-url]: https://github.com/node-formidable/formidable/blob/master/LICENSE
[chat-img]: https://badgen.net/badge/chat/on%20gitter/46BC99?icon=gitter
[chat-url]: https://gitter.im/node-formidable/Lobby
[libera-manifesto-url]: https://liberamanifesto.com
[libera-manifesto-img]: https://badgen.net/badge/libera/manifesto/grey
[renovateapp-url]: https://renovatebot.com
[renovateapp-img]: https://badgen.net/badge/renovate/enabled/green?cache=300
[prs-welcome-img]: https://badgen.net/badge/PRs/welcome/green?cache=300
[prs-welcome-url]: http://makeapullrequest.com
[twitter-url]: https://twitter.com/wgw_eth
[twitter-img]: https://badgen.net/badge/twitter/follow/wgw_eth?icon=twitter&color=1da1f2&cache=30
[npm-weekly-img]: https://badgen.net/npm/dw/formidable?icon=npm&cache=300
[npm-monthly-img]: https://badgen.net/npm/dm/formidable?icon=npm&cache=300
[npm-yearly-img]: https://badgen.net/npm/dy/formidable?icon=npm&cache=300
[npm-alltime-img]: https://badgen.net/npm/dt/formidable?icon=npm&cache=300&label=total%20downloads
[nodejs-img]: https://badgen.net/badge/node/>=%2010.13/green?cache=300
[ccommits-url]: https://conventionalcommits.org/
[ccommits-img]: https://badgen.net/badge/conventional%20commits/v1.0.0/green?cache=300
[contributing-url]: https://github.com/node-formidable/.github/blob/master/CONTRIBUTING.md
[code_of_conduct-url]: https://github.com/node-formidable/.github/blob/master/CODE_OF_CONDUCT.md
[open-issue-url]: https://github.com/node-formidable/formidable/issues/new
[tidelift-url]: https://tidelift.com/subscription/pkg/npm-formidable?utm_source=npm-formidable&utm_medium=referral&utm_campaign=enterprise
[tidelift-img]: https://badgen.net/badge/tidelift/subscription/4B5168?labelColor=F6914D
[kofi-url]: https://ko-fi.com/tunnckoCore/commissions
[kofi-img]: https://badgen.net/badge/ko-fi/support/29abe0c2?cache=300&icon=https://rawcdn.githack.com/tunnckoCore/badgen-icons/f8264c6414e0bec449dd86f2241d50a9b89a1203/icons/kofi.svg
[linux-build-img]: https://badgen.net/github/checks/node-formidable/formidable/master?label=linux%20build&icon=github
[macos-build-img]: https://badgen.net/github/checks/node-formidable/formidable/master?label=macos%20build&icon=github
[windows-build-img]: https://badgen.net/github/checks/node-formidable/formidable/master/windows?cache=300&label=windows%20build&icon=github
[build-url]: https://github.com/node-formidable/formidable/actions
<!-- prettier-ignore-end -->
================================================
FILE: README_pt_BR.md
================================================
<p align="center">
<img alt="npm formidable package logo" src="https://raw.githubusercontent.com/node-formidable/formidable/master/logo.png" />
</p>
# formidable [![npm version][npmv-img]][npmv-url] [![MIT license][license-img]][license-url] [![Libera Manifesto][libera-manifesto-img]][libera-manifesto-url] [![Twitter][twitter-img]][twitter-url]
> A Node.js module for parsing form data, especially file uploads.
[![Code style][codestyle-img]][codestyle-url]
[![codecoverage][codecov-img]][codecov-url]
[![linux build status][linux-build-img]][build-url]
[![macos build status][macos-build-img]][build-url]
Se você tiver qualquer tipo de pergunta sobre _como_ fazer, por favor leia o [Contributing
Guia][contributing-url] e [Código de Conduta][code_of_conduct-url]
documentos.<br /> Para relatórios de bugs e solicitações de recursos, [crie uma
issue][open-issue-url] ou ping [@tunnckoCore / @3a1FcBx0](https://twitter.com/3a1FcBx0)
no Twitter.
[![Conventional Commits][ccommits-img]][ccommits-url]
[![Minimum Required Nodejs][nodejs-img]][npmv-url]
[![Tidelift Subscription][tidelift-img]][tidelift-url]
[![Buy me a Kofi][kofi-img]][kofi-url]
[![Renovate App Status][renovateapp-img]][renovateapp-url]
[![Make A Pull Request][prs-welcome-img]][prs-welcome-url]
Este projeto é [semanticamente versionado](https://semver.org) e está disponível como
parte da [Assinatura Tidelift][tidelift-url] para nível profissional
garantias, suporte aprimorado e segurança.
[Saiba mais.](https://tidelift.com/subscription/pkg/npm-formidable?utm_source=npm-formidable&utm_medium=referral&utm_campaign=enterprise)
_Os mantenedores do `formidable` e milhares de outros pacotes estão trabalhando
com Tidelift para fornecer suporte comercial e manutenção para o Open Source
dependências que você usa para construir seus aplicativos. Economize tempo, reduza riscos e
melhorar a integridade do código, enquanto paga aos mantenedores das dependências exatas que você
usar._
[![][npm-weekly-img]][npmv-url] [![][npm-monthly-img]][npmv-url]
[![][npm-yearly-img]][npmv-url] [![][npm-alltime-img]][npmv-url]
## Status do Projeto: Mantido
_Verifique [VERSION NOTES](https://github.com/node-formidable/formidable/blob/master/VERSION_NOTES.md) para obter mais informações sobre os planos v1, v2 e v3, NPM dist-tags e branches._
Este módulo foi inicialmente desenvolvido por
[**@felixge**](https://github.com/felixge) para
[Transloadit](http://transloadit.com/), um serviço focado em upload e
codificação de imagens e vídeos. Foi testado em batalha contra centenas de GBs de
uploads de arquivos de uma grande variedade de clientes e é considerado pronto para produção
e é usado na produção por anos.
Atualmente, somos poucos mantenedores tentando lidar com isso. :) Mais contribuidores
são sempre bem-vindos! ❤️ Pule
[issue #412](https://github.com/felixge/node-formidable/issues/412) que está
fechado, mas se você estiver interessado, podemos discuti-lo e adicioná-lo após regras estritas, como ativar o Two-Factor Auth em suas contas npm e GitHub.
## Destaques
- [Rápido (~ 900-2500 mb/seg)](#benchmarks) e analisador multiparte de streaming
- Gravar uploads de arquivos automaticamente no disco (opcional, consulte
[`options.fileWriteStreamHandler`](#options))
- [API de plug-ins](#useplugin-plugin) - permitindo analisadores e plug-ins personalizados
- Baixo consumo de memória
- Tratamento de erros gracioso
- Cobertura de teste muito alta
## Instalar
Este projeto requer `Node.js >= 10.13`. Instale-o usando
[yarn](https://yarnpkg.com) ou [npm](https://npmjs.com).<br /> _Nós altamente
recomendamos usar o Yarn quando pensar em contribuir para este projeto._
Este é um pacote de baixo nível e, se você estiver usando uma estrutura de alto nível, _pode_ já estar incluído. Verifique os exemplos
abaixo e a pasta [examples/](https://github.com/node-formidable/formidable/tree/master/examples).
```
# v2
npm install formidable
npm install formidable@v2
# v3
npm install formidable@v3
```
_**Nota:** Em um futuro próximo, a v3 será publicada na dist-tag `latest` do NPM.
Versões futuras não prontas serão publicadas nas dist-tags `*-next` para a versão correspondente._
## Exemplos
Para mais exemplos veja o diretório `examples/`.
### com módulo http Node.js
Analisar um upload de arquivo de entrada, com o
[Módulo `http` integrado do Node.js](https://nodejs.org/api/http.html).
```js
import http from 'node:http';
import formidable, {errors as formidableErrors} from 'formidable';
const server = http.createServer((req, res) => {
if (req.url === '/api/upload' && req.method.toLowerCase() === 'post') {
// analisar um upload de arquivo
const form = formidable({});
form.parse(req, (err, fields, files) => {
if (err) {
// exemplo para verificar um erro muito específico
if (err.code === formidableErrors.maxFieldsExceeded) {
}
res.writeHead(err.httpCode || 400, { 'Content-Type': 'text/plain' });
res.end(String(err));
return;
}
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ fields, files }, null, 2));
});
return;
}
// mostrar um formulário de upload de arquivo
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end(`
<h2>With Node.js <code>"http"</code> module</h2>
<form action="/api/upload" enctype="multipart/form-data" method="post">
<div>Text field title: <input type="text" name="title" /></div>
<div>File: <input type="file" name="multipleFiles" multiple="multiple" /></div>
<input type="submit" value="Upload" />
</form>
`);
});
server.listen(8080, () => {
console.log('Server listening on http://localhost:8080/ ...');
});
```
### com Express.js
Existem várias variantes para fazer isso, mas o Formidable só precisa do Node.js Request
stream, então algo como o exemplo a seguir deve funcionar bem, sem nenhum middleware [Express.js](https://ghub.now.sh/express) de terceiros.
Ou tente o
[examples/with-express.js](https://github.com/node-formidable/formidable/blob/master/examples/with-express.js)
```js
import express from 'express';
import formidable from 'formidable';
const app = express();
app.get('/', (req, res) => {
res.send(`
<h2>With <code>"express"</code> npm package</h2>
<form action="/api/upload" enctype="multipart/form-data" method="post">
<div>Text field title: <input type="text" name="title" /></div>
<div>File: <input type="file" name="someExpressFiles" multiple="multiple" /></div>
<input type="submit" value="Upload" />
</form>
`);
});
app.post('/api/upload', (req, res, next) => {
const form = formidable({});
form.parse(req, (err, fields, files) => {
if (err) {
next(err);
return;
}
res.json({ fields, files });
});
});
app.listen(3000, () => {
console.log('Server listening on http://localhost:3000 ...');
});
```
### com Koa e Formidable
Claro, com [Koa v1, v2 ou future v3](https://ghub.now.sh/koa) as coisas
sao muito parecidas. Você pode usar `formidable` manualmente como mostrado abaixo ou através
do pacote [koa-better-body](https://ghub.now.sh/koa-better-body) que é
usando `formidable` sob o capô e suporte a mais recursos e diferentes
corpos de solicitação, verifique sua documentação para mais informações.
_Nota: este exemplo está assumindo Koa v2. Esteja ciente de que você deve passar `ctx.req`
que é a solicitação do Node.js e **NÃO** o `ctx.request` que é a solicitação do Koa
objeto - há uma diferença._
```js
import Koa from 'Koa';
import formidable from 'formidable';
const app = new Koa();
app.on('error', (err) => {
console.error('server error', err);
});
app.use(async (ctx, next) => {
if (ctx.url === '/api/upload' && ctx.method.toLowerCase() === 'post') {
const form = formidable({});
// não muito elegante, mas é por enquanto se você não quiser usar `koa-better-body`
// ou outros middlewares.
await new Promise((resolve, reject) => {
form.parse(ctx.req, (err, fields, files) => {
if (err) {
reject(err);
return;
}
ctx.set('Content-Type', 'application/json');
ctx.status = 200;
ctx.state = { fields, files };
ctx.body = JSON.stringify(ctx.state, null, 2);
resolve();
});
});
await next();
return;
}
// mostrar um formulário de upload de arquivo
ctx.set('Content-Type', 'text/html');
ctx.status = 200;
ctx.body = `
<h2>With <code>"koa"</code> npm package</h2>
<form action="/api/upload" enctype="multipart/form-data" method="post">
<div>Text field title: <input type="text" name="title" /></div>
<div>File: <input type="file" name="koaFiles" multiple="multiple" /></div>
<input type="submit" value="Upload" />
</form>
`;
});
app.use((ctx) => {
console.log('The next middleware is called');
console.log('Results:', ctx.state);
});
app.listen(3000, () => {
console.log('Server listening on http://localhost:3000 ...');
});
```
## Benchmarks
O benchmark é bastante antigo, da antiga base de código. Mas talvez seja bem verdade.
Anteriormente, os números giravam em torno de ~ 500 mb/s. Atualmente com a mudança para o novo
Node.js Streams API, é mais rápido. Você pode ver claramente as diferenças entre as
versões do Node.
_Observação: um benchmarking muito melhor pode e deve ser feito no futuro._
Benchmark realizado em 8 GB de RAM, Xeon X3440 (2,53 GHz, 4 núcleos, 8 threads)
```
~/github/node-formidable master
❯ nve --parallel 8 10 12 13 node benchmark/bench-multipart-parser.js
⬢ Node 8
1261.08 mb/sec
⬢ Node 10
1113.04 mb/sec
⬢ Node 12
2107.00 mb/sec
⬢ Node 13
2566.42 mb/sec
```

## API
### Formidable / IncomingForm
Todos os mostrados são equivalentes.
_Por favor, passe [`options`](#options) para a função/construtor, não atribuindo
eles para a instância `form`_
```js
import formidable from 'formidable';
const form = formidable(options);
```
### Opções
Veja seus padrões em [src/Formidable.js DEFAULT_OPTIONS](./src/Formidable.js)
(a constante `DEFAULT_OPTIONS`).
- `options.encoding` **{string}** - padrão `'utf-8'`; define a codificação para campos de formulário de entrada,
- `options.uploadDir` **{string}** - padrão `os.tmpdir()`; o diretório para colocar os uploads de arquivos. Você pode movê-los mais tarde usando `fs.rename()`.
- `options.keepExtensions` **{boolean}** - padrão `false`; incluir as extensões dos arquivos originais ou não
- `options.allowEmptyFiles` **{boolean}** - padrão `false`; permitir upload de arquivos vazios
- `options.minFileSize` **{number}** - padrão `1` (1byte); o tamanho mínimo do arquivo carregado.
- `options.maxFiles` **{number}** - padrão `Infinity`;
limitar a quantidade de arquivos carregados, defina Infinity para ilimitado
- `options.maxFileSize` **{number}** - padrão `200 * 1024 * 1024` (200mb);
limitar o tamanho de cada arquivo carregado.
- `options.maxTotalFileSize` **{number}** - padrão `options.maxFileSize`;
limitar o tamanho do lote de arquivos carregados.
- `options.maxFields` **{number}** - padrão `1000`; limite o número de campos, defina Infinity para ilimitado
- `options.maxFieldsSize` **{number}** - padrão `20 * 1024 * 1024` (20mb);
limitar a quantidade de memória que todos os campos juntos (exceto arquivos) podem alocar em
bytes.
- `options.hashAlgorithm` **{string | false}** - padrão `false`; incluir checksums calculados
para arquivos recebidos, defina isso para algum algoritmo de hash, consulte
[crypto.createHash](https://nodejs.org/api/crypto.html#crypto_crypto_createhash_algorithm_options)
para algoritmos disponíveis
- `options.fileWriteStreamHandler` **{function}** - padrão `null`, que por padrão grava no sistema de arquivos da máquina host cada arquivo analisado; A função
deve retornar uma instância de um
[fluxo gravável](https://nodejs.org/api/stream.html#stream_class_stream_writable)
que receberá os dados do arquivo carregado. Com esta opção, você pode ter qualquer
comportamento personalizado em relação a onde os dados do arquivo carregado serão transmitidos.
Se você deseja gravar o arquivo carregado em outros tipos de armazenamento em nuvem
(AWS S3, armazenamento de blob do Azure, armazenamento em nuvem do Google) ou armazenamento de arquivo privado,
esta é a opção que você está procurando. Quando esta opção é definida, o comportamento padrão de gravar o arquivo no sistema de arquivos da máquina host é perdido.
- `options.filename` **{function}** - padrão `undefined` Use-o para controlar newFilename. Deve retornar uma string. Será associado a options.uploadDir.
- `options.filter` **{function}** - função padrão que sempre retorna verdadeiro.
Use-o para filtrar arquivos antes de serem carregados. Deve retornar um booleano.
#### `options.filename` **{function}** function (name, ext, part, form) -> string
onde a parte pode ser decomposta como
```js
const { originalFilename, mimetype} = part;
```
_**Observação:** Se este tamanho de campos combinados, ou tamanho de algum arquivo for excedido, um
O evento `'error'` é disparado._
```js
// A quantidade de bytes recebidos para este formulário até agora.
form.bytesReceived;
```
```js
// O número esperado de bytes neste formulário.
form.bytesExpected;
```
#### `options.filter` **{function}** function ({name, originalFilename, mimetype}) -> boolean
**Observação:** use uma variável externa para cancelar todos os uploads no primeiro erro
```js
const options = {
filter: function ({name, originalFilename, mimetype}) {
// manter apenas imagens
return mimetype && mimetype.includes("image");
}
};
```
### .parse(request, callback)
Analisa uma `request` do Node.js recebida contendo dados de formulário. Se `callback` for
fornecido, todos os campos e arquivos são coletados e passados para o retorno de chamada.
```js
const form = formidable({ uploadDir: __dirname });
form.parse(req, (err, fields, files) => {
console.log('fields:', fields);
console.log('files:', files);
});
```
Você pode substituir esse método se estiver interessado em acessar diretamente o
fluxo de várias partes. Fazer isso desativará qualquer processamento de eventos `'field'` / `'file'`
que ocorreria de outra forma, tornando você totalmente responsável por lidar com o processamento.
Sobre `uploadDir`, dada a seguinte estrutura de diretório
```
project-name
├── src
│ └── server.js
│
└── uploads
└── image.jpg
```
`__dirname` seria o mesmo diretório que o próprio arquivo de origem (src)
```js
`${__dirname}/../uploads`
```
para colocar arquivos em uploads.
Omitir `__dirname` tornaria o caminho relativo ao diretório de trabalho atual. Isso seria o mesmo se server.js fosse iniciado a partir de src, mas não de project-name.
`null` usará o padrão que é `os.tmpdir()`
Nota: Se o diretório não existir, os arquivos carregados são __silenciosamente descartados__. Para ter certeza de que existe:
```js
import {createNecessaryDirectoriesSync} from "filesac";
const uploadPath = `${__dirname}/../uploads`;
createNecessaryDirectoriesSync(`${uploadPath}/x`);
```
No exemplo abaixo, escutamos alguns eventos e os direcionamos para o ouvinte `data`, para
que você possa fazer o que quiser lá, com base em se é antes do arquivo ser emitido, o valor do
cabeçalho, o nome do cabeçalho, no campo , em arquivo e etc.
Ou a outra maneira poderia ser apenas substituir o `form.onPart` como é mostrado um pouco
mais tarde.
```js
form.once('error', console.error);
form.on('fileBegin', (formname, file) => {
form.emit('data', { name: 'fileBegin', formname, value: file });
});
form.on('file', (formname, file) => {
form.emit('data', { name: 'file', formname, value: file });
});
form.on('field', (fieldName, fieldValue) => {
form.emit('data', { name: 'field', key: fieldName, value: fieldValue });
});
form.once('end', () => {
console.log('Done!');
});
// Se você quiser personalizar o que quiser...
form.on('data', ({ name, key, value, buffer, start, end, formname, ...more }) => {
if (name === 'partBegin') {
}
if (name === 'partData') {
}
if (name === 'headerField') {
}
if (name === 'headerValue') {
}
if (name === 'headerEnd') {
}
if (name === 'headersEnd') {
}
if (name === 'field') {
console.log('field name:', key);
console.log('field value:', value);
}
if (name === 'file') {
console.log('file:', formname, value);
}
if (name === 'fileBegin') {
console.log('fileBegin:', formname, value);
}
});
```
### .use(plugin: Plugin)
Um método que permite estender a biblioteca Formidable. Por padrão, incluímos
4 plug-ins, que são essencialmente adaptadores para conectar os diferentes analisadores integrados.
**Os plugins adicionados por este método estão sempre ativados.**
_Consulte [src/plugins/](./src/plugins/) para uma visão mais detalhada dos plug-ins padrão._
O parâmetro `plugin` tem essa assinatura:
```typescript
function(formidable: Formidable, options: Options): void;
```
A arquitetura é simples. O `plugin` é uma função que é passada com a instância Formidable (o `form` nos exemplos README) e as opções.
**Observação:** o contexto `this` da função do plug-in também é a mesma instância.
```js
const form = formidable({ keepExtensions: true });
form.use((self, options) => {
// self === this === form
console.log('woohoo, custom plugin');
// faça suas coisas; verifique `src/plugins` para inspiração
});
form.parse(req, (error, fields, files) => {
console.log('done!');
});
```
**Importante observar**, é que dentro do plugin `this.options`, `self.options` e
`options` PODEM ou NÃO ser iguais. A melhor prática geral é sempre usar o
`this`, para que você possa testar seu plugin mais tarde de forma independente e mais fácil.
Se você quiser desabilitar alguns recursos de análise do Formidable, você pode desabilitar
o plugin que corresponde ao analisador. Por exemplo, se você deseja desabilitar a análise de
várias partes (para que o [src/parsers/Multipart.js](./src/parsers/Multipart.js)
que é usado em [src/plugins/multipart.js](./src/plugins/multipart.js)), então
você pode removê-lo do `options.enabledPlugins`, assim
```js
import formidable, {octetstream, querystring, json} from "formidable";
const form = formidable({
hashAlgorithm: 'sha1',
enabledPlugins: [octetstream, querystring, json],
});
```
**Esteja ciente** de que a ordem _PODE_ ser importante também. Os nomes correspondem 1:1 a
arquivos na pasta [src/plugins/](./src/plugins).
Solicitações pull para novos plug-ins integrados PODEM ser aceitas - por exemplo, analisador de
querystring mais avançado. Adicione seu plugin como um novo arquivo na pasta `src/plugins/` (em letras minúsculas) e
siga como os outros plugins são feitos.
### form.onPart
Se você quiser usar Formidable para manipular apenas algumas partes para você, você pode fazer
alguma coisa similar. ou ver
[#387](https://github.com/node-formidable/node-formidable/issues/387) para
inspiração, você pode, por exemplo, validar o tipo mime.
```js
const form = formidable();
form.onPart = (part) => {
part.on('data', (buffer) => {
// faça o que quiser aqui
});
};
```
Por exemplo, force Formidable a ser usado apenas em "partes" que não sejam de arquivo (ou seja, html
Campos)
```js
const form = formidable();
form.onPart = function (part) {
// deixe formidável lidar apenas com partes não arquivadas
if (part.originalFilename === '' || !part.mimetype) {
// usado internamente, por favor, não substitua!
form._handlePart(part);
}
};
```
### Arquivo
```ts
export interface File {
// O tamanho do arquivo enviado em bytes.
// Se o arquivo ainda estiver sendo carregado (veja o evento `'fileBegin'`),
// esta propriedade diz quantos bytes do arquivo já foram gravados no disco.
file.size: number;
// O caminho em que este arquivo está sendo gravado. Você pode modificar isso no evento `'fileBegin'`
// caso você esteja insatisfeito com a forma como o formidable gera um caminho temporário para seus arquivos.
file.filepath: string;
// O nome que este arquivo tinha de acordo com o cliente de upload.
file.originalFilename: string | null;
// calculado com base nas opções fornecidas.
file.newFilename: string | null;
// O tipo mime deste arquivo, de acordo com o cliente de upload.
file.mimetype: string | null;
// Um objeto Date (ou `null`) contendo a hora em que este arquivo foi gravado pela última vez.
// Principalmente aqui para compatibilidade com o [W3C File API Draft](http://dev.w3.org/2006/webapi/FileAPI/).
file.mtime: Date | null;
file.hashAlgorithm: false | |'sha1' | 'md5' | 'sha256'
// Se o cálculo `options.hashAlgorithm` foi definido, você pode ler o resumo hexadecimal desta var (no final, será uma string)
file.hash: string | object | null;
}
```
#### file.toJSON()
Este método retorna uma representação JSON do arquivo, permitindo que você `JSON.stringify()`
o arquivo que é útil para registrar e responder a solicitações.
### Eventos
#### `'progress'`
Emitido após cada bloco de entrada de dados que foi analisado. Pode ser usado para rolar sua própria barra de progresso. **Aviso** Use isso
apenas para a barra de progresso do lado do servidor. No lado do cliente, é melhor usar `XMLHttpRequest` com `xhr.upload.onprogress =`
```js
form.on('progress', (bytesReceived, bytesExpected) => {});
```
#### `'field'`
Emitido sempre que um par campo/valor é recebido.
```js
form.on('field', (name, value) => {});
```
#### `'fileBegin'`
Emitido sempre que um novo arquivo é detectado no fluxo de upload.
Use este evento se desejar transmitir o arquivo para outro lugar enquanto armazena o upload no sistema de arquivos.
```js
form.on('fileBegin', (formName, file) => {
// acessível aqui
// formName o nome no formulário (<input name="thisname" type="file">) ou http filename para octetstream
// file.originalFilename http filename ou null se houver um erro de análise
// file.newFilename gerou hexoid ou o que options.filename retornou
// file.filepath nome do caminho padrão de acordo com options.uploadDir e options.filename
// file.filepath = CUSTOM_PATH // para alterar o caminho final
});
```
#### `'file'`
Emitido sempre que um par campo/arquivo é recebido. `file` é uma instância de
`File`.
```js
form.on('file', (formname, file) => {
// o mesmo que fileBegin, exceto
// é muito tarde para alterar file.filepath
// file.hash está disponível se options.hash foi usado
});
```
#### `'error'`
Emitido quando há um erro no processamento do formulário recebido. Uma solicitação que
apresenta um erro é pausada automaticamente, você terá que chamar manualmente
`request.resume()` se você quiser que a requisição continue disparando eventos `'data'`.
Pode ter `error.httpCode` e `error.code` anexados.
```js
form.on('error', (err) => {});
```
#### `'aborted'`
Emitido quando a requisição foi abortada pelo usuário. Agora isso pode ser devido a um
evento 'timeout' ou 'close' no soquete. Após este evento ser emitido, um
O evento `error` seguirá. No futuro, haverá um 'timeout' separado
evento (precisa de uma mudança no núcleo do nó).
```js
form.on('aborted', () => {});
```
#### `'end'`
Emitido quando toda a solicitação foi recebida e todos os arquivos contidos foram
liberados para o disco. Este é um ótimo lugar para você enviar sua resposta.
```js
form.on('end', () => {});
```
### Helpers
#### firstValues
Obtém os primeiros valores dos campos, como pré 3.0.0 sem passar múltiplos em uma
lista de exceções opcionais onde arrays de strings ainda são desejados (`<select multiple>` por exemplo)
```js
import { firstValues } from 'formidable/src/helpers/firstValues.js';
// ...
form.parse(request, async (error, fieldsMultiple, files) => {
if (error) {
//...
}
const exceptions = ['thisshouldbeanarray'];
const fieldsSingle = firstValues(form, fieldsMultiple, exceptions);
// ...
```
#### readBooleans
Html form input type="checkbox" envia apenas o valor "on" se marcado,
converta-o em booleanos para cada entrada que deve ser enviada como uma caixa de seleção, use somente após a chamada de firstValues ou similar.
```js
import { firstValues } from 'formidable/src/helpers/firstValues.js';
import { readBooleans } from 'formidable/src/helpers/readBooleans.js';
// ...
form.parse(request, async (error, fieldsMultiple, files) => {
if (error) {
//...
}
const fieldsSingle = firstValues(form, fieldsMultiple);
const expectedBooleans = ['checkbox1', 'wantsNewsLetter', 'hasACar'];
const fieldsWithBooleans = readBooleans(fieldsSingle, expectedBooleans);
// ...
```
## Changelog
[./CHANGELOG.md](./CHANGELOG.md)
## Ports & Créditos
- [multipart-parser](http://github.com/FooBarWidget/multipart-parser): um analisador C++ baseado em formidável
- [Ryan Dahl](https://x.com/rough__sea) por seu trabalho em
[http-parser](http://github.com/ry/http-parser) que inspirou fortemente o `multipart_parser.js` inicial.
## Contribuindo
Se a documentação não estiver clara ou tiver um erro de digitação, clique no botão `Edit` da página (ícone de lápis) e sugira uma correção.
Se você gostaria de nos ajudar a corrigir
um bug ou adicionar um novo recurso, verifique nosso [Contributing
Guide][contribuindo-url]. Pull requests são bem-vindos!
Agradecimentos vão para essas pessoas maravilhosas
([emoji key](https://allcontributors.org/docs/en/emoji-key)):
<!-- ALL-CONTRIBUTORS-LIST:START -->
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<table>
<tr>
<td align="center"><a href="https://twitter.com/felixge"><img src="https://avatars3.githubusercontent.com/u/15000?s=460&v=4" width="100px;" alt=""/><br /><sub><b>Felix Geisendörfer</b></sub></a><br /><a href="https://github.com/node-formidable/node-formidable/commits?author=felixge" title="Code">💻</a> <a href="#design-felixge" title="Design">🎨</a> <a href="#ideas-felixge" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/node-formidable/node-formidable/commits?author=felixge" title="Documentation">📖</a></td>
<td align="center"><a href="https://tunnckoCore.com"><img src="https://avatars3.githubusercontent.com/u/5038030?v=4" width="100px;" alt=""/><br /><sub><b>Charlike Mike Reagent</b></sub></a><br /><a href="https://github.com/node-formidable/node-formidable/issues?q=author%3AtunnckoCore" title="Bug reports">🐛</a> <a href="#infra-tunnckoCore" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#design-tunnckoCore" title="Design">🎨</a> <a href="https://github.com/node-formidable/node-formidable/commits?author=tunnckoCore" title="Code">💻</a> <a href="https://github.com/node-formidable/node-formidable/commits?author=tunnckoCore" title="Documentation">📖</a> <a href="#example-tunnckoCore" title="Examples">💡</a> <a href="#ideas-tunnckoCore" title="Ideas, Planning, & Feedback">🤔</a> <a href="#maintenance-tunnckoCore" title="Maintenance">🚧</a> <a href="https://github.com/node-formidable/node-formidable/commits?author=tunnckoCore" title="Tests">⚠️</a></td>
<td align="center"><a href="https://github.com/kedarv"><img src="https://avatars1.githubusercontent.com/u/1365665?v=4" width="100px;" alt=""/><br /><sub><b>Kedar</b></sub></a><br /><a href="https://github.com/node-formidable/node-formidable/commits?author=kedarv" title="Code">💻</a> <a href="https://github.com/node-formidable/node-formidable/commits?author=kedarv" title="Tests">⚠️</a> <a href="#question-kedarv" title="Answering Questions">💬</a> <a href="https://github.com/node-formidable/node-formidable/issues?q=author%3Akedarv" title="Bug reports">🐛</a></td>
<td align="center"><a href="https://github.com/GrosSacASac"><img src="https://avatars0.githubusercontent.com/u/5721194?v=4" width="100px;" alt=""/><br /><sub><b>Walle Cyril</b></sub></a><br /><a href="#question-GrosSacASac" title="Answering Questions">💬</a> <a href="https://github.com/node-formidable/node-formidable/issues?q=author%3AGrosSacASac" title="Bug reports">🐛</a> <a href="https://github.com/node-formidable/node-formidable/commits?author=GrosSacASac" title="Code">💻</a> <a href="#financial-GrosSacASac" title="Financial">💵</a> <a href="#ideas-GrosSacASac" title="Ideas, Planning, & Feedback">🤔</a> <a href="#maintenance-GrosSacASac" title="Maintenance">🚧</a></td>
<td align="center"><a href="https://github.com/xarguments"><img src="https://avatars2.githubusercontent.com/u/40522463?v=4" width="100px;" alt=""/><br /><sub><b>Xargs</b></sub></a><br /><a href="#question-xarguments" title="Answering Questions">💬</a> <a href="https://github.com/node-formidable/node-formidable/issues?q=author%3Axarguments" title="Bug reports">🐛</a> <a href="https://github.com/node-formidable/node-formidable/commits?author=xarguments" title="Code">💻</a> <a href="#maintenance-xarguments" title="Maintenance">🚧</a></td>
<td align="center"><a href="https://github.com/Amit-A"><img src="https://avatars1.githubusercontent.com/u/7987238?v=4" width="100px;" alt=""/><br /><sub><b>Amit-A</b></sub></a><br /><a href="#question-Amit-A" title="Answering Questions">💬</a> <a href="https://github.com/node-formidable/node-formidable/issues?q=author%3AAmit-A" title="Bug reports">🐛</a> <a href="https://github.com/node-formidable/node-formidable/commits?author=Amit-A" title="Code">💻</a></td>
</tr>
<tr>
<td align="center"><a href="https://charmander.me/"><img src="https://avatars1.githubusercontent.com/u/1889843?v=4" width="100px;" alt=""/><br /><sub><b>Charmander</b></sub></a><br /><a href="#question-charmander" title="Answering Questions">💬</a> <a href="https://github.com/node-formidable/node-formidable/issues?q=author%3Acharmander" title="Bug reports">🐛</a> <a href="https://github.com/node-formidable/node-formidable/commits?author=charmander" title="Code">💻</a> <a href="#ideas-charmander" title="Ideas, Planning, & Feedback">🤔</a> <a href="#maintenance-charmander" title="Maintenance">🚧</a></td>
<td align="center"><a href="https://twitter.com/dylan_piercey"><img src="https://avatars2.githubusercontent.com/u/4985201?v=4" width="100px;" alt=""/><br /><sub><b>Dylan Piercey</b></sub></a><br /><a href="#ideas-DylanPiercey" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center"><a href="http://ochrona.jawne.info.pl"><img src="https://avatars1.githubusercontent.com/u/3618479?v=4" width="100px;" alt=""/><br /><sub><b>Adam Dobrawy</b></sub></a><br /><a href="https://github.com/node-formidable/node-formidable/issues?q=author%3Aad-m" title="Bug reports">🐛</a> <a href="https://github.com/node-formidable/node-formidable/commits?author=ad-m" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/amitrohatgi"><img src="https://avatars3.githubusercontent.com/u/12177021?v=4" width="100px;" alt=""/><br /><sub><b>amitrohatgi</b></sub></a><br /><a href="#ideas-amitrohatgi" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center"><a href="https://github.com/fengxinming"><img src="https://avatars2.githubusercontent.com/u/6262382?v=4" width="100px;" alt=""/><br /><sub><b>Jesse Feng</b></sub></a><br /><a href="https://github.com/node-formidable/node-formidable/issues?q=author%3Afengxinming" title="Bug reports">🐛</a></td>
<td align="center"><a href="https://qtmsheep.com"><img src="https://avatars1.githubusercontent.com/u/7271496?v=4" width="100px;" alt=""/><br /><sub><b>Nathanael Demacon</b></sub></a><br /><a href="#question-quantumsheep" title="Answering Questions">💬</a> <a href="https://github.com/node-formidable/node-formidable/commits?author=quantumsheep" title="Code">💻</a> <a href="https://github.com/node-formidable/node-formidable/pulls?q=is%3Apr+reviewed-by%3Aquantumsheep" title="Reviewed Pull Requests">👀</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/MunMunMiao"><img src="https://avatars1.githubusercontent.com/u/18216142?v=4" width="100px;" alt=""/><br /><sub><b>MunMunMiao</b></sub></a><br /><a href="https://github.com/node-formidable/node-formidable/issues?q=author%3AMunMunMiao" title="Bug reports">🐛</a></td>
<td align="center"><a href="https://github.com/gabipetrovay"><img src="https://avatars0.githubusercontent.com/u/1170398?v=4" width="100px;" alt=""/><br /><sub><b>Gabriel Petrovay</b></sub></a><br /><a href="https://github.com/node-formidable/node-formidable/issues?q=author%3Agabipetrovay" title="Bug reports">🐛</a> <a href="https://github.com/node-formidable/node-formidable/commits?author=gabipetrovay" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/Elzair"><img src="https://avatars0.githubusercontent.com/u/2352818?v=4" width="100px;" alt=""/><br /><sub><b>Philip Woods</b></sub></a><br /><a href="https://github.com/node-formidable/node-formidable/commits?author=Elzair" title="Code">💻</a> <a href="#ideas-Elzair" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center"><a href="https://github.com/dmolim"><img src="https://avatars2.githubusercontent.com/u/7090374?v=4" width="100px;" alt=""/><br /><sub><b>Dmitry Ivonin</b></sub></a><br /><a href="https://github.com/node-formidable/node-formidable/commits?author=dmolim" title="Documentation">📖</a></td>
<td align="center"><a href="https://audiobox.fm"><img src="https://avatars1.githubusercontent.com/u/12844?v=4" width="100px;" alt=""/><br /><sub><b>Claudio Poli</b></sub></a><br /><a href="https://github.com/node-formidable/node-formidable/commits?author=masterkain" title="Code">💻</a></td>
</tr>
</table>
<!-- markdownlint-enable -->
<!-- prettier-ignore-end -->
<!-- ALL-CONTRIBUTORS-LIST:END -->
De uma [postagem do blog Felix](https://felixge.de/2013/03/11/the-pull-request-hack/):
- [Sven Lito](https://github.com/svnlto) por corrigir bugs e mesclar patches
- [egirshov](https://github.com/egirshov) por contribuir com muitas melhorias para o analisador multipartes formidável de nós
- [Andrew Kelley](https://github.com/superjoe30) por também ajudar a corrigir bugs e fazer melhorias
- [Mike Frey](https://github.com/mikefrey) por contribuir com suporte JSON
## Licença
Formidable é licenciado sob a [MIT License][license-url].
<!-- badges -->
<!-- prettier-ignore-start -->
[codestyle-url]: https://github.com/airbnb/javascript
[codestyle-img]: https://badgen.net/badge/code%20style/airbnb%20%2B%20prettier/ff5a5f?icon=airbnb&cache=300
[codecov-url]: https://codecov.io/gh/node-formidable/formidable
[codecov-img]: https://badgen.net/codecov/c/github/node-formidable/formidable/master?icon=codecov
[npmv-canary-img]: https://badgen.net/npm/v/formidable/canary?icon=npm
[npmv-dev-img]: https://badgen.net/npm/v/formidable/dev?icon=npm
[npmv-img]: https://badgen.net/npm/v/formidable?icon=npm
[npmv-url]: https://npmjs.com/package/formidable
[license-img]: https://badgen.net/npm/license/formidable
[license-url]: https://github.com/node-formidable/formidable/blob/master/LICENSE
[chat-img]: https://badgen.net/badge/chat/on%20gitter/46BC99?icon=gitter
[chat-url]: https://gitter.im/node-formidable/Lobby
[libera-manifesto-url]: https://liberamanifesto.com
[libera-manifesto-img]: https://badgen.net/badge/libera/manifesto/grey
[renovateapp-url]: https://renovatebot.com
[renovateapp-img]: https://badgen.net/badge/renovate/enabled/green?cache=300
[prs-welcome-img]: https://badgen.net/badge/PRs/welcome/green?cache=300
[prs-welcome-url]: http://makeapullrequest.com
[twitter-url]: https://twitter.com/3a1fcBx0
[twitter-img]: https://badgen.net/twitter/follow/3a1fcBx0?icon=twitter&color=1da1f2&cache=300
[npm-weekly-img]: https://badgen.net/npm/dw/formidable?icon=npm&cache=300
[npm-monthly-img]: https://badgen.net/npm/dm/formidable?icon=npm&cache=300
[npm-yearly-img]: https://badgen.net/npm/dy/formidable?icon=npm&cache=300
[npm-alltime-img]: https://badgen.net/npm/dt/formidable?icon=npm&cache=300&label=total%20downloads
[nodejs-img]: https://badgen.net/badge/node/>=%2010.13/green?cache=300
[ccommits-url]: https://conventionalcommits.org/
[ccommits-img]: https://badgen.net/badge/conventional%20commits/v1.0.0/green?cache=300
[contributing-url]: https://github.com/node-formidable/.github/blob/master/CONTRIBUTING.md
[code_of_conduct-url]: https://github.com/node-formidable/.github/blob/master/CODE_OF_CONDUCT.md
[open-issue-url]: https://github.com/node-formidable/formidable/issues/new
[tidelift-url]: https://tidelift.com/subscription/pkg/npm-formidable?utm_source=npm-formidable&utm_medium=referral&utm_campaign=enterprise
[tidelift-img]: https://badgen.net/badge/tidelift/subscription/4B5168?labelColor=F6914D
[kofi-url]: https://ko-fi.com/tunnckoCore/commissions
[kofi-img]: https://badgen.net/badge/ko-fi/support/29abe0c2?cache=300&icon=https://rawcdn.githack.com/tunnckoCore/badgen-icons/f8264c6414e0bec449dd86f2241d50a9b89a1203/icons/kofi.svg
[linux-build-img]: https://badgen.net/github/checks/node-formidable/formidable/master?cache=30&label=linux%20build&icon=github
[macos-build-img]: https://badgen.net/github/checks/node-formidable/formidable/master?cache=30&label=macos%20build&icon=github
[build-url]: https://github.com/node-formidable/formidable/actions
<!-- prettier-ignore-end -->
================================================
FILE: VERSION_NOTES.md
================================================
# Important Notes for v1, v2, and v3
For more info, check the [CHANGELOG](https://github.com/node-formidable/formidable/blob/master/CHANGELOG.md) on the master branch.
## v1 is deprecated
All `v1` versions are deprecated in NPM for over 2 years. You can find it at `formidable@v1` on NPM, and on [v1 branch][v1branch] on GitHub.
We highly recommend to use `v2` or `v3`. Both are already in use by many, especially `v2` which was on `formidable@canary` for 2 years.
- **Status: Not Maintained!**
- We won't provide support or accept reports on that version.
- **No Backporting:** bugfixes, security fixes, or new features WILL NOT happen!
- Please move to at least **v2**!
- Try with installing `formidable@v2` and if still have the problem - report!
## v2 is going to be deprecated
The `v2` is available as `formidable@v2`.
The source code is available **only** on [v2 branch][v2branch].
If you want to use v2, it's recommended to lock and use the v2 dist-tag `formidable@v2-latest`.
**Main Differences from v1:**
- Better organization and modernized code, requiring newer Node.js versions (>= v10).
- A lot of bugfixes, closed issues, merged or closed PRs.
- Better docs, new features (plugins, parsers, options) and optimizations.
## v3 - ESModules, Monorepo structure
We recommend to use `formidable@latest` to install, as it uses more modern Node.js Streams, has support for more stuff.
You can see more info and track some ideas on [issue#635](https://github.com/node-formidable/formidable/issues/635).
- The source code can be found on the [master branch][v3branch] on GitHub.
- It is published as `formidable@latest`
- Dropping older Node.js versions, requiring higher than v12-v14.
- Dropping v1 compatibility.
- Rewritten to ESModules, more optimizations.
- Moving to monorepo structure, more plugins & helper utils.
[v1branch]: https://github.com/node-formidable/formidable/tree/v1-legacy
[v2branch]: https://github.com/node-formidable/formidable/tree/v2-latest
[v3branch]: https://github.com/node-formidable/formidable/tree/master
================================================
FILE: benchmark/2022-11-30-i5-9600k.txt
================================================
npm run bench
> formidable@3.2.5 bench
> node benchmark
4132.23 mb/sec
PS C:\files\formidable> node -v
v18.0.0
npm run bench
> formidable@3.2.5 bench
> node benchmark
3952.57 mb/sec
PS C:\files\formidable> node -v
v19.2.0
C:\files\formidable> bombardier --body-file="./README.md" --method=POST
--duration=10s --connections=100 http://localhost:3000/api/upload
Bombarding http://localhost:3000/api/upload for 10s using 100 connection(s)[====================================================================] 10s
Done!
Statistics Avg Stdev Max
Reqs/sec 2824.09 1512.74 6881.85
Latency 35.51ms 37.38ms 0.98s
HTTP codes:
1xx - 0, 2xx - 28163, 3xx - 0, 4xx - 0, 5xx - 0
others - 0
Throughput: 102.08MB/s
================================================
FILE: benchmark/e2e.txt
================================================
node ./benchmark/server.js
bombardier --body-file="./README.md" --method=POST --duration=10s --connections=100 http://localhost:3000/api/upload
================================================
FILE: benchmark/index.js
================================================
import assert from "node:assert";
import MultipartParser from '../src/parsers/Multipart.js';
const parser = new MultipartParser();
const customBoundary = '-----------------------------168072824752491622650073';
const mb = 1000; // 1GB
const buf = createMultipartBuffer(customBoundary, mb * 1024 * 1024);
const calls = {
partBegin: 0,
headerField: 0,
headerValue: 0,
headerEnd: 0,
headersEnd: 0,
partData: 0,
partEnd: 0,
end: 0,
};
const start = performance.now();
parser.initWithBoundary(customBoundary);
parser.on('data', ({ name }) => {
calls[name] += 1;
});
parser.write(buf);
const duration = performance.now() - start;
const mbPerSec = (mb / (duration / 1000)).toFixed(2);
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.alloc(size);
buffer.write(head, 0, 'ascii');
buffer.write(tail, buffer.length - tail.length, 'ascii');
return buffer;
}
process.on('exit', () => {
assert.deepStrictEqual(calls, {
partBegin: 1,
headerField: 1,
headerValue: 1,
headerEnd: 1,
headersEnd: 1,
partData: 1,
partEnd: 1,
end: 1,
});
// Object.keys(events).forEach((k) => {
// console.log(k, events[k]);
// // assert.equal(callbacks[k], 0, `${k} count off by ${callbacks[k]}`);
// });
});
================================================
FILE: benchmark/server.js
================================================
// inital copy of with-http.js
// made a copy so that examples can be changed without impacting tests
import http from 'node:http';
import slugify from '@sindresorhus/slugify';
import formidable, {errors as formidableErrors} from '../src/index.js';
const server = http.createServer((req, res) => {
// handle common internet errors
// to avoid server crash
req.on('error', console.error);
res.on('error', console.error);
if (req.url === '/api/upload' && req.method.toLowerCase() === 'post') {
const form = formidable({
uploadDir: `benchmark/testuploads`,
keepExtensions: true,
});
form.parse(req, (err, fields, files) => {
if (err) {
console.error(err);
res.writeHead(err.httpCode || 400, { 'Content-Type': 'text/plain' });
res.end(String(err));
return;
}
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ fields, files }, null, 2));
});
return;
}
// else not used in tests
});
server.listen(3000, () => {
console.log('Server listening on http://localhost:3000 ...');
});
================================================
FILE: examples/express-middleware.js
================================================
import express from 'express';
import formidable from '../src/index.js';
const app = express();
// middlewares that populates req.fields and req.body
const formMiddleWare = (req, res, next) => {
const form = formidable({});
form.parse(req, (err, fields, files) => {
if (err) {
next(err);
return;
}
req.fields = fields;
req.files = files;
next();
});
};
app.get('/', (req, res) => {
res.send(`
<h2>With <code>"express"</code> npm package</h2>
<form action="/api/upload" enctype="multipart/form-data" method="post">
<div>Text field title: <input type="text" name="title" /></div>
<div>File: <input type="file" name="someExpressFiles" multiple="multiple"></div>
<input type="submit" value="Upload">
</form>
`);
});
// use middleware
app.post('/api/upload', formMiddleWare, (req, res, next) => {
res.json({
fields: req.fields,
files: req.files,
});
});
app.listen(3000, () => {
console.log('Server listening on http://localhost:3000 ...');
});
================================================
FILE: examples/forceBuffer.js
================================================
// warning: forcing file into a Buffer elminates the benefits of using streams and may cause memory overflow
import http from 'node:http';
import { Buffer } from 'node:buffer'
import { Writable } from 'node:stream';
import formidable from '../src/index.js';
const server = http.createServer((req, res) => {
if (req.url === '/api/upload' && req.method.toLowerCase() === 'post') {
// parse a file upload
const endBuffers = {};
const form = formidable({
fileWriteStreamHandler: (file) => {
const chunks = [];
const writable = new Writable({
write (chunk, enc, next) {
chunks.push(chunk);
next();
},
destroy() {
endBuffers = {};
},
final(cb) {
const buffer = Buffer.concat(chunks);
// if filename option is not provided file.newFilename will be a random string
endBuffers[file.newFilename] = buffer;
cb();
},
})
return writable;
},
});
form.parse(req, (err, fields, files) => {
// available here endBuffers
if (err) {
console.error(err);
res.writeHead(err.httpCode || 400, { 'Content-Type': 'text/plain' });
res.end(String(err));
return;
}
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ fields, files }, null, 2));
Object.entries(endBuffers).map(([key, value]) => {
console.log(key);
console.log(value.toString("utf8"));
});
});
return;
}
// show a file upload form
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end(`
<h2>With Node.js <code>"http"</code> module</h2>
<form action="/api/upload" enctype="multipart/form-data" method="post">
<div>Text field title: <input type="text" name="title"></div>
<div>File: <input type="file" name="myfile"></div>
<button>Upload</button>
</form>
`);
});
server.listen(3000, () => {
console.log('Server listening on http://localhost:3000 ...');
});
================================================
FILE: examples/json.js
================================================
import http from 'node:http';
import util from 'node:util';
import formidable from '../src/index.js';
const PORT = 3000;
const server = http.createServer((req, res) => {
if (req.method !== 'POST') {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end(`Please POST a JSON payload to http://localhost:${PORT}/`);
return;
}
const form = formidable();
const fields = {};
form
.on('error', (err) => {
console.error(err);
res.writeHead(500, { 'Content-Type': 'text/plain' });
res.end(`error:\n\n${util.inspect(err)}`);
})
.on('field', (field, value) => {
console.log(field, value);
fields[field] = value;
})
.on('end', () => {
console.log('-> post done from "end" event');
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end(`received fields:\n\n${util.inspect(fields)}`);
});
form.parse(req);
});
server.listen(PORT, () => {
const chosenPort = server.address().port;
console.log(`Listening on http://localhost:${chosenPort}/`);
const body = JSON.stringify({
numbers: [1, 2, 3, 4, 5],
nested: { key: 'some val' },
});
const request = http.request(
{
host: 'localhost',
path: '/',
port: chosenPort,
method: 'POST',
headers: {
'Content-Type': 'application/json',
'content-length': body.length,
},
},
(response) => {
console.log('\nServer responded with:');
console.log('Status:', response.statusCode);
response.pipe(process.stdout);
response.on('end', () => {
console.log('\n');
process.exit();
});
// const data = '';
// response.on('data', function(chunk) {
// data += chunk.toString('utf8');
// });
// response.on('end', function() {
// console.log('Response Data:');
// console.log(data);
// process.exit();
// });
},
);
request.end(body);
});
================================================
FILE: examples/log-file-content-to-console.js
================================================
import http from 'node:http';
import { Writable } from 'node:stream';
import formidable from '../src/index.js';
const server = http.createServer((req, res) => {
if (req.url === '/api/upload' && req.method.toLowerCase() === 'post') {
// parse a file upload
const form = formidable({
fileWriteStreamHandler: (/* file */) => {
const writable = Writable();
// eslint-disable-next-line no-underscore-dangle
writable._write = (chunk, enc, next) => {
console.log(chunk.toString());
next();
};
return writable;
},
});
form.parse(req, () => {
res.writeHead(200);
res.end();
});
return;
}
// show a file upload form
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end(`
<h2>With Node.js <code>"http"</code> module</h2>
<form action="/api/upload" enctype="multipart/form-data" method="post">
<div>Text field title: <input type="text" name="title" /></div>
<div>File: <input type="file" name="file" /></div>
<input type="submit" value="Upload" />
</form>
`);
});
server.listen(3000, () => {
console.log('Server listening on http://localhost:3000 ...');
});
================================================
FILE: examples/multipart-parser.js
================================================
import { Blob } from 'node:buffer';
import { Readable } from 'node:stream';
import { FormData, formDataToBlob } from 'formdata-polyfill/esm.min.js'
import { MultipartParser } from '../src/index.js';
const blob1 = new Blob(
['Content of a.txt.'],
{ type: 'text/plain' }
);
const blob2 = new Blob(
['<!DOCTYPE html><title>Content of a.html.</title>'],
{ type: 'text/html' }
);
const fd = new FormData();
fd.set('text', 'some text ...');
fd.set('z', 'text inside z');
fd.set('file1', blob1, 'a.txt');
fd.set('file2', blob2, 'a.html');
const multipartParser = new MultipartParser();
multipartParser.on('data', ({ name, buffer, start, end }) => {
console.log(`${name}:`);
if (buffer && start && end) {
console.log(String(buffer.slice(start, end)));
}
console.log();
});
multipartParser.on('error', console.error);
const blob = formDataToBlob(fd);
const boundary = blob.type.split('boundary=')[1];
multipartParser.initWithBoundary(boundary);
Readable.from(blob.stream()).pipe(multipartParser);
================================================
FILE: examples/multiples.js
================================================
import http from 'node:http';
import os from 'node:os';
import formidable from '../src/index.js';
const server = http.createServer((req, res) => {
if (req.url === '/') {
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end(`
<form action="/upload" enctype="multipart/form-data" method="post">
<label>simple<input type="text" name="text_single" autofocus /></label><br />
<label>array text 0<input type="text" name="text_multiple[]" /></label><br />
<label>array text 1<input type="text" name="text_multiple[]" /></label><br />
<label>file simple<input type="file" name="file_single" /></label><br />
<label>file attribute multiple<input type="file" name="file_multiple" multiple /></label><br />
<label>file html array0<input type="file" name="filearray[]" /></label><br />
<label>file html array1<input type="file" name="filearray[]" /></label><br />
<label>file html array and multiple0<input type="file" name="filearray_with_multiple[]" multiple /></label><br />
<label>file html array and multiple1<input type="file" name="filearray_with_multiple[]" multiple /></label><br />
<br />
<button>Upload</button>
</form>
`);
} else if (req.url === '/upload') {
const form = formidable({ uploadDir: os.tmpdir() });
form.parse(req, (err, fields, files) => {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ err, fields, files }, null, 2));
});
} else {
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('404');
}
});
server.listen(3000, () => {
console.log('Server listening on http://localhost:3000 ...');
});
================================================
FILE: examples/store-files-on-s3.js
================================================
// To test this example you have to install aws-sdk nodejs package and create a bucket named "demo-bucket"
import http from 'node:http';
import { PassThrough } from 'node:stream';
import AWS from 'aws-sdk';
import formidable from '../src/index.js';
const s3Client = new AWS.S3({
credentials: {
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_KEY,
},
});
const uploadStream = (file) => {
const pass = new PassThrough();
s3Client.upload(
{
Bucket: 'demo-bucket',
Key: file.newFilename,
Body: pass,
},
(err, data) => {
console.log(err, data);
},
);
return pass;
};
const server = http.createServer((req, res) => {
if (req.url === '/api/upload' && req.method.toLowerCase() === 'post') {
// parse a file upload
const form = formidable({
fileWriteStreamHandler: uploadStream,
});
form.parse(req, () => {
res.writeHead(200);
res.end();
});
return;
}
// show a file upload form
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end(`
<h2>With Node.js <code>"http"</code> module</h2>
<form action="/api/upload" enctype="multipart/form-data" method="post">
<div>Text field title: <input type="text" name="title" /></div>
<div>File: <input type="file" name="file"/></div>
<input type="submit" value="Upload" />
</form>
`);
});
server.listen(3000, () => {
console.log('Server listening on http://localhost:3000 ...');
});
================================================
FILE: examples/upload-multiple-files.js
================================================
import http from 'node:http';
import util from 'node:util';
import os from 'node:os';
import formidable from '../src/index.js';
const server = http.createServer((req, res) => {
if (req.url === '/') {
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end(`
<form action="/upload" enctype="multipart/form-data" method="post">
<input type="text" name="title"><br>
<input type="file" name="someCoolFiles" multiple><br>
<button>Upload</button>
</form>
`);
} else if (req.url === '/upload') {
const form = formidable({ uploadDir: os.tmpdir() });
const files = [];
const fields = [];
form
.on('field', (fieldName, value) => {
console.log(fieldName, value);
fields.push({ fieldName, value });
})
.on('file', (fieldName, file) => {
console.log(fieldName, file);
files.push({ fieldName, file });
})
.on('end', () => {
console.log('-> upload done');
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.write(`received fields:\n\n${util.inspect(fields)}`);
res.write('\n\n');
res.end(`received files:\n\n${util.inspect(files)}`);
});
form.parse(req);
} else {
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('404');
}
});
server.listen(3000, () => {
console.log('Server listening on http://localhost:3000 ...');
});
================================================
FILE: examples/urlencoded-no-enctype.js
================================================
import http from 'node:http';
import util from 'node:util';
import formidable from '../src/index.js';
const server = http.createServer((req, res) => {
if (req.url === '/') {
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end(`
<form action="/post" method="post">
Title: <input type="text" name="title" /><br />
Data: <input type="text" name="data" /><br />
<button>Submit</button>
</form>
`);
} else if (req.url === '/post') {
const form = formidable();
const fields = [];
form
.on('error', (err) => {
console.log('err!', err);
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end(`error:\n\n${util.inspect(err)}`);
})
.on('field', (fieldName, fieldValue) => {
console.log('fieldName:', fieldName);
console.log('fieldValue:', fieldValue);
fields.push({ fieldName, fieldValue });
})
.on('end', () => {
console.log('-> post done from "end" event');
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end(`received fields:\n\n${util.inspect(fields)}`);
});
form.parse(req, () => {
console.log('-> post done from callback');
// res.writeHead(200, { 'Content-Type': 'text/plain' });
// res.end(`received fields:\n\n${util.inspect(fields)}`);
});
} else {
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('404');
}
});
server.listen(3000, () => {
console.log('Server listening on http://localhost:3000 ...');
});
================================================
FILE: examples/with-express.js
================================================
import express from 'express';
import formidable from '../src/index.js';
const app = express();
app.get('/', (req, res) => {
res.send(`
<h2>With <code>"express"</code> npm package</h2>
<form action="/api/upload" enctype="multipart/form-data" method="post">
<div>Text field title: <input type="text" name="title" /></div>
<div>File: <input type="file" name="someExpressFiles" multiple="multiple" /></div>
<input type="submit" value="Upload" />
</form>
`);
});
app.post('/api/upload', (req, res, next) => {
const form = formidable({ });
form.parse(req, (err, fields, files) => {
if (err) {
next(err);
return;
}
res.json({ fields, files });
});
});
app.listen(3000, () => {
console.log('Server listening on http://localhost:3000 ...');
});
================================================
FILE: examples/with-http.js
================================================
import http from 'node:http';
import slugify from '@sindresorhus/slugify';
import formidable, {errors as formidableErrors} from '../src/index.js';
const server = http.createServer((req, res) => {
// handle common internet errors
// to avoid server crash
req.on('error', console.error);
res.on('error', console.error);
if (req.url === '/api/upload' && req.method.toLowerCase() === 'post') {
// parse a file upload
const form = formidable({
defaultInvalidName: 'invalid',
uploadDir: `uploads`,
keepExtensions: true,
createDirsFromUploads: true,
allowEmptyFiles: true,
minFileSize: 0,
filename(name, ext, part, form) {
/* name basename of the http originalFilename
ext with the dot ".txt" only if keepExtensions is true
*/
// originalFilename will have slashes with relative path if a
// directory was uploaded
const {originalFilename} = part;
if (!originalFilename) {
return 'invalid';
}
// return 'yo.txt'; // or completly different name
// return 'z/yo.txt'; // subdirectory
return originalFilename.split("/").map((subdir) => {
return slugify(subdir, {separator: ''}); // slugify to avoid invalid filenames
}).join("/").substr(0, 100); // substr to define a maximum
},
filter: function ({name, originalFilename, mimetype}) {
return Boolean(originalFilename);
// keep only images
// return mimetype?.includes("image");
}
// maxTotalFileSize: 4000,
// maxFileSize: 1000,
});
form.parse(req, (err, fields, files) => {
if (err) {
console.error(err);
res.writeHead(err.httpCode || 400, { 'Content-Type': 'text/plain' });
res.end(String(err));
return;
}
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ fields, files }, null, 2));
});
return;
}
// else show a file upload form
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end(`
<h2>With Node.js <code>"http"</code> module</h2>
<form action="/api/upload" enctype="multipart/form-data" method="post">
<div>Text field title: <input type="text" name="title" /></div>
<div>File: <input type="file" name="multipleFiles" multiple /></div>
<div>Folders: <input type="file" name="folders" webkitdirectory directory multiple /></div>
<input type="submit" value="Upload" />
</form>
<form action="/api/upload" enctype="multipart/form-data" method="post">
<div>Text field title: <input type="text" name="title" /></div>
<div>Text field with same name: <input type="text" name="title" /></div>
<div>Other field <input type="text" name="other" /></div>
<input type="submit" value="submit simple" />
</form>
`);
});
server.listen(3000, () => {
console.log('Server listening on http://localhost:3000 ...');
});
================================================
FILE: examples/with-koa2.js
================================================
import Koa from 'koa';
import formidable from '../src/index.js';
const app = new Koa();
app.on('error', (err) => {
console.error('server error', err);
});
app.use(async (ctx, next) => {
if (ctx.url === '/api/upload' && ctx.method.toLowerCase() === 'post') {
let i = 0;
const form = formidable({
keepExtensions: true,
// must return absolute path
filename: (part, $self) => {
i += 1;
return `${$self.uploadDir}/sasasa${i}`;
},
});
// not very elegant, but that's for now if you don't want touse `koa-better-body`
// or other middlewares.
await new Promise((resolve, reject) => {
form.parse(ctx.req, (err, fields, files) => {
if (err) {
reject(err);
return;
}
ctx.set('Content-Type', 'application/json');
ctx.status = 200;
ctx.state = { fields, files };
ctx.body = JSON.stringify(ctx.state, null, 2);
resolve();
});
});
await next();
return;
}
// show a file upload form
ctx.set('Content-Type', 'text/html');
ctx.status = 200;
ctx.body = `
<h2>With <code>"koa"</code> npm package</h2>
<form action="/api/upload" enctype="multipart/form-data" method="post">
<div>Text field title: <input type="text" name="title" /></div>
<div>File: <input type="file" name="koaFiles" multiple="multiple" /></div>
<input type="submit" value="Upload" />
</form>
`;
});
app.use((ctx) => {
console.log('The next middleware is called');
console.log('Results:', ctx.state);
});
app.listen(3000, () => {
console.log('Server listening on http://localhost:3000 ...');
});
================================================
FILE: nyc.config.js
================================================
'use strict';
module.exports = {
statements: 70,
branches: 70,
functions: 70,
lines: 70,
'check-coverage': true,
exclude: ['test'],
include: ['src'],
reporter: ['text', 'text-summary', 'lcov', 'clover'],
};
================================================
FILE: package.json
================================================
{
"name": "formidable",
"version": "3.5.4",
"license": "MIT",
"description": "A node.js module for parsing form data, especially file uploads.",
"homepage": "https://github.com/node-formidable/formidable",
"funding": "https://ko-fi.com/tunnckoCore/commissions",
"repository": "node-formidable/formidable",
"type": "module",
"main": "./dist/index.cjs",
"exports": {
".": {
"import": {
"default": "./src/index.js"
},
"require": {
"default": "./dist/index.cjs"
},
"default": "./dist/index.cjs"
},
"./src/helpers/*.js": {
"import": {
"default": "./src/helpers/*.js"
},
"require": {
"default": "./dist/helpers/*.cjs"
}
},
"./src/parsers/*.js": {
"import": {
"default": "./src/parsers/*.js"
},
"require": {
"default": "./dist/index.cjs"
}
}
},
"files": [
"src",
"./dist",
"./CHANGELOG",
"./README.md",
"./README_pt_BR.md"
],
"publishConfig": {
"access": "public",
"tag": "latest"
},
"scripts": {
"build-package": "rollup --config ./tool/rollup.config.js",
"prepublishOnly": "pnpm run build-package",
"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": "pnpm run fmt:prepare '**/*'",
"fmt:prepare": "prettier --write",
"lint": "pnpm run lint:prepare .",
"lint:prepare": "eslint --cache --fix --quiet --format codeframe",
"fresh": "rm -rf ./node_modules",
"test-specific": "node --disable-warning=ExperimentalWarning --experimental-vm-modules ./node_modules/jest/bin/jest.js --testPathPattern=test/standalone/keep-alive-error.test.js",
"test-jest": "node --disable-warning=ExperimentalWarning --experimental-vm-modules ./node_modules/jest/bin/jest.js --testPathPattern=test/ --coverage",
"test-node": "node --disable-warning=ExperimentalWarning --test ./test-node/**/*.test.js",
"test-jest:ci": "node --experimental-vm-modules ./node_modules/jest/bin/jest.js --testPathPattern=test/ --coverage",
"test:local": "pnpm run test-node && pnpm run test-jest",
"audit": "pnpm audit --prod --fix",
"pretest": "rm -rf ./test/tmp && mkdir ./test/tmp",
"test": "pnpm run audit && node --test ./test-node/**/*.test.js && pnpm run test-jest:ci"
},
"dependencies": {
"@paralleldrive/cuid2": "2.2.2",
"dezalgo": "^1.0.4",
"once": "^1.4.0"
},
"packageManager": "pnpm@10.8.1",
"devDependencies": {
"@rollup/plugin-commonjs": "^25.0.2",
"@rollup/plugin-node-resolve": "^15.1.0",
"@sindresorhus/slugify": "^2.1.0",
"@tunnckocore/prettier-config": "1.3.8",
"eslint": "6.8.0",
"eslint-config-airbnb-base": "14.1.0",
"eslint-config-prettier": "6.11.0",
"eslint-plugin-import": "2.20.2",
"eslint-plugin-prettier": "3.1.3",
"express": "^4.21.1",
"formdata-polyfill": "^4.0.10",
"jest": "27.2.4",
"koa": "2.16.1",
"nyc": "15.1.0",
"prettier": "2.0.5",
"prettier-plugin-pkgjson": "0.2.8",
"rollup": "^3.25.3",
"supertest": "6.1.6"
},
"engines": {
"node": ">=14.0.0"
},
"jest": {
"verbose": true
},
"keywords": [
"multipart",
"form",
"data",
"querystring",
"www",
"json",
"ulpoad",
"file"
]
}
================================================
FILE: pnpm-lock.yaml
================================================
lockfileVersion: '9.0'
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
importers:
.:
dependencies:
'@paralleldrive/cuid2':
specifier: 2.2.2
version: 2.2.2
dezalgo:
specifier: ^1.0.4
version: 1.0.4
once:
specifier: ^1.4.0
version: 1.4.0
devDependencies:
'@rollup/plugin-commonjs':
specifier: ^25.0.2
version: 25.0.8(rollup@3.29.5)
'@rollup/plugin-node-resolve':
specifier: ^15.1.0
version: 15.3.1(rollup@3.29.5)
'@sindresorhus/slugify':
specifier: ^2.1.0
version: 2.2.1
'@tunnckocore/prettier-config':
specifier: 1.3.8
version: 1.3.8(prettier-plugin-pkgjson@0.2.8(prettier@2.0.5))(prettier@2.0.5)
eslint:
specifier: 6.8.0
version: 6.8.0
eslint-config-airbnb-base:
specifier: 14.1.0
version: 14.1.0(eslint-plugin-import@2.20.2(eslint@6.8.0))(eslint@6.8.0)
eslint-config-prettier:
specifier: 6.11.0
version: 6.11.0(eslint@6.8.0)
eslint-plugin-import:
specifier: 2.20.2
version: 2.20.2(eslint@6.8.0)
eslint-plugin-prettier:
specifier: 3.1.3
version: 3.1.3(eslint@6.8.0)(prettier@2.0.5)
express:
specifier: ^4.21.1
version: 4.21.2
formdata-polyfill:
specifier: ^4.0.10
version: 4.0.10
jest:
specifier: 27.2.4
version: 27.2.4
koa:
specifier: 2.16.1
version: 2.16.1
nyc:
specifier: 15.1.0
version: 15.1.0
prettier:
specifier: 2.0.5
version: 2.0.5
prettier-plugin-pkgjson:
specifier: 0.2.8
version: 0.2.8(prettier@2.0.5)
rollup:
specifier: ^3.25.3
version: 3.29.5
supertest:
specifier: 6.1.6
version: 6.1.6
packages:
'@ampproject/remapping@2.3.0':
resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==}
engines: {node: '>=6.0.0'}
'@babel/code-frame@7.26.2':
resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==}
engines: {node: '>=6.9.0'}
'@babel/compat-data@7.26.8':
resolution: {integrity: sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==}
engines: {node: '>=6.9.0'}
'@babel/core@7.26.10':
resolution: {integrity: sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==}
engines: {node: '>=6.9.0'}
'@babel/generator@7.27.0':
resolution: {integrity: sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==}
engines: {node: '>=6.9.0'}
'@babel/helper-compilation-targets@7.27.0':
resolution: {integrity: sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA==}
engines: {node: '>=6.9.0'}
'@babel/helper-module-imports@7.25.9':
resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==}
engines: {node: '>=6.9.0'}
'@babel/helper-module-transforms@7.26.0':
resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0
'@babel/helper-plugin-utils@7.26.5':
resolution: {integrity: sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==}
engines: {node: '>=6.9.0'}
'@babel/helper-string-parser@7.25.9':
resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==}
engines: {node: '>=6.9.0'}
'@babel/helper-validator-identifier@7.25.9':
resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==}
engines: {node: '>=6.9.0'}
'@babel/helper-validator-option@7.25.9':
resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==}
engines: {node: '>=6.9.0'}
'@babel/helpers@7.27.0':
resolution: {integrity: sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==}
engines: {node: '>=6.9.0'}
'@babel/parser@7.27.0':
resolution: {integrity: sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==}
engines: {node: '>=6.0.0'}
hasBin: true
'@babel/plugin-syntax-async-generators@7.8.4':
resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==}
peerDependencies:
'@babel/core': ^7.0.0-0
'@babel/plugin-syntax-bigint@7.8.3':
resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==}
peerDependencies:
'@babel/core': ^7.0.0-0
'@babel/plugin-syntax-class-properties@7.12.13':
resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==}
peerDependencies:
'@babel/core': ^7.0.0-0
'@babel/plugin-syntax-class-static-block@7.14.5':
resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
'@babel/plugin-syntax-import-attributes@7.26.0':
resolution: {integrity: sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
'@babel/plugin-syntax-import-meta@7.10.4':
resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==}
peerDependencies:
'@babel/core': ^7.0.0-0
'@babel/plugin-syntax-json-strings@7.8.3':
resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==}
peerDependencies:
'@babel/core': ^7.0.0-0
'@babel/plugin-syntax-logical-assignment-operators@7.10.4':
resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==}
peerDependencies:
'@babel/core': ^7.0.0-0
'@babel/plugin-syntax-nullish-coalescing-operator@7.8.3':
resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==}
peerDependencies:
'@babel/core': ^7.0.0-0
'@babel/plugin-syntax-numeric-separator@7.10.4':
resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==}
peerDependencies:
'@babel/core': ^7.0.0-0
'@babel/plugin-syntax-object-rest-spread@7.8.3':
resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==}
peerDependencies:
'@babel/core': ^7.0.0-0
'@babel/plugin-syntax-optional-catch-binding@7.8.3':
resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==}
peerDependencies:
'@babel/core': ^7.0.0-0
'@babel/plugin-syntax-optional-chaining@7.8.3':
resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==}
peerDependencies:
'@babel/core': ^7.0.0-0
'@babel/plugin-syntax-private-property-in-object@7.14.5':
resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
'@babel/plugin-syntax-top-level-await@7.14.5':
resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
'@babel/plugin-syntax-typescript@7.25.9':
resolution: {integrity: sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
'@babel/template@7.27.0':
resolution: {integrity: sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==}
engines: {node: '>=6.9.0'}
'@babel/traverse@7.27.0':
resolution: {integrity: sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==}
engines: {node: '>=6.9.0'}
'@babel/types@7.27.0':
resolution: {integrity: sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==}
engines: {node: '>=6.9.0'}
'@bcoe/v8-coverage@0.2.3':
resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==}
'@istanbuljs/load-nyc-config@1.1.0':
resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==}
engines: {node: '>=8'}
'@istanbuljs/schema@0.1.3':
resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==}
engines: {node: '>=8'}
'@jest/console@27.5.1':
resolution: {integrity: sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
'@jest/core@27.5.1':
resolution: {integrity: sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
peerDependencies:
node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0
peerDependenciesMeta:
node-notifier:
optional: true
'@jest/environment@27.5.1':
resolution: {integrity: sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
'@jest/fake-timers@27.5.1':
resolution: {integrity: sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
'@jest/globals@27.5.1':
resolution: {integrity: sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
'@jest/reporters@27.5.1':
resolution: {integrity: sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
peerDependencies:
node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0
peerDependenciesMeta:
node-notifier:
optional: true
'@jest/source-map@27.5.1':
resolution: {integrity: sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
'@jest/test-result@27.5.1':
resolution: {integrity: sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
'@jest/test-sequencer@27.5.1':
resolution: {integrity: sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
'@jest/transform@27.5.1':
resolution: {integrity: sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
'@jest/types@27.5.1':
resolution: {integrity: sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
'@jridgewell/gen-mapping@0.3.8':
resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==}
engines: {node: '>=6.0.0'}
'@jridgewell/resolve-uri@3.1.2':
resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
engines: {node: '>=6.0.0'}
'@jridgewell/set-array@1.2.1':
resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==}
engines: {node: '>=6.0.0'}
'@jridgewell/sourcemap-codec@1.5.0':
resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==}
'@jridgewell/trace-mapping@0.3.25':
resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
'@noble/hashes@1.8.0':
resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==}
engines: {node: ^14.21.3 || >=16}
'@nodelib/fs.scandir@2.1.5':
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
engines: {node: '>= 8'}
'@nodelib/fs.stat@2.0.5':
resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
engines: {node: '>= 8'}
'@nodelib/fs.walk@1.2.8':
resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
engines: {node: '>= 8'}
'@paralleldrive/cuid2@2.2.2':
resolution: {integrity: sha512-ZOBkgDwEdoYVlSeRbYYXs0S9MejQofiVYoTbKzy/6GQa39/q5tQU2IX46+shYnUkpEl3wc+J6wRlar7r2EK2xA==}
'@rollup/plugin-commonjs@25.0.8':
resolution: {integrity: sha512-ZEZWTK5n6Qde0to4vS9Mr5x/0UZoqCxPVR9KRUjU4kA2sO7GEUn1fop0DAwpO6z0Nw/kJON9bDmSxdWxO/TT1A==}
engines: {node: '>=14.0.0'}
peerDependencies:
rollup: ^2.68.0||^3.0.0||^4.0.0
peerDependenciesMeta:
rollup:
optional: true
'@rollup/plugin-node-resolve@15.3.1':
resolution: {integrity: sha512-tgg6b91pAybXHJQMAAwW9VuWBO6Thi+q7BCNARLwSqlmsHz0XYURtGvh/AuwSADXSI4h/2uHbs7s4FzlZDGSGA==}
engines: {node: '>=14.0.0'}
peerDependencies:
rollup: ^2.78.0||^3.0.0||^4.0.0
peerDependenciesMeta:
rollup:
optional: true
'@rollup/pluginutils@5.1.4':
resolution: {integrity: sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==}
engines: {node: '>=14.0.0'}
peerDependencies:
rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0
peerDependenciesMeta:
rollup:
optional: true
'@sindresorhus/slugify@2.2.1':
resolution: {integrity: sha512-MkngSCRZ8JdSOCHRaYd+D01XhvU3Hjy6MGl06zhOk614hp9EOAp5gIkBeQg7wtmxpitU6eAL4kdiRMcJa2dlrw==}
engines: {node: '>=12'}
'@sindresorhus/transliterate@1.6.0':
resolution: {integrity: sha512-doH1gimEu3A46VX6aVxpHTeHrytJAG6HgdxntYnCFiIFHEM/ZGpG8KiZGBChchjQmG0XFIBL552kBTjVcMZXwQ==}
engines: {node: '>=12'}
'@sinonjs/commons@1.8.6':
resolution: {integrity: sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==}
'@sinonjs/fake-timers@8.1.0':
resolution: {integrity: sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==}
'@tootallnate/once@1.1.2':
resolution: {integrity: sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==}
engines: {node: '>= 6'}
'@tunnckocore/prettier-config@1.3.8':
resolution: {integrity: sha512-vhWfo1bgHMGR8qj8w9clxsanIDXYKTge/8kL23qVDfIMLOjam4SCyWgJi5ueOZ+drQJL7y3ni0y+o9lFvxaW+Q==}
engines: {node: '>=10.13'}
peerDependencies:
prettier: ^2.0.2
prettier-plugin-pkgjson: ^0.2.3
'@types/babel__core@7.20.5':
resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==}
'@types/babel__generator@7.27.0':
resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==}
'@types/babel__template@7.4.4':
resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==}
'@types/babel__traverse@7.20.7':
resolution: {integrity: sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==}
'@types/estree@1.0.7':
resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==}
'@types/glob@7.2.0':
resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==}
'@types/graceful-fs@4.1.9':
resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==}
'@types/istanbul-lib-coverage@2.0.6':
resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==}
'@types/istanbul-lib-report@3.0.3':
resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==}
'@types/istanbul-reports@3.0.4':
resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==}
'@types/minimatch@5.1.2':
resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==}
'@types/node@22.14.1':
resolution: {integrity: sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw==}
'@types/prettier@2.7.3':
resolution: {integrity: sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==}
'@types/resolve@1.20.2':
resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==}
'@types/stack-utils@2.0.3':
resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==}
'@types/yargs-parser@21.0.3':
resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==}
'@types/yargs@16.0.9':
resolution: {integrity: sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==}
abab@2.0.6:
resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==}
deprecated: Use your platform's native atob() and btoa() methods instead
accepts@1.3.8:
resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==}
engines: {node: '>= 0.6'}
acorn-globals@6.0.0:
resolution: {integrity: sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==}
acorn-jsx@5.3.2:
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
peerDependencies:
acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
acorn-walk@7.2.0:
resolution: {integrity: sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==}
engines: {node: '>=0.4.0'}
acorn@7.4.1:
resolution: {integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==}
engines: {node: '>=0.4.0'}
hasBin: true
acorn@8.14.1:
resolution: {integrity: sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==}
engines: {node: '>=0.4.0'}
hasBin: true
agent-base@6.0.2:
resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==}
engines: {node: '>= 6.0.0'}
aggregate-error@3.1.0:
resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==}
engines: {node: '>=8'}
ajv@6.12.6:
resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
ansi-escapes@4.3.2:
resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==}
engines: {node: '>=8'}
ansi-regex@4.1.1:
resolution: {integrity: sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==}
engines: {node: '>=6'}
ansi-regex@5.0.1:
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
engines: {node: '>=8'}
ansi-styles@3.2.1:
resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==}
engines: {node: '>=4'}
ansi-styles@4.3.0:
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
engines: {node: '>=8'}
ansi-styles@5.2.0:
resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==}
engines: {node: '>=10'}
anymatch@3.1.3:
resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
engines: {node: '>= 8'}
append-transform@2.0.0:
resolution: {integrity: sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==}
engines: {node: '>=8'}
archy@1.0.0:
resolution: {integrity: sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==}
argparse@1.0.10:
resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==}
array-buffer-byte-length@1.0.2:
resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==}
engines: {node: '>= 0.4'}
array-flatten@1.1.1:
resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==}
array-includes@3.1.8:
resolution: {integrity: sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==}
engines: {node: '>= 0.4'}
array-union@2.1.0:
resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==}
engines: {node: '>=8'}
array.prototype.flat@1.3.3:
resolution: {integrity: sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==}
engines: {node: '>= 0.4'}
arraybuffer.prototype.slice@1.0.4:
resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==}
engines: {node: '>= 0.4'}
asap@2.0.6:
resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==}
astral-regex@1.0.0:
resolution: {integrity: sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==}
engines: {node: '>=4'}
async-function@1.0.0:
resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==}
engines: {node: '>= 0.4'}
asynckit@0.4.0:
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
available-typed-arrays@1.0.7:
resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==}
engines: {node: '>= 0.4'}
babel-jest@27.5.1:
resolution: {integrity: sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
peerDependencies:
'@babel/core': ^7.8.0
babel-plugin-istanbul@6.1.1:
resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==}
engines: {node: '>=8'}
babel-plugin-jest-hoist@27.5.1:
resolution: {integrity: sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
babel-preset-current-node-syntax@1.1.0:
resolution: {integrity: sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==}
peerDependencies:
'@babel/core': ^7.0.0
babel-preset-jest@27.5.1:
resolution: {integrity: sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
peerDependencies:
'@babel/core': ^7.0.0
balanced-match@1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
body-parser@1.20.3:
resolution: {integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==}
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
brace-expansion@1.1.11:
resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
brace-expansion@2.0.1:
resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
braces@3.0.3:
resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
engines: {node: '>=8'}
browser-process-hrtime@1.0.0:
resolution: {integrity: sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==}
browserslist@4.24.4:
resolution: {integrity: sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==}
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
hasBin: true
bser@2.1.1:
resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==}
buffer-from@1.1.2:
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
bytes@3.1.2:
resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==}
engines: {node: '>= 0.8'}
cache-content-type@1.0.1:
resolution: {integrity: sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA==}
engines: {node: '>= 6.0.0'}
caching-transform@4.0.0:
resolution: {integrity: sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==}
engines: {node: '>=8'}
call-bind-apply-helpers@1.0.2:
resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
engines: {node: '>= 0.4'}
call-bind@1.0.8:
resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==}
engines: {node: '>= 0.4'}
call-bound@1.0.4:
resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==}
engines: {node: '>= 0.4'}
callsites@3.1.0:
resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
engines: {node: '>=6'}
camelcase@5.3.1:
resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==}
engines: {node: '>=6'}
camelcase@6.3.0:
resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==}
engines: {node: '>=10'}
caniuse-lite@1.0.30001715:
resolution: {integrity: sha512-7ptkFGMm2OAOgvZpwgA4yjQ5SQbrNVGdRjzH0pBdy1Fasvcr+KAeECmbCAECzTuDuoX0FCY8KzUxjf9+9kfZEw==}
chalk@2.4.2:
resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
engines: {node: '>=4'}
chalk@4.1.2:
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
engines: {node: '>=10'}
char-regex@1.0.2:
resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==}
engines: {node: '>=10'}
chardet@0.7.0:
resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==}
ci-info@3.9.0:
resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==}
engines: {node: '>=8'}
cjs-module-lexer@1.4.3:
resolution: {integrity: sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==}
clean-stack@2.2.0:
resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==}
engines: {node: '>=6'}
cli-cursor@3.1.0:
resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==}
engines: {node: '>=8'}
cli-width@3.0.0:
resolution: {integrity: sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==}
engines: {node: '>= 10'}
cliui@6.0.0:
resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==}
cliui@7.0.4:
resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==}
co@4.6.0:
resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==}
engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'}
collect-v8-coverage@1.0.2:
resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==}
color-convert@1.9.3:
resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
color-convert@2.0.1:
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
engines: {node: '>=7.0.0'}
color-name@1.1.3:
resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==}
color-name@1.1.4:
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
combined-stream@1.0.8:
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
engines: {node: '>= 0.8'}
commondir@1.0.1:
resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==}
component-emitter@1.3.1:
resolution: {integrity: sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==}
concat-map@0.0.1:
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
confusing-browser-globals@1.0.11:
resolution: {integrity: sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==}
contains-path@0.1.0:
resolution: {integrity: sha512-OKZnPGeMQy2RPaUIBPFFd71iNf4791H12MCRuVQDnzGRwCYNYmTDy5pdafo2SLAcEMKzTOQnLWG4QdcjeJUMEg==}
engines: {node: '>=0.10.0'}
content-disposition@0.5.4:
resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==}
engines: {node: '>= 0.6'}
content-type@1.0.5:
resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==}
engines: {node: '>= 0.6'}
convert-source-map@1.9.0:
resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==}
convert-source-map@2.0.0:
resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
cookie-signature@1.0.6:
resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==}
cookie@0.7.1:
resolution: {integrity: sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==}
engines: {node: '>= 0.6'}
cookiejar@2.1.4:
resolution: {integrity: sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==}
cookies@0.9.1:
resolution: {integrity: sha512-TG2hpqe4ELx54QER/S3HQ9SRVnQnGBtKUz5bLQWtYAQ+o6GpgMs6sYUvaiJjVxb+UXwhRhAEP3m7LbsIZ77Hmw==}
engines: {node: '>= 0.8'}
cross-spawn@6.0.6:
resolution: {integrity: sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==}
engines: {node: '>=4.8'}
cross-spawn@7.0.6:
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
engines: {node: '>= 8'}
cssom@0.3.8:
resolution: {integrity: sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==}
cssom@0.4.4:
resolution: {integrity: sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==}
cssstyle@2.3.0:
resolution: {integrity: sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==}
engines: {node: '>=8'}
data-urls@2.0.0:
resolution: {integrity: sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==}
engines: {node: '>=10'}
data-view-buffer@1.0.2:
resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==}
engines: {node: '>= 0.4'}
data-view-byte-length@1.0.2:
resolution: {integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==}
engines: {node: '>= 0.4'}
data-view-byte-offset@1.0.1:
resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==}
engines: {node: '>= 0.4'}
debug@2.6.9:
resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
peerDependencies:
supports-color: '*'
peerDependenciesMeta:
supports-color:
optional: true
debug@3.2.7:
resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==}
peerDependencies:
supports-color: '*'
peerDependenciesMeta:
supports-color:
optional: true
debug@4.4.0:
resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==}
engines: {node: '>=6.0'}
peerDependencies:
supports-color: '*'
peerDependenciesMeta:
supports-color:
optional: true
decamelize@1.2.0:
resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==}
engines: {node: '>=0.10.0'}
decimal.js@10.5.0:
resolution: {integrity: sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==}
dedent@0.7.0:
resolution: {integrity: sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==}
deep-equal@1.0.1:
resolution: {integrity: sha512-bHtC0iYvWhyaTzvV3CZgPeZQqCOBGyGsVV7v4eevpdkLHfiSrXUdBG+qAuSz4RI70sszvjQ1QSZ98An1yNwpSw==}
deep-is@0.1.4:
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
deepmerge@4.3.1:
resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==}
engines: {node: '>=0.10.0'}
default-require-extensions@3.0.1:
resolution: {integrity: sha512-eXTJmRbm2TIt9MgWTsOH1wEuhew6XGZcMeGKCtLedIg/NCsg1iBePXkceTdK4Fii7pzmN9tGsZhKzZ4h7O/fxw==}
engines: {node: '>=8'}
define-data-property@1.1.4:
resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==}
engines: {node: '>= 0.4'}
define-properties@1.2.1:
resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==}
engines: {node: '>= 0.4'}
delayed-stream@1.0.0:
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
engines: {node: '>=0.4.0'}
delegates@1.0.0:
resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==}
depd@1.1.2:
resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==}
engines: {node: '>= 0.6'}
depd@2.0.0:
resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
engines: {node: '>= 0.8'}
destroy@1.2.0:
resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==}
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
detect-indent@6.1.0:
resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==}
engines: {node: '>=8'}
detect-newline@3.1.0:
resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==}
engines: {node: '>=8'}
dezalgo@1.0.4:
resolution: {integrity: sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==}
diff-sequences@27.5.1:
resolution: {integrity: sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
dir-glob@3.0.1:
resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
engines: {node: '>=8'}
doctrine@1.5.0:
resolution: {integrity: sha512-lsGyRuYr4/PIB0txi+Fy2xOMI2dGaTguCaotzFGkVZuKR5usKfcRWIFKNM3QNrU7hh/+w2bwTW+ZeXPK5l8uVg==}
engines: {node: '>=0.10.0'}
doctrine@3.0.0:
resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==}
engines: {node: '>=6.0.0'}
domexception@2.0.1:
resolution: {integrity: sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==}
engines: {node: '>=8'}
deprecated: Use your platform's native DOMException instead
dunder-proto@1.0.1:
resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
engines: {node: '>= 0.4'}
ee-first@1.1.1:
resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
electron-to-chromium@1.5.140:
resolution: {integrity: sha512-o82Rj+ONp4Ip7Cl1r7lrqx/pXhbp/lh9DpKcMNscFJdh8ebyRofnc7Sh01B4jx403RI0oqTBvlZ7OBIZLMr2+Q==}
emittery@0.8.1:
resolution: {integrity: sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==}
engines: {node: '>=10'}
emoji-regex@7.0.3:
resolution: {integrity: sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==}
emoji-regex@8.0.0:
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
encodeurl@1.0.2:
resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==}
engines: {node: '>= 0.8'}
encodeurl@2.0.0:
resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==}
engines: {node: '>= 0.8'}
error-ex@1.3.2:
resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==}
es-abstract@1.23.9:
resolution: {integrity: sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==}
engines: {node: '>= 0.4'}
es-define-property@1.0.1:
resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==}
engines: {node: '>= 0.4'}
es-errors@1.3.0:
resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
engines: {node: '>= 0.4'}
es-object-atoms@1.1.1:
resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==}
engines: {node: '>= 0.4'}
es-set-tostringtag@2.1.0:
resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==}
engines: {node: '>= 0.4'}
es-shim-unscopables@1.1.0:
resolution: {integrity: sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==}
engines: {node: '>= 0.4'}
es-to-primitive@1.3.0:
resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==}
engines: {node: '>= 0.4'}
es6-error@4.1.1:
resolution: {integrity: sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==}
escalade@3.2.0:
resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
engines: {node: '>=6'}
escape-html@1.0.3:
resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
escape-string-regexp@1.0.5:
resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
engines: {node: '>=0.8.0'}
escape-string-regexp@2.0.0:
resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==}
engines: {node: '>=8'}
escape-string-regexp@5.0.0:
resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==}
engines: {node: '>=12'}
escodegen@2.1.0:
resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==}
engines: {node: '>=6.0'}
hasBin: true
eslint-config-airbnb-base@14.1.0:
resolution: {integrity: sha512-+XCcfGyCnbzOnktDVhwsCAx+9DmrzEmuwxyHUJpw+kqBVT744OUBrB09khgFKlK1lshVww6qXGsYPZpavoNjJw==}
engines: {node: '>= 6'}
peerDependencies:
eslint: ^5.16.0 || ^6.8.0
eslint-plugin-import: ^2.20.1
eslint-config-prettier@6.11.0:
resolution: {integrity: sha512-oB8cpLWSAjOVFEJhhyMZh6NOEOtBVziaqdDQ86+qhDHFbZXoRTM7pNSvFRfW/W/L/LrQ38C99J5CGuRBBzBsdA==}
hasBin: true
peerDependencies:
eslint: '>=3.14.1'
eslint-import-resolver-node@0.3.9:
resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==}
eslint-module-utils@2.12.0:
resolution: {integrity: sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==}
engines: {node: '>=4'}
peerDependencies:
'@typescript-eslint/parser': '*'
eslint: '*'
eslint-import-resolver-node: '*'
eslint-import-resolver-typescript: '*'
eslint-import-resolver-webpack: '*'
peerDependenciesMeta:
'@typescript-eslint/parser':
optional: true
eslint:
optional: true
eslint-import-resolver-node:
optional: true
eslint-import-resolver-typescript:
optional: true
eslint-import-resolver-webpack:
optional: true
eslint-plugin-import@2.20.2:
resolution: {integrity: sha512-FObidqpXrR8OnCh4iNsxy+WACztJLXAHBO5hK79T1Hc77PgQZkyDGA5Ag9xAvRpglvLNxhH/zSmZ70/pZ31dHg==}
engines: {node: '>=4'}
peerDependencies:
'@typescript-eslint/parser': '*'
eslint: 2.x - 6.x
peerDependenciesMeta:
'@typescript-eslint/parser':
optional: true
eslint-plugin-prettier@3.1.3:
resolution: {integrity: sha512-+HG5jmu/dN3ZV3T6eCD7a4BlAySdN7mLIbJYo0z1cFQuI+r2DiTJEFeF68ots93PsnrMxbzIZ2S/ieX+mkrBeQ==}
engines: {node: '>=6.0.0'}
peerDependencies:
eslint: '>= 5.0.0'
prettier: '>= 1.13.0'
eslint-scope@5.1.1:
resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==}
engines: {node: '>=8.0.0'}
eslint-utils@1.4.3:
resolution: {integrity: sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==}
engines: {node: '>=6'}
eslint-visitor-keys@1.3.0:
resolution: {integrity: sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==}
engines: {node: '>=4'}
eslint@6.8.0:
resolution: {integrity: sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==}
engines: {node: ^8.10.0 || ^10.13.0 || >=11.10.1}
deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options.
hasBin: true
espree@6.2.1:
resolution: {integrity: sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==}
engines: {node: '>=6.0.0'}
esprima@4.0.1:
resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==}
engines: {node: '>=4'}
hasBin: true
esquery@1.6.0:
resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==}
engines: {node: '>=0.10'}
esrecurse@4.3.0:
resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==}
engines: {node: '>=4.0'}
estraverse@4.3.0:
resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==}
engines: {node: '>=4.0'}
estraverse@5.3.0:
resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==}
engines: {node: '>=4.0'}
estree-walker@2.0.2:
resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
esutils@2.0.3:
resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
engines: {node: '>=0.10.0'}
etag@1.8.1:
resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==}
engines: {node: '>= 0.6'}
execa@5.1.1:
resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==}
engines: {node: '>=10'}
exit@0.1.2:
resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==}
engines: {node: '>= 0.8.0'}
expect@27.5.1:
resolution: {integrity: sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
express@4.21.2:
resolution: {integrity: sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==}
engines: {node: '>= 0.10.0'}
external-editor@3.1.0:
resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==}
engines: {node: '>=4'}
fast-deep-equal@3.1.3:
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
fast-diff@1.3.0:
resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==}
fast-glob@3.3.3:
resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==}
engines: {node: '>=8.6.0'}
fast-json-stable-stringify@2.1.0:
resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
fast-levenshtein@2.0.6:
resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
fast-safe-stringify@2.1.1:
resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==}
fastq@1.19.1:
resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==}
fb-watchman@2.0.2:
resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==}
fetch-blob@3.2.0:
resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==}
engines: {node: ^12.20 || >= 14.13}
figures@3.2.0:
resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==}
engines: {node: '>=8'}
file-entry-cache@5.0.1:
resolution: {integrity: sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==}
engines: {node: '>=4'}
fill-range@7.1.1:
resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
engines: {node: '>=8'}
finalhandler@1.3.1:
resolution: {integrity: sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==}
engines: {node: '>= 0.8'}
find-cache-dir@3.3.2:
resolution: {integrity: sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==}
engines: {node: '>=8'}
find-up@2.1.0:
resolution: {integrity: sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==}
engines: {node: '>=4'}
find-up@4.1.0:
resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==}
engines: {node: '>=8'}
flat-cache@2.0.1:
resolution: {integrity: sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==}
engines: {node: '>=4'}
flatted@2.0.2:
resolution: {integrity: sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==}
for-each@0.3.5:
resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==}
engines: {node: '>= 0.4'}
foreground-child@2.0.0:
resolution: {integrity: sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==}
engines: {node: '>=8.0.0'}
form-data@3.0.3:
resolution: {integrity: sha512-q5YBMeWy6E2Un0nMGWMgI65MAKtaylxfNJGJxpGh45YDciZB4epbWpaAfImil6CPAPTYB4sh0URQNDRIZG5F2w==}
engines: {node: '>= 6'}
formdata-polyfill@4.0.10:
resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==}
engines: {node: '>=12.20.0'}
formidable@1.2.6:
resolution: {integrity: sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==}
deprecated: 'Please upgrade to latest, formidable@v2 or formidable@v3! Check these notes: https://bit.ly/2ZEqIau'
forwarded@0.2.0:
resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==}
engines: {node: '>= 0.6'}
fresh@0.5.2:
resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==}
engines: {node: '>= 0.6'}
fromentries@1.3.2:
resolution: {integrity: sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==}
fs.realpath@1.0.0:
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
fsevents@2.3.3:
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
os: [darwin]
function-bind@1.1.2:
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
function.prototype.name@1.1.8:
resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==}
engines: {node: '>= 0.4'}
functional-red-black-tree@1.0.1:
resolution: {integrity: sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==}
functions-have-names@1.2.3:
resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==}
gensync@1.0.0-beta.2:
resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
engines: {node: '>=6.9.0'}
get-caller-file@2.0.5:
resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
engines: {node: 6.* || 8.* || >= 10.*}
get-intrinsic@1.3.0:
resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==}
engines: {node: '>= 0.4'}
get-package-type@0.1.0:
resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==}
engines: {node: '>=8.0.0'}
get-proto@1.0.1:
resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==}
engines: {node: '>= 0.4'}
get-stdin@6.0.0:
resolution: {integrity: sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==}
engines: {node: '>=4'}
get-stream@6.0.1:
resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==}
engines: {node: '>=10'}
get-symbol-description@1.1.0:
resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==}
engines: {node: '>= 0.4'}
git-hooks-list@1.0.3:
resolution: {integrity: sha512-Y7wLWcrLUXwk2noSka166byGCvhMtDRpgHdzCno1UQv/n/Hegp++a2xBWJL1lJarnKD3SWaljD+0z1ztqxuKyQ==}
glob-parent@5.1.2:
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
engines: {node: '>= 6'}
glob@7.2.3:
resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
deprecated: Glob versions prior to v9 are no longer supported
glob@8.1.0:
resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==}
engines: {node: '>=12'}
deprecated: Glob versions prior to v9 are no longer supported
globals@11.12.0:
resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==}
engines: {node: '>=4'}
globals@12.4.0:
resolution: {integrity: sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==}
engines: {node: '>=8'}
globalthis@1.0.4:
resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==}
engines: {node: '>= 0.4'}
globby@10.0.0:
resolution: {integrity: sha512-3LifW9M4joGZasyYPz2A1U74zbC/45fvpXUvO/9KbSa+VV0aGZarWkfdgKyR9sExNP0t0x0ss/UMJpNpcaTspw==}
engines: {node: '>=8'}
gopd@1.2.0:
resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
engines: {node: '>= 0.4'}
graceful-fs@4.2.11:
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
has-bigints@1.1.0:
resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==}
engines: {node: '>= 0.4'}
has-flag@3.0.0:
resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==}
engines: {node: '>=4'}
has-flag@4.0.0:
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Af
gitextract_b0r5txre/
├── .all-contributorsrc
├── .editorconfig
├── .eslintignore
├── .eslintrc.cjs
├── .github/
│ ├── .kodiak.toml
│ ├── dependabot.yml
│ └── workflows/
│ ├── codeql-analysis.yml
│ └── main.yml
├── .gitignore
├── .prettierignore
├── .prettierrc.js
├── CHANGELOG.md
├── LICENSE
├── README.md
├── README_pt_BR.md
├── VERSION_NOTES.md
├── benchmark/
│ ├── 2022-11-30-i5-9600k.txt
│ ├── e2e.txt
│ ├── index.js
│ └── server.js
├── examples/
│ ├── express-middleware.js
│ ├── forceBuffer.js
│ ├── json.js
│ ├── log-file-content-to-console.js
│ ├── multipart-parser.js
│ ├── multiples.js
│ ├── store-files-on-s3.js
│ ├── upload-multiple-files.js
│ ├── urlencoded-no-enctype.js
│ ├── with-express.js
│ ├── with-http.js
│ └── with-koa2.js
├── nyc.config.js
├── package.json
├── pnpm-lock.yaml
├── src/
│ ├── Formidable.js
│ ├── FormidableError.js
│ ├── PersistentFile.js
│ ├── VolatileFile.js
│ ├── helpers/
│ │ ├── firstValues.js
│ │ └── readBooleans.js
│ ├── index.js
│ ├── parsers/
│ │ ├── Dummy.js
│ │ ├── JSON.js
│ │ ├── Multipart.js
│ │ ├── OctetStream.js
│ │ ├── Querystring.js
│ │ ├── StreamingQuerystring.js
│ │ └── index.js
│ └── plugins/
│ ├── index.js
│ ├── json.js
│ ├── multipart.js
│ ├── octetstream.js
│ └── querystring.js
├── test/
│ ├── fixture/
│ │ ├── file/
│ │ │ ├── funkyfilename.txt
│ │ │ ├── plain.txt
│ │ │ └── second-plaintext.txt
│ │ ├── http/
│ │ │ ├── encoding/
│ │ │ │ ├── beta-sticker-1.png.http
│ │ │ │ ├── binaryfile.tar.gz.http
│ │ │ │ ├── blank.gif.http
│ │ │ │ ├── menu_separator.png.http
│ │ │ │ └── plain.txt.http
│ │ │ ├── misc/
│ │ │ │ ├── boundary-substring-json.http
│ │ │ │ ├── empty-multipart.http
│ │ │ │ ├── empty-multipart2.http
│ │ │ │ ├── empty-urlencoded.http
│ │ │ │ ├── empty.http
│ │ │ │ └── minimal.http
│ │ │ ├── no-filename/
│ │ │ │ ├── filename-name.http
│ │ │ │ └── generic.http
│ │ │ ├── preamble/
│ │ │ │ ├── crlf.http
│ │ │ │ └── preamble.http
│ │ │ ├── special-chars-in-filename/
│ │ │ │ ├── info.md
│ │ │ │ ├── line-separator.http
│ │ │ │ ├── osx-chrome-13.http
│ │ │ │ ├── osx-firefox-3.6.http
│ │ │ │ ├── osx-safari-5.http
│ │ │ │ ├── xp-chrome-12.http
│ │ │ │ ├── xp-ie-7.http
│ │ │ │ ├── xp-ie-8.http
│ │ │ │ └── xp-safari-5.http
│ │ │ └── workarounds/
│ │ │ ├── missing-hyphens1.http
│ │ │ └── missing-hyphens2.http
│ │ ├── js/
│ │ │ ├── encoding.js
│ │ │ ├── misc.js
│ │ │ ├── no-filename.js
│ │ │ ├── preamble.js
│ │ │ ├── special-chars-in-filename.js
│ │ │ └── workarounds.js
│ │ ├── multi_video.upload
│ │ └── multipart.js
│ ├── integration/
│ │ ├── file-write-stream-handler-option.test.js
│ │ ├── fixtures.test.js
│ │ ├── json.test.js
│ │ ├── octet-stream.test.js
│ │ └── store-files-option.test.js
│ ├── standalone/
│ │ ├── connection-aborted.test.js
│ │ ├── content-transfer-encoding.test.js
│ │ ├── issue-46.test.js
│ │ └── keep-alive-error.test.js
│ ├── tools/
│ │ └── base64.html
│ └── unit/
│ ├── custom-plugins.test.js
│ ├── formidable.test.js
│ ├── multipart-parser.test.js
│ ├── persistent-file.disabled-test.js
│ ├── querystring-parser.test.js
│ └── volatile-file.test.js
├── test-legacy/
│ ├── .DS_Store
│ ├── README.md
│ ├── common.js
│ ├── integration/
│ │ └── test-multipart-parser.js
│ ├── simple/
│ │ ├── test-file.js
│ │ └── test-incoming-form.js
│ └── system/
│ └── test-multi-video-upload.js
├── test-node/
│ └── standalone/
│ ├── createDirsFromUploads.test.js
│ ├── end-event-emitted-twice.test.js
│ ├── multipart_parser.test.js
│ └── promise.test.js
└── tool/
├── record.js
└── rollup.config.js
SYMBOL INDEX (125 symbols across 34 files)
FILE: benchmark/index.js
function createMultipartBuffer (line 35) | function createMultipartBuffer(boundary, size) {
FILE: examples/forceBuffer.js
method write (line 17) | write (chunk, enc, next) {
method destroy (line 21) | destroy() {
method final (line 24) | final(cb) {
FILE: examples/json.js
constant PORT (line 6) | const PORT = 3000;
FILE: examples/with-http.js
method filename (line 21) | filename(name, ext, part, form) {
FILE: src/Formidable.js
constant CUID2_FINGERPRINT (line 19) | const CUID2_FINGERPRINT = `${process.env.NODE_ENV}-${os.platform()}-${os...
constant DEFAULT_OPTIONS (line 22) | const DEFAULT_OPTIONS = {
method filter (line 38) | filter(_part) {
function hasOwnProp (line 44) | function hasOwnProp(obj, key) {
class IncomingForm (line 84) | class IncomingForm extends EventEmitter {
method constructor (line 85) | constructor(options = {}) {
method use (line 142) | use(plugin) {
method pause (line 153) | pause () {
method resume (line 167) | resume () {
method parse (line 183) | async parse(req, cb) {
method writeHeaders (line 293) | async writeHeaders(headers) {
method write (line 314) | write(buffer) {
method onPart (line 333) | onPart(part) {
method _handlePart (line 338) | async _handlePart(part) {
method _parseContentType (line 473) | async _parseContentType() {
method _error (line 517) | _error(err, eventName = 'error') {
method _parseContentLength (line 531) | _parseContentLength() {
method _newParser (line 544) | _newParser() {
method _newFile (line 548) | async _newFile({ filepath, originalFilename, mimetype, newFilename }) {
method _getFileName (line 579) | _getFileName(headerValue) {
method _getExtension (line 599) | _getExtension(str) {
method _joinDirectoryName (line 626) | _joinDirectoryName(name) {
method _setUpRename (line 640) | _setUpRename() {
method _setUpMaxFields (line 670) | _setUpMaxFields() {
method _setUpMaxFiles (line 688) | _setUpMaxFiles() {
method _maybeEnd (line 706) | _maybeEnd() {
FILE: src/FormidableError.js
method constructor (line 22) | constructor(message, internalCode, httpCode = 500) {
FILE: src/PersistentFile.js
class PersistentFile (line 7) | class PersistentFile extends EventEmitter {
method constructor (line 8) | constructor({ filepath, newFilename, originalFilename, mimetype, hashA...
method open (line 24) | open() {
method toJSON (line 31) | toJSON() {
method toString (line 47) | toString() {
method write (line 51) | write(buffer, cb) {
method end (line 69) | end(cb) {
method destroy (line 79) | destroy() {
FILE: src/VolatileFile.js
class VolatileFile (line 6) | class VolatileFile extends EventEmitter {
method constructor (line 7) | constructor({ filepath, newFilename, originalFilename, mimetype, hashA...
method open (line 23) | open() {
method destroy (line 30) | destroy() {
method toJSON (line 34) | toJSON() {
method toString (line 48) | toString() {
method write (line 52) | write(buffer, cb) {
method end (line 69) | end(cb) {
FILE: src/parsers/Dummy.js
class DummyParser (line 5) | class DummyParser extends Transform {
method constructor (line 6) | constructor(incomingForm, options = {}) {
method _flush (line 12) | _flush(callback) {
FILE: src/parsers/JSON.js
class JSONParser (line 5) | class JSONParser extends Transform {
method constructor (line 6) | constructor(options = {}) {
method _transform (line 12) | _transform(chunk, encoding, callback) {
method _flush (line 17) | _flush(callback) {
FILE: src/parsers/Multipart.js
constant STATE (line 11) | const STATE = {
constant FBOUNDARY (line 28) | const FBOUNDARY = { PART_BOUNDARY: f, LAST_BOUNDARY: (f *= 2) };
constant SPACE (line 32) | const SPACE = 32;
constant HYPHEN (line 33) | const HYPHEN = 45;
constant COLON (line 34) | const COLON = 58;
function lower (line 38) | function lower(c) {
constant STATES (line 42) | const STATES = {};
class MultipartParser (line 48) | class MultipartParser extends Transform {
method constructor (line 49) | constructor(options = {}) {
method _endUnexpected (line 62) | _endUnexpected() {
method _flush (line 70) | _flush(done) {
method initWithBoundary (line 85) | initWithBoundary(str) {
method _handleCallback (line 97) | _handleCallback(name, buf, start, end) {
method _transform (line 105) | _transform(buffer, _, done) {
method explain (line 342) | explain() {
FILE: src/parsers/OctetStream.js
class OctetStreamParser (line 3) | class OctetStreamParser extends PassThrough {
method constructor (line 4) | constructor(options = {}) {
FILE: src/parsers/Querystring.js
class QuerystringParser (line 6) | class QuerystringParser extends Transform {
method constructor (line 7) | constructor(options = {}) {
method _transform (line 14) | _transform(buffer, encoding, callback) {
method _flush (line 20) | _flush(callback) {
FILE: src/parsers/StreamingQuerystring.js
constant AMPERSAND (line 7) | const AMPERSAND = 38;
constant EQUALS (line 8) | const EQUALS = 61;
class QuerystringParser (line 10) | class QuerystringParser extends Transform {
method constructor (line 11) | constructor(options = {}) {
method _transform (line 23) | _transform(buffer, encoding, callback) {
method _flush (line 77) | _flush(callback) {
method getSection (line 95) | getSection(buffer, i) {
method emitField (line 101) | emitField(key, val) {
FILE: src/plugins/json.js
function plugin (line 7) | function plugin(formidable, options) {
function init (line 24) | function init(_self, _opts) {
FILE: src/plugins/multipart.js
function plugin (line 10) | function plugin(formidable, options) {
function createInitMultipart (line 42) | function createInitMultipart(boundary) {
FILE: src/plugins/octetstream.js
function plugin (line 7) | async function plugin(formidable, options) {
function init (line 23) | async function init(_self, _opts) {
FILE: src/plugins/querystring.js
function plugin (line 8) | function plugin(formidable, options) {
function init (line 24) | function init(_self, _opts) {
FILE: test-legacy/integration/test-multipart-parser.js
constant CHUNK_LENGTH (line 3) | const CHUNK_LENGTH = 10;
FILE: test-legacy/simple/test-file.js
function test (line 11) | function test(test) {
FILE: test-legacy/simple/test-incoming-form.js
function test (line 25) | function test(test) {
FILE: test-legacy/system/test-multi-video-upload.js
constant BOUNDARY (line 3) | const BOUNDARY = '---------------------------101027544145785087814587779...
constant FIXTURE (line 4) | const FIXTURE = `${TEST_FIXTURES}/multi_video.upload`;
FILE: test-node/standalone/createDirsFromUploads.test.js
constant PORT (line 7) | const PORT = 13539;
FILE: test-node/standalone/end-event-emitted-twice.test.js
constant PORT (line 6) | const PORT = 13540;
FILE: test/fixture/js/special-chars-in-filename.js
function expect (line 3) | function expect(originalFilename, fixtureName) {
FILE: test/integration/file-write-stream-handler-option.test.js
constant PORT (line 13) | const PORT = 13533;
constant DEFAULT_UPLOAD_DIR (line 14) | const DEFAULT_UPLOAD_DIR = join(
constant CUSTOM_UPLOAD_DIR (line 18) | const CUSTOM_UPLOAD_DIR = join(
constant CUSTOM_UPLOAD_FILE_PATH (line 22) | const CUSTOM_UPLOAD_FILE_PATH = join(CUSTOM_UPLOAD_DIR, 'test-file');
FILE: test/integration/fixtures.test.js
constant PORT (line 12) | const PORT = 13534;
constant CWD (line 13) | const CWD = process.cwd();
constant FIXTURES_HTTP (line 14) | const FIXTURES_HTTP = join(CWD, 'test', 'fixture', 'http');
constant UPLOAD_DIR (line 15) | const UPLOAD_DIR = join(CWD, 'test', 'tmp');
function findFixtures (line 36) | function findFixtures() {
function testNext (line 50) | function testNext(results) {
function uploadFixture (line 96) | function uploadFixture(fixtureName, cb) {
FILE: test/integration/json.test.js
constant PORT (line 10) | const PORT = 13535;
FILE: test/integration/octet-stream.test.js
constant PORT (line 12) | const PORT = 13536;
FILE: test/integration/store-files-option.test.js
constant PORT (line 13) | const PORT = 13537;
constant DEFAULT_UPLOAD_DIR (line 14) | const DEFAULT_UPLOAD_DIR = join(
constant CUSTOM_UPLOAD_FILE_PATH (line 18) | const CUSTOM_UPLOAD_FILE_PATH = join(DEFAULT_UPLOAD_DIR, 'test-file');
FILE: test/standalone/content-transfer-encoding.test.js
constant UPLOAD_DIR (line 7) | const UPLOAD_DIR = join(process.cwd(), 'test', 'tmp');
constant PORT (line 10) | const PORT = 13530;
FILE: test/standalone/issue-46.test.js
constant PORT (line 7) | const PORT = 13531;
FILE: test/unit/custom-plugins.test.js
function createServer (line 10) | function createServer(options, handler) {
function fromFixtures (line 22) | function fromFixtures(...args) {
FILE: test/unit/formidable.test.js
function requestStub (line 13) | function requestStub() {
function getForm (line 20) | function getForm(name, opts) {
function makeHeader (line 23) | function makeHeader(originalFilename) {
Condensed preview — 120 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (510K chars).
[
{
"path": ".all-contributorsrc",
"chars": 5027,
"preview": "{\n \"projectName\": \"node-formidable\",\n \"projectOwner\": \"node-formidable\",\n \"repoType\": \"github\",\n \"repoHost\": \"https:"
},
{
"path": ".editorconfig",
"chars": 228,
"preview": "# http://editorconfig.org/\nroot = true\n\n[*]\nindent_style = space\nindent_size = 2\ntab_width = 2\nend_of_line = lf\ncharset "
},
{
"path": ".eslintignore",
"chars": 300,
"preview": "# Ignore everything!\n*\n\n# de-ignores: add here what you want to be committed\n!*.*js*\n!*.ts*\n!*.md*\n\n!**/src\n!**/src/**\n\n"
},
{
"path": ".eslintrc.cjs",
"chars": 5241,
"preview": "'use strict';\n\nconst airbnbBase = require('eslint-config-airbnb-base');\n\n// eslint-disable-next-line import/no-dynamic-r"
},
{
"path": ".github/.kodiak.toml",
"chars": 951,
"preview": "# .kodiak.toml\n# Minimal config. version is the only required field.\nversion = 1\n\n[merge] \nautomerge_label = \"ship it\"\nr"
},
{
"path": ".github/dependabot.yml",
"chars": 584,
"preview": "# Versions and updates, dependabot.yml\n\nversion: 2\nupdates:\n\n # Maintain dependencies for GitHub Actions\n - package-ec"
},
{
"path": ".github/workflows/codeql-analysis.yml",
"chars": 2329,
"preview": "# For most projects, this workflow file will not need changing; you simply need\n# to commit it to your repository.\n#\n# Y"
},
{
"path": ".github/workflows/main.yml",
"chars": 1883,
"preview": "name: ci\n\n# on:\n# push:\n# branches: [ master ]\n# pull_request:\n# branches: [ master ]\n\n# jobs:\n# # lint:\n#"
},
{
"path": ".gitignore",
"chars": 1739,
"preview": "# Ignore everything!\n*\n*~*\n\n# de-ignores: add here what you want to be committed\n!logo.png\n!logo.jpg\n!test-legacy\n!tool\n"
},
{
"path": ".prettierignore",
"chars": 1810,
"preview": "# Ignore everything!\n*\n\n# de-ignores: add here what you want to be committed\n\n!*.*js*\n!*.ts*\n!*.md*\n!*.y*ml\n\n!**/src\n!**"
},
{
"path": ".prettierrc.js",
"chars": 388,
"preview": "'use strict';\n\nconst config = require('@tunnckocore/prettier-config');\n\nmodule.exports = {\n ...config,\n overrides: [\n "
},
{
"path": "CHANGELOG.md",
"chars": 11898,
"preview": "# Changelog\n\n### 3.5.4\n\n- fix the `os.machine` breaking some dependents, fix [#994](https://github.com/node-formidable/f"
},
{
"path": "LICENSE",
"chars": 1112,
"preview": "The MIT License (MIT)\n\nCopyright (c) 2011-present Felix Geisendörfer, and contributors.\n\nPermission is hereby granted, f"
},
{
"path": "README.md",
"chars": 38373,
"preview": "<p align=\"center\">\n <img alt=\"npm formidable package logo\" src=\"https://raw.githubusercontent.com/node-formidable/formi"
},
{
"path": "README_pt_BR.md",
"chars": 37222,
"preview": "<p align=\"center\">\n <img alt=\"npm formidable package logo\" src=\"https://raw.githubusercontent.com/node-formidable/formi"
},
{
"path": "VERSION_NOTES.md",
"chars": 2059,
"preview": "\n# Important Notes for v1, v2, and v3\n\nFor more info, check the [CHANGELOG](https://github.com/node-formidable/formidabl"
},
{
"path": "benchmark/2022-11-30-i5-9600k.txt",
"chars": 782,
"preview": "npm run bench\n\n> formidable@3.2.5 bench\n> node benchmark\n\n4132.23 mb/sec\nPS C:\\files\\formidable> node -v \nv18.0.0\n\n"
},
{
"path": "benchmark/e2e.txt",
"chars": 149,
"preview": "node ./benchmark/server.js\nbombardier --body-file=\"./README.md\" --method=POST --duration=10s --connections=100 http://lo"
},
{
"path": "benchmark/index.js",
"chars": 1468,
"preview": "import assert from \"node:assert\";\nimport MultipartParser from '../src/parsers/Multipart.js';\n\n\nconst parser = new Multip"
},
{
"path": "benchmark/server.js",
"chars": 1118,
"preview": "// inital copy of with-http.js\n// made a copy so that examples can be changed without impacting tests\nimport http from '"
},
{
"path": "examples/express-middleware.js",
"chars": 1065,
"preview": "import express from 'express';\nimport formidable from '../src/index.js';\n\nconst app = express();\n\n// middlewares that po"
},
{
"path": "examples/forceBuffer.js",
"chars": 2109,
"preview": "// warning: forcing file into a Buffer elminates the benefits of using streams and may cause memory overflow\nimport http"
},
{
"path": "examples/json.js",
"chars": 1962,
"preview": "import http from 'node:http';\nimport util from 'node:util';\nimport formidable from '../src/index.js';\n\n\nconst PORT = 300"
},
{
"path": "examples/log-file-content-to-console.js",
"chars": 1212,
"preview": "import http from 'node:http';\nimport { Writable } from 'node:stream';\nimport formidable from '../src/index.js';\n\n\nconst "
},
{
"path": "examples/multipart-parser.js",
"chars": 1015,
"preview": "import { Blob } from 'node:buffer';\nimport { Readable } from 'node:stream';\nimport { FormData, formDataToBlob } from 'fo"
},
{
"path": "examples/multiples.js",
"chars": 1726,
"preview": "import http from 'node:http';\nimport os from 'node:os';\nimport formidable from '../src/index.js';\n\n\nconst server = http."
},
{
"path": "examples/store-files-on-s3.js",
"chars": 1509,
"preview": "// To test this example you have to install aws-sdk nodejs package and create a bucket named \"demo-bucket\"\n\nimport http "
},
{
"path": "examples/upload-multiple-files.js",
"chars": 1430,
"preview": "import http from 'node:http';\nimport util from 'node:util';\nimport os from 'node:os';\nimport formidable from '../src/ind"
},
{
"path": "examples/urlencoded-no-enctype.js",
"chars": 1564,
"preview": "import http from 'node:http';\nimport util from 'node:util';\nimport formidable from '../src/index.js';\n\n\nconst server = h"
},
{
"path": "examples/with-express.js",
"chars": 808,
"preview": "import express from 'express';\nimport formidable from '../src/index.js';\n\nconst app = express();\n\napp.get('/', (req, res"
},
{
"path": "examples/with-http.js",
"chars": 2992,
"preview": "import http from 'node:http';\nimport slugify from '@sindresorhus/slugify';\nimport formidable, {errors as formidableError"
},
{
"path": "examples/with-koa2.js",
"chars": 1663,
"preview": "import Koa from 'koa';\nimport formidable from '../src/index.js';\n\n\nconst app = new Koa();\n\napp.on('error', (err) => {\n "
},
{
"path": "nyc.config.js",
"chars": 225,
"preview": "'use strict';\n\nmodule.exports = {\n statements: 70,\n branches: 70,\n functions: 70,\n lines: 70,\n\n 'check-coverage': t"
},
{
"path": "package.json",
"chars": 3446,
"preview": "{\n \"name\": \"formidable\",\n \"version\": \"3.5.4\",\n \"license\": \"MIT\",\n \"description\": \"A node.js module for parsing form "
},
{
"path": "pnpm-lock.yaml",
"chars": 193783,
"preview": "lockfileVersion: '9.0'\n\nsettings:\n autoInstallPeers: true\n excludeLinksFromLockfile: false\n\nimporters:\n\n .:\n depen"
},
{
"path": "src/Formidable.js",
"chars": 18944,
"preview": "/* eslint-disable class-methods-use-this */\n/* eslint-disable no-underscore-dangle */\n\nimport { init as cuid2init } from"
},
{
"path": "src/FormidableError.js",
"chars": 1242,
"preview": "const missingPlugin = 1000;\nconst pluginFunction = 1001;\nconst aborted = 1002;\nconst noParser = 1003;\nconst uninitialize"
},
{
"path": "src/PersistentFile.js",
"chars": 1988,
"preview": "/* eslint-disable no-underscore-dangle */\n\nimport fs from 'node:fs';\nimport crypto from 'node:crypto';\nimport { EventEmi"
},
{
"path": "src/VolatileFile.js",
"chars": 1752,
"preview": "/* eslint-disable no-underscore-dangle */\n\nimport { createHash } from 'node:crypto';\nimport { EventEmitter } from 'node:"
},
{
"path": "src/helpers/firstValues.js",
"chars": 496,
"preview": "import { multipartType } from '../plugins/multipart.js';\nimport { querystringType } from '../plugins/querystring.js';\n\nc"
},
{
"path": "src/helpers/readBooleans.js",
"chars": 310,
"preview": "const readBooleans = (fields, listOfBooleans) => {\n // html forms do not send off at all\n const fieldsWithBooleans = {"
},
{
"path": "src/index.js",
"chars": 754,
"preview": "import PersistentFile from './PersistentFile.js';\nimport VolatileFile from './VolatileFile.js';\nimport Formidable, { DEF"
},
{
"path": "src/parsers/Dummy.js",
"chars": 407,
"preview": "/* eslint-disable no-underscore-dangle */\n\nimport { Transform } from 'node:stream';\n\nclass DummyParser extends Transform"
},
{
"path": "src/parsers/JSON.js",
"chars": 643,
"preview": "/* eslint-disable no-underscore-dangle */\n\nimport { Transform } from 'node:stream';\n\nclass JSONParser extends Transform "
},
{
"path": "src/parsers/Multipart.js",
"chars": 9824,
"preview": "/* eslint-disable no-fallthrough */\n/* eslint-disable no-bitwise */\n/* eslint-disable no-plusplus */\n/* eslint-disable n"
},
{
"path": "src/parsers/OctetStream.js",
"chars": 215,
"preview": "import { PassThrough } from 'node:stream';\n\nclass OctetStreamParser extends PassThrough {\n constructor(options = {}) {\n"
},
{
"path": "src/parsers/Querystring.js",
"chars": 797,
"preview": "/* eslint-disable no-underscore-dangle */\n\nimport { Transform } from 'node:stream';\n\n// This is a buffering parser, have"
},
{
"path": "src/parsers/StreamingQuerystring.js",
"chars": 3256,
"preview": "// not used\n/* eslint-disable no-underscore-dangle */\n\nimport { Transform } from 'node:stream';\nimport FormidableError, "
},
{
"path": "src/parsers/index.js",
"chars": 407,
"preview": "import JSONParser from './JSON.js';\nimport DummyParser from './Dummy.js';\nimport MultipartParser from './Multipart.js';\n"
},
{
"path": "src/plugins/index.js",
"chars": 213,
"preview": "import octetstream from './octetstream.js';\nimport querystring from './querystring.js';\nimport multipart from './multipa"
},
{
"path": "src/plugins/json.js",
"chars": 1099,
"preview": "/* eslint-disable no-underscore-dangle */\n\nimport JSONParser from '../parsers/JSON.js';\n\nexport const jsonType = 'json';"
},
{
"path": "src/plugins/multipart.js",
"chars": 6089,
"preview": "/* eslint-disable no-underscore-dangle */\n\nimport { Stream } from 'node:stream';\nimport MultipartParser from '../parsers"
},
{
"path": "src/plugins/octetstream.js",
"chars": 2246,
"preview": "/* eslint-disable no-underscore-dangle */\n\nimport OctetStreamParser from '../parsers/OctetStream.js';\n\nexport const octe"
},
{
"path": "src/plugins/querystring.js",
"chars": 1180,
"preview": "/* eslint-disable no-underscore-dangle */\n\n\nimport QuerystringParser from '../parsers/Querystring.js';\n\nexport const que"
},
{
"path": "test/fixture/file/funkyfilename.txt",
"chars": 36,
"preview": "I am a text file with a funky name!\n"
},
{
"path": "test/fixture/file/plain.txt",
"chars": 30,
"preview": "I am a simple plain text file\n"
},
{
"path": "test/fixture/file/second-plaintext.txt",
"chars": 36,
"preview": "Some another plain text file, yeah!\n"
},
{
"path": "test/fixture/http/encoding/beta-sticker-1.png.http",
"chars": 2658,
"preview": "POST /upload HTTP/1.1\r\nHost: localhost:8080\r\nContent-Type: multipart/form-data; boundary=\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\"
},
{
"path": "test/fixture/http/encoding/binaryfile.tar.gz.http",
"chars": 850,
"preview": "POST /upload HTTP/1.1\r\nHost: localhost:8080\r\nContent-Type: multipart/form-data; boundary=\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\"
},
{
"path": "test/fixture/http/encoding/blank.gif.http",
"chars": 497,
"preview": "POST /upload HTTP/1.1\r\nHost: localhost:8080\r\nContent-Type: multipart/form-data; boundary=\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\"
},
{
"path": "test/fixture/http/encoding/menu_separator.png.http",
"chars": 1684,
"preview": "POST /upload HTTP/1.1\r\nHost: localhost:8080\r\nContent-Type: multipart/form-data; boundary=\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\"
},
{
"path": "test/fixture/http/encoding/plain.txt.http",
"chars": 352,
"preview": "POST /upload HTTP/1.1\r\nHost: localhost:8080\r\nContent-Type: multipart/form-data; boundary=----TLV0SrKD4z1TRxRhAPUvZ\r\nCont"
},
{
"path": "test/fixture/http/misc/boundary-substring-json.http",
"chars": 369,
"preview": "POST /upload HTTP/1.1\r\nHost: localhost:8080\r\nContent-Type: multipart/form-data; boundary=uj05Dyqd7Fd5aqAJnK1j9WeJSONmNy5"
},
{
"path": "test/fixture/http/misc/empty-multipart.http",
"chars": 137,
"preview": "POST /upload HTTP/1.1\r\nHost: localhost:8080\r\nContent-Type: multipart/form-data; boundary=----TLV0SrKD4z1TRxRhAPUvZ\r\nCont"
},
{
"path": "test/fixture/http/misc/empty-multipart2.http",
"chars": 169,
"preview": "POST /upload HTTP/1.1\r\nHost: localhost:8080\r\nContent-Type: multipart/form-data; boundary=----TLV0SrKD4z1TRxRhAPUvZ\r\nCont"
},
{
"path": "test/fixture/http/misc/empty-urlencoded.http",
"chars": 115,
"preview": "POST /upload HTTP/1.1\r\nHost: localhost:8080\r\nContent-Length: 0\r\nContent-Type: application/x-www-form-urlencoded\r\n\r\n"
},
{
"path": "test/fixture/http/misc/empty.http",
"chars": 66,
"preview": "POST /upload HTTP/1.1\r\nHost: localhost:8080\r\nContent-Length: 0\r\n\r\n"
},
{
"path": "test/fixture/http/misc/minimal.http",
"chars": 47,
"preview": "POST /upload HTTP/1.1\r\nHost: localhost:8080\r\n\r\n"
},
{
"path": "test/fixture/http/no-filename/filename-name.http",
"chars": 364,
"preview": "POST /upload HTTP/1.1\r\nHost: localhost:8080\r\nContent-Type: multipart/form-data; boundary=----WebKitFormBoundarytyE4wkKlZ"
},
{
"path": "test/fixture/http/no-filename/generic.http",
"chars": 353,
"preview": "POST /upload HTTP/1.1\r\nHost: localhost:8080\r\nContent-Type: multipart/form-data; boundary=----WebKitFormBoundarytyE4wkKlZ"
},
{
"path": "test/fixture/http/preamble/crlf.http",
"chars": 323,
"preview": "POST /upload HTTP/1.1\r\nHost: localhost:8080\r\nContent-Type: multipart/form-data; boundary=----TLV0SrKD4z1TRxRhAPUvZ\r\nCont"
},
{
"path": "test/fixture/http/preamble/preamble.http",
"chars": 366,
"preview": "POST /upload HTTP/1.1\r\nHost: localhost:8080\r\nContent-Type: multipart/form-data; boundary=----TLV0SrKD4z1TRxRhAPUvZ\r\nCont"
},
{
"path": "test/fixture/http/special-chars-in-filename/info.md",
"chars": 227,
"preview": "- Opera does not allow submitting this file, it shows a warning to the\n user that the file could not be found instead. "
},
{
"path": "test/fixture/http/special-chars-in-filename/line-separator.http",
"chars": 465,
"preview": "POST /upload HTTP/1.1\nHost: localhost:8080\nReferer: http://localhost:8080/\nContent-Length: 383\nOrigin: http://localhost:"
},
{
"path": "test/fixture/http/special-chars-in-filename/osx-chrome-13.http",
"chars": 1063,
"preview": "POST /upload HTTP/1.1\r\nHost: localhost:8080\r\nConnection: keep-alive\r\nReferer: http://localhost:8080/\r\nContent-Length: 38"
},
{
"path": "test/fixture/http/special-chars-in-filename/osx-firefox-3.6.http",
"chars": 977,
"preview": "POST /upload HTTP/1.1\r\nHost: localhost:8080\r\nUser-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2"
},
{
"path": "test/fixture/http/special-chars-in-filename/osx-safari-5.http",
"chars": 920,
"preview": "POST /upload HTTP/1.1\r\nHost: localhost:8080\r\nOrigin: http://localhost:8080\r\nContent-Length: 383\r\nUser-Agent: Mozilla/5.0"
},
{
"path": "test/fixture/http/special-chars-in-filename/xp-chrome-12.http",
"chars": 945,
"preview": "POST /upload HTTP/1.1\r\nHost: 192.168.56.1:8080\r\nConnection: keep-alive\r\nReferer: http://192.168.56.1:8080/\r\nContent-Leng"
},
{
"path": "test/fixture/http/special-chars-in-filename/xp-ie-7.http",
"chars": 820,
"preview": "POST /upload HTTP/1.1\r\nAccept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, */*\r\nRefe"
},
{
"path": "test/fixture/http/special-chars-in-filename/xp-ie-8.http",
"chars": 833,
"preview": "POST /upload HTTP/1.1\r\nAccept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, */*\r\nRefe"
},
{
"path": "test/fixture/http/special-chars-in-filename/xp-safari-5.http",
"chars": 881,
"preview": "POST /upload HTTP/1.1\r\nHost: 192.168.56.1:8080\r\nReferer: http://192.168.56.1:8080/\r\nAccept: application/xml,application/"
},
{
"path": "test/fixture/http/workarounds/missing-hyphens1.http",
"chars": 327,
"preview": "POST /upload HTTP/1.1\r\nHost: localhost:8080\r\nContent-Type: multipart/form-data; boundary=----TLV0SrKD4z1TRxRhAPUvZ\r\nCont"
},
{
"path": "test/fixture/http/workarounds/missing-hyphens2.http",
"chars": 350,
"preview": "POST /upload HTTP/1.1\r\nHost: localhost:8080\r\nContent-Type: multipart/form-data; boundary=----TLVx0SrKD4z1TRxRhAPUvZx\r\nCo"
},
{
"path": "test/fixture/js/encoding.js",
"chars": 1155,
"preview": "const menu_separator_png_http = [\n {\n type: 'file',\n name: 'image',\n originalFilename: 'menu_separator.png',\n "
},
{
"path": "test/fixture/js/misc.js",
"chars": 455,
"preview": "const boundary_substring_json = [\n {\n type: 'file',\n name: 'upload',\n originalFilename: 'plain.txt',\n fixtu"
},
{
"path": "test/fixture/js/no-filename.js",
"chars": 422,
"preview": "const generic_http = [\n {\n type: 'file',\n name: 'upload',\n originalFilename: '',\n fixture: 'generic',\n s"
},
{
"path": "test/fixture/js/preamble.js",
"chars": 407,
"preview": "const crlf_http = [\n {\n type: 'file',\n name: 'upload',\n originalFilename: 'plain.txt',\n fixture: 'crlf',\n "
},
{
"path": "test/fixture/js/special-chars-in-filename.js",
"chars": 1102,
"preview": "const properFilename = 'funkyfilename.txt';\n\nfunction expect(originalFilename, fixtureName) {\n return [\n {\n typ"
},
{
"path": "test/fixture/js/workarounds.js",
"chars": 478,
"preview": "const missing_hyphens1_http = [\n {\n type: 'file',\n name: 'upload',\n originalFilename: 'plain.txt',\n fixture"
},
{
"path": "test/fixture/multipart.js",
"chars": 1988,
"preview": "exports.rfc1867 = {\n boundary: 'AaB03x',\n raw:\n '--AaB03x\\r\\n' +\n 'content-disposition: form-data; name=\"field1\""
},
{
"path": "test/integration/file-write-stream-handler-option.test.js",
"chars": 2134,
"preview": "import { existsSync, mkdirSync, createWriteStream, readdirSync, statSync, unlinkSync, createReadStream } from 'node:fs';"
},
{
"path": "test/integration/fixtures.test.js",
"chars": 3874,
"preview": "/* eslint-disable global-require */\n/* eslint-disable import/no-dynamic-require */\n\nimport { createReadStream } from 'no"
},
{
"path": "test/integration/json.test.js",
"chars": 899,
"preview": "import { createServer, request as _request } from 'node:http';\nimport assert, { deepStrictEqual } from 'node:assert';\nim"
},
{
"path": "test/integration/octet-stream.test.js",
"chars": 1335,
"preview": "import { readFileSync, createReadStream } from 'node:fs';\nimport { createServer, request as _request } from 'node:http';"
},
{
"path": "test/integration/store-files-option.test.js",
"chars": 1827,
"preview": "import { existsSync, mkdirSync, WriteStream, statSync, unlinkSync, createReadStream } from 'node:fs';\nimport { tmpdir } "
},
{
"path": "test/standalone/connection-aborted.test.js",
"chars": 1284,
"preview": "import assert from 'node:assert';\nimport { createServer } from 'node:http';\nimport { connect } from 'node:net';\nimport f"
},
{
"path": "test/standalone/content-transfer-encoding.test.js",
"chars": 1669,
"preview": "import { join } from 'node:path';\nimport { createServer, request } from 'node:http';\nimport { strictEqual } from 'node:a"
},
{
"path": "test/standalone/issue-46.test.js",
"chars": 1257,
"preview": "import { createServer, request } from \"node:http\";\nimport { ok, strictEqual } from \"node:assert\";\nimport { Buffer } from"
},
{
"path": "test/standalone/keep-alive-error.test.js",
"chars": 2073,
"preview": "/* eslint-disable max-nested-callbacks */\n\nimport assert from 'node:assert/strict';\nimport { createServer } from 'node:h"
},
{
"path": "test/tools/base64.html",
"chars": 2426,
"preview": "<html>\n <head>\n <title>Convert a file to a base64 request</title>\n\n <script type=\"text/javascript\">\n functio"
},
{
"path": "test/unit/custom-plugins.test.js",
"chars": 5302,
"preview": "/* eslint-disable no-underscore-dangle */\n\nimport { join } from 'node:path';\n\nimport Koa from 'koa';\nimport request from"
},
{
"path": "test/unit/formidable.test.js",
"chars": 11454,
"preview": "/* eslint-disable max-statements */\n/* eslint-disable no-underscore-dangle */\n\nimport {jest} from '@jest/globals';\nimpor"
},
{
"path": "test/unit/multipart-parser.test.js",
"chars": 1754,
"preview": "import { MultipartParser } from '../../src/index.js';\n\ntest('on constructor', () => {\n const parser = new MultipartPars"
},
{
"path": "test/unit/persistent-file.disabled-test.js",
"chars": 1134,
"preview": "import {jest} from '@jest/globals';\nimport fs from 'node:fs';\nimport PersistentFile from '../../src/PersistentFile.js';\n"
},
{
"path": "test/unit/querystring-parser.test.js",
"chars": 697,
"preview": "import { QuerystringParser } from '../../src/index.js';\n\ntest('on constructor', () => {\n const parser = new Querystring"
},
{
"path": "test/unit/volatile-file.test.js",
"chars": 1828,
"preview": "import {jest} from '@jest/globals';\nimport VolatileFile from '../../src/VolatileFile.js';\n\n\ndescribe('VolatileFile', () "
},
{
"path": "test-legacy/README.md",
"chars": 99,
"preview": "These tests were deleted due to failures when removing the gently lib.\npreviously in `test/legacy`\n"
},
{
"path": "test-legacy/common.js",
"chars": 532,
"preview": "const path = require('path');\nconst fs = require('fs');\n\nexports.lib = path.join(__dirname, '../../lib');\n\nglobal.assert"
},
{
"path": "test-legacy/integration/test-multipart-parser.js",
"chars": 2077,
"preview": "const common = require('../common');\n\nconst CHUNK_LENGTH = 10;\nconst multipartParser = require(`${common.lib}/multipart_"
},
{
"path": "test-legacy/simple/test-file.js",
"chars": 2302,
"preview": "const common = require('../common');\n\nconst WriteStreamStub = GENTLY.stub('fs', 'WriteStream');\n\nconst File = require(`$"
},
{
"path": "test-legacy/simple/test-incoming-form.js",
"chars": 20140,
"preview": "const common = require('../common');\n\nconst MultipartParserStub = GENTLY.stub(\n './multipart_parser',\n 'MultipartParse"
},
{
"path": "test-legacy/system/test-multi-video-upload.js",
"chars": 2432,
"preview": "const common = require('../common');\n\nconst BOUNDARY = '---------------------------10102754414578508781458777923';\nconst"
},
{
"path": "test-node/standalone/createDirsFromUploads.test.js",
"chars": 1631,
"preview": "import {strictEqual, deepEqual} from 'node:assert';\nimport { createServer, request } from 'node:http';\nimport formidable"
},
{
"path": "test-node/standalone/end-event-emitted-twice.test.js",
"chars": 1476,
"preview": "import {strictEqual} from 'node:assert';\nimport { createServer, request } from 'node:http';\nimport formidable from '../."
},
{
"path": "test-node/standalone/multipart_parser.test.js",
"chars": 806,
"preview": "import {Readable} from 'node:stream';\nimport MultipartParser from '../../src/parsers/Multipart.js';\nimport {malformedMul"
},
{
"path": "test-node/standalone/promise.test.js",
"chars": 3001,
"preview": "import { ok, strictEqual } from 'node:assert';\nimport { createServer } from 'node:http';\nimport test from 'node:test';\ni"
},
{
"path": "tool/record.js",
"chars": 1324,
"preview": "/* eslint-disable no-param-reassign */\nconst http = require('http');\nconst fs = require('fs');\n\nlet connections = 0;\n\nco"
},
{
"path": "tool/rollup.config.js",
"chars": 1843,
"preview": "/* eslint-disable */\nimport cjs from '@rollup/plugin-commonjs';\nimport { nodeResolve } from '@rollup/plugin-node-resolve"
}
]
// ... and 2 more files (download for full content)
About this extraction
This page contains the full source code of the node-formidable/formidable GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 120 files (472.6 KB), approximately 174.6k tokens, and a symbol index with 125 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.