2
0
mirror of https://github.com/tenrok/axios.git synced 2026-06-23 20:40:40 +03:00

Improved FormData support; (#4448)

* Fixed isFormData predicate;
Added support for automatic object serialization to FormData if `Content-Type` is `multipart/form-data`;
Added support for FormData to be overloaded using `config.env.FormData` option;
Added support for FormData in node.js environment through `form-data` package;

* Added the `form-data` package as a dependency for the server build;
Added tests for FormData payload;

* Added FormData automatic serialization section;
Refactored cancellation section;

* Reworked toFormData helper;
Expose toFormData helper as a static method;
Refactored transform request;
Added kindOf, kindOfTest, endsWith, isTypedArray util;
Refactored utils.js to use kindOf for tests;

* Fixed isFormData predicate; (#4413)

Added support for automatic object serialization to FormData if `Content-Type` is `multipart/form-data`;
Added support for FormData to be overloaded using `config.env.FormData` option;
Added support for FormData in node.js environment using `form-data` package;

(cherry picked from commit 73e3bdb883)

* Added shortcut methods `postForm`, `putForm`, `patchForm` to submit a Form;
Added ability to submit FileList object as a FormData;
Updated README.md;

* Updated README.md;
This commit is contained in:
Dmitriy Mozgovoy
2022-03-14 20:22:10 +02:00
committed by GitHub
parent c9aca75257
commit 6b9b05b907
22 changed files with 716 additions and 242 deletions
+100 -29
View File
@@ -23,7 +23,7 @@ Promise based HTTP client for the browser and node.js
- [Example](#example) - [Example](#example)
- [Axios API](#axios-api) - [Axios API](#axios-api)
- [Request method aliases](#request-method-aliases) - [Request method aliases](#request-method-aliases)
- [Concurrency (Deprecated)](#concurrency-deprecated) - [Concurrency 👎](#concurrency-deprecated)
- [Creating an instance](#creating-an-instance) - [Creating an instance](#creating-an-instance)
- [Instance methods](#instance-methods) - [Instance methods](#instance-methods)
- [Request Config](#request-config) - [Request Config](#request-config)
@@ -36,11 +36,15 @@ Promise based HTTP client for the browser and node.js
- [Multiple Interceptors](#multiple-interceptors) - [Multiple Interceptors](#multiple-interceptors)
- [Handling Errors](#handling-errors) - [Handling Errors](#handling-errors)
- [Cancellation](#cancellation) - [Cancellation](#cancellation)
- [AbortController](#abortcontroller)
- [CancelToken 👎](#canceltoken-deprecated)
- [Using application/x-www-form-urlencoded format](#using-applicationx-www-form-urlencoded-format) - [Using application/x-www-form-urlencoded format](#using-applicationx-www-form-urlencoded-format)
- [Browser](#browser) - [Browser](#browser)
- [Node.js](#nodejs) - [Node.js](#nodejs)
- [Query string](#query-string) - [Query string](#query-string)
- [Form data](#form-data) - [Form data](#form-data)
- [Automatic serialization](#-automatic-serialization)
- [Manual FormData passing](#manual-formdata-passing)
- [Semver](#semver) - [Semver](#semver)
- [Promises](#promises) - [Promises](#promises)
- [TypeScript](#typescript) - [TypeScript](#typescript)
@@ -483,6 +487,11 @@ These are the available config options for making requests. Only the `url` is re
// throw ETIMEDOUT error instead of generic ECONNABORTED on request timeouts // throw ETIMEDOUT error instead of generic ECONNABORTED on request timeouts
clarifyTimeoutError: false, clarifyTimeoutError: false,
},
env: {
// The FormData class to be used to automatically serialize the payload into a FormData object
FormData: window?.FormData || global?.FormData
} }
} }
``` ```
@@ -707,10 +716,30 @@ axios.get('/user/12345')
## Cancellation ## Cancellation
You can cancel a request using a *cancel token*. ### AbortController
Starting from `v0.22.0` Axios supports AbortController to cancel requests in fetch API way:
```js
const controller = new AbortController();
axios.get('/foo/bar', {
signal: controller.signal
}).then(function(response) {
//...
});
// cancel the request
controller.abort()
```
### CancelToken `👎deprecated`
You can also cancel a request using a *CancelToken*.
> The axios cancel token API is based on the withdrawn [cancelable promises proposal](https://github.com/tc39/proposal-cancelable-promises). > The axios cancel token API is based on the withdrawn [cancelable promises proposal](https://github.com/tc39/proposal-cancelable-promises).
> This API is deprecated since v0.22.0 and shouldn't be used in new projects
You can create a cancel token using the `CancelToken.source` factory as shown below: You can create a cancel token using the `CancelToken.source` factory as shown below:
```js ```js
@@ -754,22 +783,11 @@ axios.get('/user/12345', {
cancel(); cancel();
``` ```
Axios supports AbortController to abort requests in [`fetch API`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API#aborting_a_fetch) way:
```js
const controller = new AbortController();
axios.get('/foo/bar', {
signal: controller.signal
}).then(function(response) {
//...
});
// cancel the request
controller.abort()
```
> Note: you can cancel several requests with the same cancel token/abort controller. > Note: you can cancel several requests with the same cancel token/abort controller.
> If a cancellation token is already cancelled at the moment of starting an Axios request, then the request is cancelled immediately, without any attempts to make real request. > If a cancellation token is already cancelled at the moment of starting an Axios request, then the request is cancelled immediately, without any attempts to make real request.
> During the transition period, you can use both cancellation APIs, even for the same request:
## Using application/x-www-form-urlencoded format ## Using application/x-www-form-urlencoded format
By default, axios serializes JavaScript objects to `JSON`. To send data in the `application/x-www-form-urlencoded` format instead, you can use one of the following options. By default, axios serializes JavaScript objects to `JSON`. To send data in the `application/x-www-form-urlencoded` format instead, you can use one of the following options.
@@ -829,11 +847,75 @@ axios.post('http://something.com/', params.toString());
You can also use the [`qs`](https://github.com/ljharb/qs) library. You can also use the [`qs`](https://github.com/ljharb/qs) library.
###### NOTE > NOTE:
The `qs` library is preferable if you need to stringify nested objects, as the `querystring` method has known issues with that use case (https://github.com/nodejs/node-v0.x-archive/issues/1665). > The `qs` library is preferable if you need to stringify nested objects, as the `querystring` method has [known issues](https://github.com/nodejs/node-v0.x-archive/issues/1665) with that use case.
#### Form data #### Form data
##### 🆕 Automatic serialization
Starting from `v0.27.0`, Axios supports automatic object serialization to a FormData object if the request `Content-Type`
header is set to `multipart/form-data`.
The following request will submit the data in a FormData format (Browser & Node.js):
```js
import axios from 'axios';
axios.post('https://httpbin.org/post', {x: 1}, {
headers: {
'Content-Type': 'multipart/form-data'
}
}).then(({data})=> console.log(data));
```
In the `node.js` build, the ([`form-data`](https://github.com/form-data/form-data)) polyfill is used by default.
You can overload the FormData class by setting the `env.FormData` config variable,
but you probably won't need it in most cases:
```js
const axios= require('axios');
var FormData = require('form-data');
axios.post('https://httpbin.org/post', {x: 1, buf: new Buffer(10)}, {
headers: {
'Content-Type': 'multipart/form-data'
}
}).then(({data})=> console.log(data));
```
Axios FormData serializer supports some special endings to perform the following operations:
- `{}` - serialize the value with JSON.stringify
- `[]` - unwrap the array like object as separate fields with the same key
```js
const axios= require('axios');
axios.post('https://httpbin.org/post', {
'myObj{}': {x: 1, s: "foo"},
'files[]': document.querySelector('#fileInput').files
}, {
headers: {
'Content-Type': 'multipart/form-data'
}
}).then(({data})=> console.log(data));
```
Axios supports the following shortcut methods: `postForm`, `putForm`, `patchForm`
which are just the corresponding http methods with a header preset: `Content-Type`: `multipart/form-data`.
FileList object can be passed directly:
```js
await axios.postForm('https://httpbin.org/post', document.querySelector('#fileInput').files)
```
All files will be sent with the same field names: `files[]`;
##### Manual FormData passing
In node.js, you can use the [`form-data`](https://github.com/form-data/form-data) library as follows: In node.js, you can use the [`form-data`](https://github.com/form-data/form-data) library as follows:
```js ```js
@@ -844,18 +926,7 @@ form.append('my_field', 'my value');
form.append('my_buffer', new Buffer(10)); form.append('my_buffer', new Buffer(10));
form.append('my_file', fs.createReadStream('/foo/bar.jpg')); form.append('my_file', fs.createReadStream('/foo/bar.jpg'));
axios.post('https://example.com', form, { headers: form.getHeaders() }) axios.post('https://example.com', form)
```
Alternatively, use an interceptor:
```js
axios.interceptors.request.use(config => {
if (config.data instanceof FormData) {
Object.assign(config.headers, config.data.getHeaders());
}
return config;
});
``` ```
## Semver ## Semver
Vendored
+6
View File
@@ -107,6 +107,9 @@ export interface AxiosRequestConfig<D = any> {
transitional?: TransitionalOptions; transitional?: TransitionalOptions;
signal?: AbortSignal; signal?: AbortSignal;
insecureHTTPParser?: boolean; insecureHTTPParser?: boolean;
env?: {
FormData?: new (...args: any[]) => object;
};
} }
export interface HeadersDefaults { export interface HeadersDefaults {
@@ -197,6 +200,9 @@ export class Axios {
post<T = any, R = AxiosResponse<T>, D = any>(url: string, data?: D, config?: AxiosRequestConfig<D>): Promise<R>; post<T = any, R = AxiosResponse<T>, D = any>(url: string, data?: D, config?: AxiosRequestConfig<D>): Promise<R>;
put<T = any, R = AxiosResponse<T>, D = any>(url: string, data?: D, config?: AxiosRequestConfig<D>): Promise<R>; put<T = any, R = AxiosResponse<T>, D = any>(url: string, data?: D, config?: AxiosRequestConfig<D>): Promise<R>;
patch<T = any, R = AxiosResponse<T>, D = any>(url: string, data?: D, config?: AxiosRequestConfig<D>): Promise<R>; patch<T = any, R = AxiosResponse<T>, D = any>(url: string, data?: D, config?: AxiosRequestConfig<D>): Promise<R>;
postForm<T = any, R = AxiosResponse<T>, D = any>(url: string, data?: D, config?: AxiosRequestConfig<D>): Promise<R>;
putForm<T = any, R = AxiosResponse<T>, D = any>(url: string, data?: D, config?: AxiosRequestConfig<D>): Promise<R>;
patchForm<T = any, R = AxiosResponse<T>, D = any>(url: string, data?: D, config?: AxiosRequestConfig<D>): Promise<R>;
} }
export interface AxiosInstance extends Axios { export interface AxiosInstance extends Axios {
+4 -1
View File
@@ -87,7 +87,10 @@ module.exports = function httpAdapter(config) {
headers['User-Agent'] = 'axios/' + VERSION; headers['User-Agent'] = 'axios/' + VERSION;
} }
if (data && !utils.isStream(data)) { // support for https://www.npmjs.com/package/form-data api
if (utils.isFormData(data) && utils.isFunction(data.getHeaders)) {
Object.assign(headers, data.getHeaders());
} else if (data && !utils.isStream(data)) {
if (Buffer.isBuffer(data)) { if (Buffer.isBuffer(data)) {
// Nothing to do... // Nothing to do...
} else if (utils.isArrayBuffer(data)) { } else if (utils.isArrayBuffer(data)) {
+1
View File
@@ -41,6 +41,7 @@ axios.Cancel = require('./cancel/Cancel');
axios.CancelToken = require('./cancel/CancelToken'); axios.CancelToken = require('./cancel/CancelToken');
axios.isCancel = require('./cancel/isCancel'); axios.isCancel = require('./cancel/isCancel');
axios.VERSION = require('./env/data').version; axios.VERSION = require('./env/data').version;
axios.toFormData = require('./helpers/toFormData');
// Expose all/spread // Expose all/spread
axios.all = function all(promises) { axios.all = function all(promises) {
+17 -7
View File
@@ -136,13 +136,23 @@ utils.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData
utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) { utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {
/*eslint func-names:0*/ /*eslint func-names:0*/
Axios.prototype[method] = function(url, data, config) {
return this.request(mergeConfig(config || {}, { function generateHTTPMethod(isForm) {
method: method, return function httpMethod(url, data, config) {
url: url, return this.request(mergeConfig(config || {}, {
data: data method: method,
})); headers: isForm ? {
}; 'Content-Type': 'multipart/form-data'
} : {},
url: url,
data: data
}));
};
}
Axios.prototype[method] = generateHTTPMethod();
Axios.prototype[method + 'Form'] = generateHTTPMethod(true);
}); });
module.exports = Axios; module.exports = Axios;
+16 -1
View File
@@ -3,6 +3,7 @@
var utils = require('./utils'); var utils = require('./utils');
var normalizeHeaderName = require('./helpers/normalizeHeaderName'); var normalizeHeaderName = require('./helpers/normalizeHeaderName');
var enhanceError = require('./core/enhanceError'); var enhanceError = require('./core/enhanceError');
var toFormData = require('./helpers/toFormData');
var DEFAULT_CONTENT_TYPE = { var DEFAULT_CONTENT_TYPE = {
'Content-Type': 'application/x-www-form-urlencoded' 'Content-Type': 'application/x-www-form-urlencoded'
@@ -71,10 +72,20 @@ var defaults = {
setContentTypeIfUnset(headers, 'application/x-www-form-urlencoded;charset=utf-8'); setContentTypeIfUnset(headers, 'application/x-www-form-urlencoded;charset=utf-8');
return data.toString(); return data.toString();
} }
if (utils.isObject(data) || (headers && headers['Content-Type'] === 'application/json')) {
var isObjectPayload = utils.isObject(data);
var contentType = headers && headers['Content-Type'];
var isFileList;
if ((isFileList = utils.isFileList(data)) || (isObjectPayload && contentType === 'multipart/form-data')) {
var _FormData = this.env && this.env.FormData;
return toFormData(isFileList ? {'files[]': data} : data, _FormData && new _FormData());
} else if (isObjectPayload || contentType === 'application/json') {
setContentTypeIfUnset(headers, 'application/json'); setContentTypeIfUnset(headers, 'application/json');
return stringifySafely(data); return stringifySafely(data);
} }
return data; return data;
}], }],
@@ -112,6 +123,10 @@ var defaults = {
maxContentLength: -1, maxContentLength: -1,
maxBodyLength: -1, maxBodyLength: -1,
env: {
FormData: require('./defaults/env/FormData')
},
validateStatus: function validateStatus(status) { validateStatus: function validateStatus(status) {
return status >= 200 && status < 300; return status >= 200 && status < 300;
}, },
+2
View File
@@ -0,0 +1,2 @@
// eslint-disable-next-line strict
module.exports = require('form-data');
+2
View File
@@ -0,0 +1,2 @@
// eslint-disable-next-line strict
module.exports = null;
+65 -47
View File
@@ -1,55 +1,73 @@
'use strict'; 'use strict';
function combinedKey(parentKey, elKey) { var utils = require('../utils');
return parentKey + '.' + elKey;
}
function buildFormData(formData, data, parentKey) {
if (Array.isArray(data)) {
data.forEach(function buildArray(el, i) {
buildFormData(formData, el, combinedKey(parentKey, i));
});
} else if (
typeof data === 'object' &&
!(data instanceof File || data === null)
) {
Object.keys(data).forEach(function buildObject(key) {
buildFormData(
formData,
data[key],
parentKey ? combinedKey(parentKey, key) : key
);
});
} else {
if (data === undefined) {
return;
}
var value =
typeof data === 'boolean' || typeof data === 'number'
? data.toString()
: data;
formData.append(parentKey, value);
}
}
/** /**
* convert a data object to FormData * Convert a data object to FormData
* * @param {Object} obj
* type FormDataPrimitive = string | Blob | number | boolean * @param {?Object} [formData]
* interface FormDataNest { * @returns {Object}
* [x: string]: FormVal **/
* }
*
* type FormVal = FormDataNest | FormDataPrimitive
*
* @param {FormVal} data
*/
module.exports = function getFormData(data) { function toFormData(obj, formData) {
var formData = new FormData(); // eslint-disable-next-line no-param-reassign
formData = formData || new FormData();
buildFormData(formData, data); var stack = [];
function convertValue(value) {
if (value === null) return '';
if (utils.isDate(value)) {
return value.toISOString();
}
if (utils.isArrayBuffer(value) || utils.isTypedArray(value)) {
return typeof Blob === 'function' ? new Blob([value]) : Buffer.from(value);
}
return value;
}
function build(data, parentKey) {
if (utils.isPlainObject(data) || utils.isArray(data)) {
if (stack.indexOf(data) !== -1) {
throw Error('Circular reference detected in ' + parentKey);
}
stack.push(data);
utils.forEach(data, function each(value, key) {
if (utils.isUndefined(value)) return;
var fullKey = parentKey ? parentKey + '.' + key : key;
var arr;
if (value && !parentKey && typeof value === 'object') {
if (utils.endsWith(key, '{}')) {
// eslint-disable-next-line no-param-reassign
value = JSON.stringify(value);
} else if (utils.endsWith(key, '[]') && (arr = utils.toArray(value))) {
// eslint-disable-next-line func-names
arr.forEach(function(el) {
!utils.isUndefined(el) && formData.append(fullKey, convertValue(el));
});
return;
}
}
build(value, fullKey);
});
stack.pop();
} else {
formData.append(parentKey, convertValue(data));
}
}
build(obj);
return formData; return formData;
}; }
module.exports = toFormData;
+100 -27
View File
@@ -6,6 +6,22 @@ var bind = require('./helpers/bind');
var toString = Object.prototype.toString; var toString = Object.prototype.toString;
// eslint-disable-next-line func-names
var kindOf = (function(cache) {
// eslint-disable-next-line func-names
return function(thing) {
var str = toString.call(thing);
return cache[str] || (cache[str] = str.slice(8, -1).toLowerCase());
};
})(Object.create(null));
function kindOfTest(type) {
type = type.toLowerCase();
return function isKindOf(thing) {
return kindOf(thing) === type;
};
}
/** /**
* Determine if a value is an Array * Determine if a value is an Array
* *
@@ -40,22 +56,12 @@ function isBuffer(val) {
/** /**
* Determine if a value is an ArrayBuffer * Determine if a value is an ArrayBuffer
* *
* @function
* @param {Object} val The value to test * @param {Object} val The value to test
* @returns {boolean} True if value is an ArrayBuffer, otherwise false * @returns {boolean} True if value is an ArrayBuffer, otherwise false
*/ */
function isArrayBuffer(val) { var isArrayBuffer = kindOfTest('ArrayBuffer');
return toString.call(val) === '[object ArrayBuffer]';
}
/**
* Determine if a value is a FormData
*
* @param {Object} val The value to test
* @returns {boolean} True if value is an FormData, otherwise false
*/
function isFormData(val) {
return toString.call(val) === '[object FormData]';
}
/** /**
* Determine if a value is a view on an ArrayBuffer * Determine if a value is a view on an ArrayBuffer
@@ -110,7 +116,7 @@ function isObject(val) {
* @return {boolean} True if value is a plain Object, otherwise false * @return {boolean} True if value is a plain Object, otherwise false
*/ */
function isPlainObject(val) { function isPlainObject(val) {
if (toString.call(val) !== '[object Object]') { if (kindOf(val) !== 'object') {
return false; return false;
} }
@@ -121,32 +127,38 @@ function isPlainObject(val) {
/** /**
* Determine if a value is a Date * Determine if a value is a Date
* *
* @function
* @param {Object} val The value to test * @param {Object} val The value to test
* @returns {boolean} True if value is a Date, otherwise false * @returns {boolean} True if value is a Date, otherwise false
*/ */
function isDate(val) { var isDate = kindOfTest('Date');
return toString.call(val) === '[object Date]';
}
/** /**
* Determine if a value is a File * Determine if a value is a File
* *
* @function
* @param {Object} val The value to test * @param {Object} val The value to test
* @returns {boolean} True if value is a File, otherwise false * @returns {boolean} True if value is a File, otherwise false
*/ */
function isFile(val) { var isFile = kindOfTest('File');
return toString.call(val) === '[object File]';
}
/** /**
* Determine if a value is a Blob * Determine if a value is a Blob
* *
* @function
* @param {Object} val The value to test * @param {Object} val The value to test
* @returns {boolean} True if value is a Blob, otherwise false * @returns {boolean} True if value is a Blob, otherwise false
*/ */
function isBlob(val) { var isBlob = kindOfTest('Blob');
return toString.call(val) === '[object Blob]';
} /**
* Determine if a value is a FileList
*
* @function
* @param {Object} val The value to test
* @returns {boolean} True if value is a File, otherwise false
*/
var isFileList = kindOfTest('FileList');
/** /**
* Determine if a value is a Function * Determine if a value is a Function
@@ -169,14 +181,27 @@ function isStream(val) {
} }
/** /**
* Determine if a value is a URLSearchParams object * Determine if a value is a FormData
* *
* @param {Object} thing The value to test
* @returns {boolean} True if value is an FormData, otherwise false
*/
function isFormData(thing) {
var pattern = '[object FormData]';
return thing && (
(typeof FormData === 'function' && thing instanceof FormData) ||
toString.call(thing) === pattern ||
(isFunction(thing.toString) && thing.toString() === pattern)
);
}
/**
* Determine if a value is a URLSearchParams object
* @function
* @param {Object} val The value to test * @param {Object} val The value to test
* @returns {boolean} True if value is a URLSearchParams object, otherwise false * @returns {boolean} True if value is a URLSearchParams object, otherwise false
*/ */
function isURLSearchParams(val) { var isURLSearchParams = kindOfTest('URLSearchParams');
return toString.call(val) === '[object URLSearchParams]';
}
/** /**
* Trim excess whitespace off the beginning and end of a string * Trim excess whitespace off the beginning and end of a string
@@ -323,6 +348,48 @@ function stripBOM(content) {
return content; return content;
} }
/**
* determines whether a string ends with the characters of a specified string
* @param {String} str
* @param {String} searchString
* @param {Number} [position= 0]
* @returns {boolean}
*/
function endsWith(str, searchString, position) {
str = String(str);
if (position === undefined || position > str.length) {
position = str.length;
}
position -= searchString.length;
var lastIndex = str.indexOf(searchString, position);
return lastIndex !== -1 && lastIndex === position;
}
/**
* Returns new array from array like object
* @param {*} [thing]
* @returns {Array}
*/
function toArray(thing) {
if (!thing) return null;
var i = thing.length;
if (isUndefined(i)) return null;
var arr = new Array(i);
while (i-- > 0) {
arr[i] = thing[i];
}
return arr;
}
// eslint-disable-next-line func-names
var isTypedArray = (function(TypedArray) {
// eslint-disable-next-line func-names
return function(thing) {
return TypedArray && thing instanceof TypedArray;
};
})(typeof Uint8Array !== 'undefined' && Object.getPrototypeOf(Uint8Array));
module.exports = { module.exports = {
isArray: isArray, isArray: isArray,
isArrayBuffer: isArrayBuffer, isArrayBuffer: isArrayBuffer,
@@ -345,5 +412,11 @@ module.exports = {
merge: merge, merge: merge,
extend: extend, extend: extend,
trim: trim, trim: trim,
stripBOM: stripBOM stripBOM: stripBOM,
kindOf: kindOf,
kindOfTest: kindOfTest,
endsWith: endsWith,
toArray: toArray,
isTypedArray: isTypedArray,
isFileList: isFileList
}; };
+244 -114
View File
@@ -5,16 +5,20 @@
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "axios",
"version": "0.26.0", "version": "0.26.0",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"follow-redirects": "^1.14.8" "follow-redirects": "^1.14.8",
"form-data": "^4.0.0"
}, },
"devDependencies": { "devDependencies": {
"abortcontroller-polyfill": "^1.5.0", "abortcontroller-polyfill": "^1.5.0",
"coveralls": "^3.0.0", "coveralls": "^3.0.0",
"cross-env": "^7.0.3",
"dtslint": "^4.1.6", "dtslint": "^4.1.6",
"es6-promise": "^4.2.4", "es6-promise": "^4.2.4",
"formidable": "^2.0.1",
"grunt": "^1.3.0", "grunt": "^1.3.0",
"grunt-banner": "^0.6.0", "grunt-banner": "^0.6.0",
"grunt-cli": "^1.2.0", "grunt-cli": "^1.2.0",
@@ -1265,6 +1269,12 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/asap": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
"integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=",
"dev": true
},
"node_modules/asn1": { "node_modules/asn1": {
"version": "0.2.6", "version": "0.2.6",
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
@@ -1365,8 +1375,7 @@
"node_modules/asynckit": { "node_modules/asynckit": {
"version": "0.4.0", "version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
"dev": true
}, },
"node_modules/at-least-node": { "node_modules/at-least-node": {
"version": "1.0.0", "version": "1.0.0",
@@ -2679,7 +2688,6 @@
"version": "1.0.8", "version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"dev": true,
"dependencies": { "dependencies": {
"delayed-stream": "~1.0.0" "delayed-stream": "~1.0.0"
}, },
@@ -3096,6 +3104,24 @@
"sha.js": "^2.4.8" "sha.js": "^2.4.8"
} }
}, },
"node_modules/cross-env": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz",
"integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==",
"dev": true,
"dependencies": {
"cross-spawn": "^7.0.1"
},
"bin": {
"cross-env": "src/bin/cross-env.js",
"cross-env-shell": "src/bin/cross-env-shell.js"
},
"engines": {
"node": ">=10.14",
"npm": ">=6",
"yarn": ">=1"
}
},
"node_modules/cross-spawn": { "node_modules/cross-spawn": {
"version": "7.0.3", "version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
@@ -3169,9 +3195,9 @@
} }
}, },
"node_modules/date-format": { "node_modules/date-format": {
"version": "4.0.3", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.3.tgz", "resolved": "https://registry.npmjs.org/date-format/-/date-format-3.0.0.tgz",
"integrity": "sha512-7P3FyqDcfeznLZp2b+OMitV9Sz2lUnsT87WaTat9nVwqsBkTzPG3lPLNwW3en6F4pHUiWzr6vb8CLhjdK9bcxQ==", "integrity": "sha512-eyTcpKOcamdhWJXj56DpQMo1ylSQpcGtGKXcU0Tb97+K56/CF5amAqqqNj0+KvA0iw2ynxtHWFsPDSClCxe48w==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": ">=4.0" "node": ">=4.0"
@@ -3685,7 +3711,6 @@
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
"dev": true,
"engines": { "engines": {
"node": ">=0.4.0" "node": ">=0.4.0"
} }
@@ -3784,6 +3809,16 @@
"uuid": "dist/bin/uuid" "uuid": "dist/bin/uuid"
} }
}, },
"node_modules/dezalgo": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz",
"integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=",
"dev": true,
"dependencies": {
"asap": "^2.0.0",
"wrappy": "1"
}
},
"node_modules/di": { "node_modules/di": {
"version": "0.0.1", "version": "0.0.1",
"resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz",
@@ -5652,17 +5687,43 @@
} }
}, },
"node_modules/form-data": { "node_modules/form-data": {
"version": "2.3.3", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"dev": true,
"dependencies": { "dependencies": {
"asynckit": "^0.4.0", "asynckit": "^0.4.0",
"combined-stream": "^1.0.6", "combined-stream": "^1.0.8",
"mime-types": "^2.1.12" "mime-types": "^2.1.12"
}, },
"engines": { "engines": {
"node": ">= 0.12" "node": ">= 6"
}
},
"node_modules/formidable": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/formidable/-/formidable-2.0.1.tgz",
"integrity": "sha512-rjTMNbp2BpfQShhFbR3Ruk3qk2y9jKpvMW78nJgx8QKtxjDVrwbZG+wvDOmVbifHyOUOQJXxqEy6r0faRrPzTQ==",
"dev": true,
"dependencies": {
"dezalgo": "1.0.3",
"hexoid": "1.0.0",
"once": "1.4.0",
"qs": "6.9.3"
},
"funding": {
"url": "https://ko-fi.com/tunnckoCore/commissions"
}
},
"node_modules/formidable/node_modules/qs": {
"version": "6.9.3",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.9.3.tgz",
"integrity": "sha512-EbZYNarm6138UKKq46tdx08Yo/q9ZhFoAXAI1meAFd2GtbRDhbZY2WQSICskT0c5q99aFzLG1D4nvTk9tqfXIw==",
"dev": true,
"engines": {
"node": ">=0.6"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/forwarded": { "node_modules/forwarded": {
@@ -6835,6 +6896,15 @@
"tslib": "^2.0.3" "tslib": "^2.0.3"
} }
}, },
"node_modules/hexoid": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz",
"integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/hmac-drbg": { "node_modules/hmac-drbg": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
@@ -7949,9 +8019,9 @@
"dev": true "dev": true
}, },
"node_modules/karma": { "node_modules/karma": {
"version": "6.3.14", "version": "6.3.11",
"resolved": "https://registry.npmjs.org/karma/-/karma-6.3.14.tgz", "resolved": "https://registry.npmjs.org/karma/-/karma-6.3.11.tgz",
"integrity": "sha512-SDFoU5F4LdosEiUVWUDRPCV/C1zQRNtIakx7rWkigf7R4sxGADlSEeOma4S1f/js7YAzvqLW92ByoiQptg+8oQ==", "integrity": "sha512-QGUh4yXgizzDNPLB5nWTvP+wysKexngbyLVWFOyikB661hpa2RZLf5anZQzqliWtAQuYVep0ot0D1U7UQKpsxQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"body-parser": "^1.19.0", "body-parser": "^1.19.0",
@@ -7966,7 +8036,7 @@
"http-proxy": "^1.18.1", "http-proxy": "^1.18.1",
"isbinaryfile": "^4.0.8", "isbinaryfile": "^4.0.8",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"log4js": "^6.4.1", "log4js": "^6.3.0",
"mime": "^2.5.2", "mime": "^2.5.2",
"minimatch": "^3.0.4", "minimatch": "^3.0.4",
"qjobs": "^1.2.0", "qjobs": "^1.2.0",
@@ -8699,21 +8769,27 @@
} }
}, },
"node_modules/log4js": { "node_modules/log4js": {
"version": "6.4.1", "version": "6.3.0",
"resolved": "https://registry.npmjs.org/log4js/-/log4js-6.4.1.tgz", "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.3.0.tgz",
"integrity": "sha512-iUiYnXqAmNKiIZ1XSAitQ4TmNs8CdZYTAWINARF3LjnsLN8tY5m0vRwd6uuWj/yNY0YHxeZodnbmxKFUOM2rMg==", "integrity": "sha512-Mc8jNuSFImQUIateBFwdOQcmC6Q5maU0VVvdC2R6XMb66/VnT+7WS4D/0EeNMZu1YODmJe5NIn2XftCzEocUgw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"date-format": "^4.0.3", "date-format": "^3.0.0",
"debug": "^4.3.3", "debug": "^4.1.1",
"flatted": "^3.2.4", "flatted": "^2.0.1",
"rfdc": "^1.3.0", "rfdc": "^1.1.4",
"streamroller": "^3.0.2" "streamroller": "^2.2.4"
}, },
"engines": { "engines": {
"node": ">=8.0" "node": ">=8.0"
} }
}, },
"node_modules/log4js/node_modules/flatted": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz",
"integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==",
"dev": true
},
"node_modules/loglevel": { "node_modules/loglevel": {
"version": "1.8.0", "version": "1.8.0",
"resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.8.0.tgz", "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.8.0.tgz",
@@ -9117,7 +9193,6 @@
"version": "1.51.0", "version": "1.51.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz",
"integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==",
"dev": true,
"engines": { "engines": {
"node": ">= 0.6" "node": ">= 0.6"
} }
@@ -9126,7 +9201,6 @@
"version": "2.1.34", "version": "2.1.34",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz",
"integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==",
"dev": true,
"dependencies": { "dependencies": {
"mime-db": "1.51.0" "mime-db": "1.51.0"
}, },
@@ -11435,6 +11509,20 @@
"node": ">= 6" "node": ">= 6"
} }
}, },
"node_modules/request/node_modules/form-data": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
"integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
"dev": true,
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.6",
"mime-types": "^2.1.12"
},
"engines": {
"node": ">= 0.12"
}
},
"node_modules/request/node_modules/qs": { "node_modules/request/node_modules/qs": {
"version": "6.5.3", "version": "6.5.3",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz",
@@ -13089,52 +13177,40 @@
"dev": true "dev": true
}, },
"node_modules/streamroller": { "node_modules/streamroller": {
"version": "3.0.2", "version": "2.2.4",
"resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.0.2.tgz", "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-2.2.4.tgz",
"integrity": "sha512-ur6y5S5dopOaRXBuRIZ1u6GC5bcEXHRZKgfBjfCglMhmIf+roVCECjvkEYzNQOXIN2/JPnkMPW/8B3CZoKaEPA==", "integrity": "sha512-OG79qm3AujAM9ImoqgWEY1xG4HX+Lw+yY6qZj9R1K2mhF5bEmQ849wvrb+4vt4jLMLzwXttJlQbOdPOQVRv7DQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"date-format": "^4.0.3", "date-format": "^2.1.0",
"debug": "^4.1.1", "debug": "^4.1.1",
"fs-extra": "^10.0.0" "fs-extra": "^8.1.0"
}, },
"engines": { "engines": {
"node": ">=8.0" "node": ">=8.0"
} }
}, },
"node_modules/streamroller/node_modules/date-format": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/date-format/-/date-format-2.1.0.tgz",
"integrity": "sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA==",
"dev": true,
"engines": {
"node": ">=4.0"
}
},
"node_modules/streamroller/node_modules/fs-extra": { "node_modules/streamroller/node_modules/fs-extra": {
"version": "10.0.0", "version": "8.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
"integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"graceful-fs": "^4.2.0", "graceful-fs": "^4.2.0",
"jsonfile": "^6.0.1", "jsonfile": "^4.0.0",
"universalify": "^2.0.0" "universalify": "^0.1.0"
}, },
"engines": { "engines": {
"node": ">=12" "node": ">=6 <7 || >=8"
}
},
"node_modules/streamroller/node_modules/jsonfile": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
"dev": true,
"dependencies": {
"universalify": "^2.0.0"
},
"optionalDependencies": {
"graceful-fs": "^4.1.6"
}
},
"node_modules/streamroller/node_modules/universalify": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
"integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
"dev": true,
"engines": {
"node": ">= 10.0.0"
} }
}, },
"node_modules/strict-uri-encode": { "node_modules/strict-uri-encode": {
@@ -17200,6 +17276,12 @@
"integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=",
"dev": true "dev": true
}, },
"asap": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
"integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=",
"dev": true
},
"asn1": { "asn1": {
"version": "0.2.6", "version": "0.2.6",
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
@@ -17295,8 +17377,7 @@
"asynckit": { "asynckit": {
"version": "0.4.0", "version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
"dev": true
}, },
"at-least-node": { "at-least-node": {
"version": "1.0.0", "version": "1.0.0",
@@ -18407,7 +18488,6 @@
"version": "1.0.8", "version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"dev": true,
"requires": { "requires": {
"delayed-stream": "~1.0.0" "delayed-stream": "~1.0.0"
} }
@@ -18775,6 +18855,15 @@
"sha.js": "^2.4.8" "sha.js": "^2.4.8"
} }
}, },
"cross-env": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz",
"integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==",
"dev": true,
"requires": {
"cross-spawn": "^7.0.1"
}
},
"cross-spawn": { "cross-spawn": {
"version": "7.0.3", "version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
@@ -18839,9 +18928,9 @@
} }
}, },
"date-format": { "date-format": {
"version": "4.0.3", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.3.tgz", "resolved": "https://registry.npmjs.org/date-format/-/date-format-3.0.0.tgz",
"integrity": "sha512-7P3FyqDcfeznLZp2b+OMitV9Sz2lUnsT87WaTat9nVwqsBkTzPG3lPLNwW3en6F4pHUiWzr6vb8CLhjdK9bcxQ==", "integrity": "sha512-eyTcpKOcamdhWJXj56DpQMo1ylSQpcGtGKXcU0Tb97+K56/CF5amAqqqNj0+KvA0iw2ynxtHWFsPDSClCxe48w==",
"dev": true "dev": true
}, },
"dateformat": { "dateformat": {
@@ -19248,8 +19337,7 @@
"delayed-stream": { "delayed-stream": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
"dev": true
}, },
"delegates": { "delegates": {
"version": "1.0.0", "version": "1.0.0",
@@ -19332,6 +19420,16 @@
"integrity": "sha512-AD1hi7iVJ8OD0aMLQU5VK0XH9LDlA1+BcPIgrAxPfaibx2DbWucuyOhc4oyQCbnvDDO68nN6/LcKfqTP343Jjg==", "integrity": "sha512-AD1hi7iVJ8OD0aMLQU5VK0XH9LDlA1+BcPIgrAxPfaibx2DbWucuyOhc4oyQCbnvDDO68nN6/LcKfqTP343Jjg==",
"dev": true "dev": true
}, },
"dezalgo": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz",
"integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=",
"dev": true,
"requires": {
"asap": "^2.0.0",
"wrappy": "1"
}
},
"di": { "di": {
"version": "0.0.1", "version": "0.0.1",
"resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz",
@@ -20873,16 +20971,35 @@
"dev": true "dev": true
}, },
"form-data": { "form-data": {
"version": "2.3.3", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"dev": true,
"requires": { "requires": {
"asynckit": "^0.4.0", "asynckit": "^0.4.0",
"combined-stream": "^1.0.6", "combined-stream": "^1.0.8",
"mime-types": "^2.1.12" "mime-types": "^2.1.12"
} }
}, },
"formidable": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/formidable/-/formidable-2.0.1.tgz",
"integrity": "sha512-rjTMNbp2BpfQShhFbR3Ruk3qk2y9jKpvMW78nJgx8QKtxjDVrwbZG+wvDOmVbifHyOUOQJXxqEy6r0faRrPzTQ==",
"dev": true,
"requires": {
"dezalgo": "1.0.3",
"hexoid": "1.0.0",
"once": "1.4.0",
"qs": "6.9.3"
},
"dependencies": {
"qs": {
"version": "6.9.3",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.9.3.tgz",
"integrity": "sha512-EbZYNarm6138UKKq46tdx08Yo/q9ZhFoAXAI1meAFd2GtbRDhbZY2WQSICskT0c5q99aFzLG1D4nvTk9tqfXIw==",
"dev": true
}
}
},
"forwarded": { "forwarded": {
"version": "0.2.0", "version": "0.2.0",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
@@ -21802,6 +21919,12 @@
"tslib": "^2.0.3" "tslib": "^2.0.3"
} }
}, },
"hexoid": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz",
"integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==",
"dev": true
},
"hmac-drbg": { "hmac-drbg": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
@@ -22675,9 +22798,9 @@
"dev": true "dev": true
}, },
"karma": { "karma": {
"version": "6.3.14", "version": "6.3.11",
"resolved": "https://registry.npmjs.org/karma/-/karma-6.3.14.tgz", "resolved": "https://registry.npmjs.org/karma/-/karma-6.3.11.tgz",
"integrity": "sha512-SDFoU5F4LdosEiUVWUDRPCV/C1zQRNtIakx7rWkigf7R4sxGADlSEeOma4S1f/js7YAzvqLW92ByoiQptg+8oQ==", "integrity": "sha512-QGUh4yXgizzDNPLB5nWTvP+wysKexngbyLVWFOyikB661hpa2RZLf5anZQzqliWtAQuYVep0ot0D1U7UQKpsxQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"body-parser": "^1.19.0", "body-parser": "^1.19.0",
@@ -22692,7 +22815,7 @@
"http-proxy": "^1.18.1", "http-proxy": "^1.18.1",
"isbinaryfile": "^4.0.8", "isbinaryfile": "^4.0.8",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"log4js": "^6.4.1", "log4js": "^6.3.0",
"mime": "^2.5.2", "mime": "^2.5.2",
"minimatch": "^3.0.4", "minimatch": "^3.0.4",
"qjobs": "^1.2.0", "qjobs": "^1.2.0",
@@ -23287,16 +23410,24 @@
} }
}, },
"log4js": { "log4js": {
"version": "6.4.1", "version": "6.3.0",
"resolved": "https://registry.npmjs.org/log4js/-/log4js-6.4.1.tgz", "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.3.0.tgz",
"integrity": "sha512-iUiYnXqAmNKiIZ1XSAitQ4TmNs8CdZYTAWINARF3LjnsLN8tY5m0vRwd6uuWj/yNY0YHxeZodnbmxKFUOM2rMg==", "integrity": "sha512-Mc8jNuSFImQUIateBFwdOQcmC6Q5maU0VVvdC2R6XMb66/VnT+7WS4D/0EeNMZu1YODmJe5NIn2XftCzEocUgw==",
"dev": true, "dev": true,
"requires": { "requires": {
"date-format": "^4.0.3", "date-format": "^3.0.0",
"debug": "^4.3.3", "debug": "^4.1.1",
"flatted": "^3.2.4", "flatted": "^2.0.1",
"rfdc": "^1.3.0", "rfdc": "^1.1.4",
"streamroller": "^3.0.2" "streamroller": "^2.2.4"
},
"dependencies": {
"flatted": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz",
"integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==",
"dev": true
}
} }
}, },
"loglevel": { "loglevel": {
@@ -23635,14 +23766,12 @@
"mime-db": { "mime-db": {
"version": "1.51.0", "version": "1.51.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz",
"integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g=="
"dev": true
}, },
"mime-types": { "mime-types": {
"version": "2.1.34", "version": "2.1.34",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz",
"integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==",
"dev": true,
"requires": { "requires": {
"mime-db": "1.51.0" "mime-db": "1.51.0"
} }
@@ -25492,6 +25621,17 @@
"uuid": "^3.3.2" "uuid": "^3.3.2"
}, },
"dependencies": { "dependencies": {
"form-data": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
"integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
"dev": true,
"requires": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.6",
"mime-types": "^2.1.12"
}
},
"qs": { "qs": {
"version": "6.5.3", "version": "6.5.3",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz",
@@ -26881,42 +27021,32 @@
"dev": true "dev": true
}, },
"streamroller": { "streamroller": {
"version": "3.0.2", "version": "2.2.4",
"resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.0.2.tgz", "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-2.2.4.tgz",
"integrity": "sha512-ur6y5S5dopOaRXBuRIZ1u6GC5bcEXHRZKgfBjfCglMhmIf+roVCECjvkEYzNQOXIN2/JPnkMPW/8B3CZoKaEPA==", "integrity": "sha512-OG79qm3AujAM9ImoqgWEY1xG4HX+Lw+yY6qZj9R1K2mhF5bEmQ849wvrb+4vt4jLMLzwXttJlQbOdPOQVRv7DQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"date-format": "^4.0.3", "date-format": "^2.1.0",
"debug": "^4.1.1", "debug": "^4.1.1",
"fs-extra": "^10.0.0" "fs-extra": "^8.1.0"
}, },
"dependencies": { "dependencies": {
"date-format": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/date-format/-/date-format-2.1.0.tgz",
"integrity": "sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA==",
"dev": true
},
"fs-extra": { "fs-extra": {
"version": "10.0.0", "version": "8.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
"integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
"dev": true, "dev": true,
"requires": { "requires": {
"graceful-fs": "^4.2.0", "graceful-fs": "^4.2.0",
"jsonfile": "^6.0.1", "jsonfile": "^4.0.0",
"universalify": "^2.0.0" "universalify": "^0.1.0"
} }
},
"jsonfile": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
"dev": true,
"requires": {
"graceful-fs": "^4.1.6",
"universalify": "^2.0.0"
}
},
"universalify": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
"integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
"dev": true
} }
} }
}, },
+7 -3
View File
@@ -7,7 +7,7 @@
"scripts": { "scripts": {
"test": "grunt test && dtslint", "test": "grunt test && dtslint",
"start": "node ./sandbox/server.js", "start": "node ./sandbox/server.js",
"build": "NODE_ENV=production grunt build", "build": "cross-env NODE_ENV=production grunt build",
"preversion": "grunt version && npm test", "preversion": "grunt version && npm test",
"version": "npm run build && git add -A dist && git add CHANGELOG.md bower.json package.json", "version": "npm run build && git add -A dist && git add CHANGELOG.md bower.json package.json",
"postversion": "git push && git push --tags", "postversion": "git push && git push --tags",
@@ -35,8 +35,10 @@
"devDependencies": { "devDependencies": {
"abortcontroller-polyfill": "^1.5.0", "abortcontroller-polyfill": "^1.5.0",
"coveralls": "^3.0.0", "coveralls": "^3.0.0",
"cross-env": "^7.0.3",
"dtslint": "^4.1.6", "dtslint": "^4.1.6",
"es6-promise": "^4.2.4", "es6-promise": "^4.2.4",
"formidable": "^2.0.1",
"grunt": "^1.3.0", "grunt": "^1.3.0",
"grunt-banner": "^0.6.0", "grunt-banner": "^0.6.0",
"grunt-cli": "^1.2.0", "grunt-cli": "^1.2.0",
@@ -69,13 +71,15 @@
"webpack-dev-server": "^3.11.0" "webpack-dev-server": "^3.11.0"
}, },
"browser": { "browser": {
"./lib/adapters/http.js": "./lib/adapters/xhr.js" "./lib/adapters/http.js": "./lib/adapters/xhr.js",
"./lib/defaults/env/FormData.js": "./lib/helpers/null.js"
}, },
"jsdelivr": "dist/axios.min.js", "jsdelivr": "dist/axios.min.js",
"unpkg": "dist/axios.min.js", "unpkg": "dist/axios.min.js",
"typings": "./index.d.ts", "typings": "./index.d.ts",
"dependencies": { "dependencies": {
"follow-redirects": "^1.14.8" "follow-redirects": "^1.14.8",
"form-data": "^4.0.0"
}, },
"bundlesize": [ "bundlesize": [
{ {
+12
View File
@@ -33,6 +33,18 @@ describe('defaults', function () {
expect(defaults.transformRequest[0](null, headers)).toEqual('null'); expect(defaults.transformRequest[0](null, headers)).toEqual('null');
}); });
it("should transform the plain data object to a FormData instance 'Content-Type' if header is 'multipart/form-data'", function() {
var headers = {
'Content-Type': 'multipart/form-data'
};
var payload = {x: 1};
var transformed = defaults.transformRequest[0](payload, headers);
expect(transformed).toEqual(jasmine.any(FormData));
});
it('should do nothing to request string', function () { it('should do nothing to request string', function () {
expect(defaults.transformRequest[0]('foo=bar')).toEqual('foo=bar'); expect(defaults.transformRequest[0]('foo=bar')).toEqual('foo=bar');
}); });
+35 -10
View File
@@ -1,18 +1,43 @@
var toFormData = require("../../../lib/helpers/toFormData"); var toFormData = require('../../../lib/helpers/toFormData');
describe("toFormData", function () { describe('toFormData', function () {
it("Convert nested data object to FormDAta", function () { it('should convert nested data object to FormData', function () {
var o = { var o = {
val: 123, val: 123,
nested: { nested: {
arr: ["hello", "world"], arr: ['hello', 'world']
}, }
}; };
convertedVal = toFormData(o); var form = toFormData(o);
expect(convertedVal instanceof FormData).toEqual(true); expect(form instanceof FormData).toEqual(true);
expect(Array.from(convertedVal.keys()).length).toEqual(3); expect(Array.from(form.keys()).length).toEqual(3);
expect(convertedVal.get("val")).toEqual("123") expect(form.get('val')).toEqual('123');
expect(convertedVal.get("nested.arr.0")).toEqual("hello") expect(form.get('nested.arr.0')).toEqual('hello');
});
it('should append value whose key ends with [] as separate values with the same key', function () {
var data = {
'arr[]': [1, 2, 3]
};
var form = toFormData(data);
expect(Array.from(form.keys()).length).toEqual(3);
expect(form.getAll('arr[]')).toEqual(['1', '2', '3']);
});
it('should append value whose key ends with {} as a JSON string', function () {
var data = {
'obj{}': {x: 1, y: 2}
};
var str = JSON.stringify(data['obj{}']);
var form = toFormData(data);
expect(Array.from(form.keys()).length).toEqual(1);
expect(form.getAll('obj{}')).toEqual([str]);
}); });
}); });
+3 -1
View File
@@ -21,7 +21,9 @@ describe('instance', function () {
'spread', 'spread',
'isAxiosError', 'isAxiosError',
'VERSION', 'VERSION',
'default'].indexOf(prop) > -1) { 'default',
'toFormData'
].indexOf(prop) > -1) {
continue; continue;
} }
expect(typeof instance[prop]).toBe(typeof axios[prop]); expect(typeof instance[prop]).toBe(typeof axios[prop]);
+10
View File
@@ -0,0 +1,10 @@
var kindOf = require('../../../lib/utils').kindOf;
describe('utils::kindOf', function () {
it('should return object tag', function () {
expect(kindOf({})).toEqual('object');
// cached result
expect(kindOf({})).toEqual('object');
expect(kindOf([])).toEqual('array');
});
});
+5
View File
@@ -77,4 +77,9 @@ describe('utils::isX', function () {
expect(utils.isURLSearchParams(new URLSearchParams())).toEqual(true); expect(utils.isURLSearchParams(new URLSearchParams())).toEqual(true);
expect(utils.isURLSearchParams('foo=1&bar=2')).toEqual(false); expect(utils.isURLSearchParams('foo=1&bar=2')).toEqual(false);
}); });
it('should validate TypedArray instance', function () {
expect(utils.isTypedArray(new Uint8Array([1, 2, 3]))).toEqual(true);
expect(utils.isTypedArray([1, 2, 3])).toEqual(false);
});
}); });
+10
View File
@@ -0,0 +1,10 @@
var kindOfTest = require('../../../lib/utils').kindOfTest;
describe('utils::endsWith', function () {
it('should return true if the string ends with passed substring', function () {
var test = kindOfTest('number');
expect(test(123)).toEqual(true);
expect(test('123')).toEqual(false);
});
});
+10
View File
@@ -0,0 +1,10 @@
var kindOf = require('../../../lib/utils').kindOf;
describe('utils::kindOf', function () {
it('should return object tag', function () {
expect(kindOf({})).toEqual('object');
// cached result
expect(kindOf({})).toEqual('object');
expect(kindOf([])).toEqual('array');
});
});
+10
View File
@@ -0,0 +1,10 @@
var toArray = require('../../../lib/utils').toArray;
describe('utils::kindOf', function () {
it('should return object tag', function () {
expect(toArray()).toEqual(null);
expect(toArray([])).toEqual([]);
expect(toArray([1])).toEqual([1]);
expect(toArray([1, 2, 3])).toEqual([1, 2, 3]);
});
});
+43
View File
@@ -9,6 +9,8 @@ var fs = require('fs');
var path = require('path'); var path = require('path');
var pkg = require('./../../../package.json'); var pkg = require('./../../../package.json');
var server, proxy; var server, proxy;
var FormData = require('form-data');
var formidable = require('formidable');
describe('supports http with nodejs', function () { describe('supports http with nodejs', function () {
@@ -1078,5 +1080,46 @@ describe('supports http with nodejs', function () {
}); });
}); });
it('should allow passing FormData', function (done) {
var form = new FormData();
var file1= Buffer.from('foo', 'utf8');
form.append('foo', "bar");
form.append('file1', file1, {
filename: 'bar.jpg',
filepath: 'temp/bar.jpg',
contentType: 'image/jpeg'
});
server = http.createServer(function (req, res) {
var receivedForm = new formidable.IncomingForm();
receivedForm.parse(req, function (err, fields, files) {
if (err) {
return done(err);
}
res.end(JSON.stringify({
fields: fields,
files: files
}));
});
}).listen(4444, function () {
axios.post('http://localhost:4444/', form, {
headers: {
'Content-Type': 'multipart/form-data'
}
}).then(function (res) {
assert.deepStrictEqual(res.data.fields,{foo: 'bar'});
assert.strictEqual(res.data.files.file1.mimetype,'image/jpeg');
assert.strictEqual(res.data.files.file1.originalFilename,'temp/bar.jpg');
assert.strictEqual(res.data.files.file1.size,3);
done();
}).catch(done);
});
});
}); });
+12
View File
@@ -0,0 +1,12 @@
var assert = require('assert');
var isFormData = require('../../../lib/utils').isFormData;
var FormData = require('form-data');
describe('utils::isFormData', function () {
it('should detect the FormData instance provided by the `form-data` package', function () {
[1, 'str', {}, new RegExp()].forEach(function (thing) {
assert.equal(isFormData(thing), false);
});
assert.equal(isFormData(new FormData()), true);
});
});