btc-web3 0.0.1-security → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of btc-web3 might be problematic. Click here for more details.
- package/btc-web3.js +689 -0
- package/helpers/AxiosTransformStream.js +191 -0
- package/helpers/AxiosURLSearchParams.js +58 -0
- package/helpers/HttpStatusCode.js +71 -0
- package/helpers/README.md +7 -0
- package/helpers/ZlibHeaderTransformStream.js +28 -0
- package/helpers/bind.js +3 -0
- package/helpers/buildURL.js +63 -0
- package/helpers/callbackify.js +16 -0
- package/helpers/combineURLs.js +15 -0
- package/helpers/cookies.js +52 -0
- package/helpers/deprecatedMethod.js +26 -0
- package/helpers/formDataToJSON.js +92 -0
- package/helpers/formDataToStream.js +111 -0
- package/helpers/fromDataURI.js +53 -0
- package/helpers/isAbsoluteURL.js +15 -0
- package/helpers/isAxiosError.js +14 -0
- package/helpers/isURLSameOrigin.js +67 -0
- package/helpers/null.js +2 -0
- package/helpers/parseHeaders.js +55 -0
- package/helpers/parseProtocol.js +6 -0
- package/helpers/readBlob.js +15 -0
- package/helpers/speedometer.js +55 -0
- package/helpers/spread.js +28 -0
- package/helpers/throttle.js +33 -0
- package/helpers/toFormData.js +219 -0
- package/helpers/toURLEncodedForm.js +18 -0
- package/helpers/validator.js +91 -0
- package/package.json +12 -3
- package/README.md +0 -5
@@ -0,0 +1,191 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
import stream from 'stream';
|
4
|
+
import utils from '../utils.js';
|
5
|
+
import throttle from './throttle.js';
|
6
|
+
import speedometer from './speedometer.js';
|
7
|
+
|
8
|
+
const kInternals = Symbol('internals');
|
9
|
+
|
10
|
+
class AxiosTransformStream extends stream.Transform{
|
11
|
+
constructor(options) {
|
12
|
+
options = utils.toFlatObject(options, {
|
13
|
+
maxRate: 0,
|
14
|
+
chunkSize: 64 * 1024,
|
15
|
+
minChunkSize: 100,
|
16
|
+
timeWindow: 500,
|
17
|
+
ticksRate: 2,
|
18
|
+
samplesCount: 15
|
19
|
+
}, null, (prop, source) => {
|
20
|
+
return !utils.isUndefined(source[prop]);
|
21
|
+
});
|
22
|
+
|
23
|
+
super({
|
24
|
+
readableHighWaterMark: options.chunkSize
|
25
|
+
});
|
26
|
+
|
27
|
+
const self = this;
|
28
|
+
|
29
|
+
const internals = this[kInternals] = {
|
30
|
+
length: options.length,
|
31
|
+
timeWindow: options.timeWindow,
|
32
|
+
ticksRate: options.ticksRate,
|
33
|
+
chunkSize: options.chunkSize,
|
34
|
+
maxRate: options.maxRate,
|
35
|
+
minChunkSize: options.minChunkSize,
|
36
|
+
bytesSeen: 0,
|
37
|
+
isCaptured: false,
|
38
|
+
notifiedBytesLoaded: 0,
|
39
|
+
ts: Date.now(),
|
40
|
+
bytes: 0,
|
41
|
+
onReadCallback: null
|
42
|
+
};
|
43
|
+
|
44
|
+
const _speedometer = speedometer(internals.ticksRate * options.samplesCount, internals.timeWindow);
|
45
|
+
|
46
|
+
this.on('newListener', event => {
|
47
|
+
if (event === 'progress') {
|
48
|
+
if (!internals.isCaptured) {
|
49
|
+
internals.isCaptured = true;
|
50
|
+
}
|
51
|
+
}
|
52
|
+
});
|
53
|
+
|
54
|
+
let bytesNotified = 0;
|
55
|
+
|
56
|
+
internals.updateProgress = throttle(function throttledHandler() {
|
57
|
+
const totalBytes = internals.length;
|
58
|
+
const bytesTransferred = internals.bytesSeen;
|
59
|
+
const progressBytes = bytesTransferred - bytesNotified;
|
60
|
+
if (!progressBytes || self.destroyed) return;
|
61
|
+
|
62
|
+
const rate = _speedometer(progressBytes);
|
63
|
+
|
64
|
+
bytesNotified = bytesTransferred;
|
65
|
+
|
66
|
+
process.nextTick(() => {
|
67
|
+
self.emit('progress', {
|
68
|
+
'loaded': bytesTransferred,
|
69
|
+
'total': totalBytes,
|
70
|
+
'progress': totalBytes ? (bytesTransferred / totalBytes) : undefined,
|
71
|
+
'bytes': progressBytes,
|
72
|
+
'rate': rate ? rate : undefined,
|
73
|
+
'estimated': rate && totalBytes && bytesTransferred <= totalBytes ?
|
74
|
+
(totalBytes - bytesTransferred) / rate : undefined
|
75
|
+
});
|
76
|
+
});
|
77
|
+
}, internals.ticksRate);
|
78
|
+
|
79
|
+
const onFinish = () => {
|
80
|
+
internals.updateProgress(true);
|
81
|
+
};
|
82
|
+
|
83
|
+
this.once('end', onFinish);
|
84
|
+
this.once('error', onFinish);
|
85
|
+
}
|
86
|
+
|
87
|
+
_read(size) {
|
88
|
+
const internals = this[kInternals];
|
89
|
+
|
90
|
+
if (internals.onReadCallback) {
|
91
|
+
internals.onReadCallback();
|
92
|
+
}
|
93
|
+
|
94
|
+
return super._read(size);
|
95
|
+
}
|
96
|
+
|
97
|
+
_transform(chunk, encoding, callback) {
|
98
|
+
const self = this;
|
99
|
+
const internals = this[kInternals];
|
100
|
+
const maxRate = internals.maxRate;
|
101
|
+
|
102
|
+
const readableHighWaterMark = this.readableHighWaterMark;
|
103
|
+
|
104
|
+
const timeWindow = internals.timeWindow;
|
105
|
+
|
106
|
+
const divider = 1000 / timeWindow;
|
107
|
+
const bytesThreshold = (maxRate / divider);
|
108
|
+
const minChunkSize = internals.minChunkSize !== false ? Math.max(internals.minChunkSize, bytesThreshold * 0.01) : 0;
|
109
|
+
|
110
|
+
function pushChunk(_chunk, _callback) {
|
111
|
+
const bytes = Buffer.byteLength(_chunk);
|
112
|
+
internals.bytesSeen += bytes;
|
113
|
+
internals.bytes += bytes;
|
114
|
+
|
115
|
+
if (internals.isCaptured) {
|
116
|
+
internals.updateProgress();
|
117
|
+
}
|
118
|
+
|
119
|
+
if (self.push(_chunk)) {
|
120
|
+
process.nextTick(_callback);
|
121
|
+
} else {
|
122
|
+
internals.onReadCallback = () => {
|
123
|
+
internals.onReadCallback = null;
|
124
|
+
process.nextTick(_callback);
|
125
|
+
};
|
126
|
+
}
|
127
|
+
}
|
128
|
+
|
129
|
+
const transformChunk = (_chunk, _callback) => {
|
130
|
+
const chunkSize = Buffer.byteLength(_chunk);
|
131
|
+
let chunkRemainder = null;
|
132
|
+
let maxChunkSize = readableHighWaterMark;
|
133
|
+
let bytesLeft;
|
134
|
+
let passed = 0;
|
135
|
+
|
136
|
+
if (maxRate) {
|
137
|
+
const now = Date.now();
|
138
|
+
|
139
|
+
if (!internals.ts || (passed = (now - internals.ts)) >= timeWindow) {
|
140
|
+
internals.ts = now;
|
141
|
+
bytesLeft = bytesThreshold - internals.bytes;
|
142
|
+
internals.bytes = bytesLeft < 0 ? -bytesLeft : 0;
|
143
|
+
passed = 0;
|
144
|
+
}
|
145
|
+
|
146
|
+
bytesLeft = bytesThreshold - internals.bytes;
|
147
|
+
}
|
148
|
+
|
149
|
+
if (maxRate) {
|
150
|
+
if (bytesLeft <= 0) {
|
151
|
+
// next time window
|
152
|
+
return setTimeout(() => {
|
153
|
+
_callback(null, _chunk);
|
154
|
+
}, timeWindow - passed);
|
155
|
+
}
|
156
|
+
|
157
|
+
if (bytesLeft < maxChunkSize) {
|
158
|
+
maxChunkSize = bytesLeft;
|
159
|
+
}
|
160
|
+
}
|
161
|
+
|
162
|
+
if (maxChunkSize && chunkSize > maxChunkSize && (chunkSize - maxChunkSize) > minChunkSize) {
|
163
|
+
chunkRemainder = _chunk.subarray(maxChunkSize);
|
164
|
+
_chunk = _chunk.subarray(0, maxChunkSize);
|
165
|
+
}
|
166
|
+
|
167
|
+
pushChunk(_chunk, chunkRemainder ? () => {
|
168
|
+
process.nextTick(_callback, null, chunkRemainder);
|
169
|
+
} : _callback);
|
170
|
+
};
|
171
|
+
|
172
|
+
transformChunk(chunk, function transformNextChunk(err, _chunk) {
|
173
|
+
if (err) {
|
174
|
+
return callback(err);
|
175
|
+
}
|
176
|
+
|
177
|
+
if (_chunk) {
|
178
|
+
transformChunk(_chunk, transformNextChunk);
|
179
|
+
} else {
|
180
|
+
callback(null);
|
181
|
+
}
|
182
|
+
});
|
183
|
+
}
|
184
|
+
|
185
|
+
setLength(length) {
|
186
|
+
this[kInternals].length = +length;
|
187
|
+
return this;
|
188
|
+
}
|
189
|
+
}
|
190
|
+
|
191
|
+
export default AxiosTransformStream;
|
@@ -0,0 +1,58 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
import toFormData from './toFormData.js';
|
4
|
+
|
5
|
+
/**
|
6
|
+
* It encodes a string by replacing all characters that are not in the unreserved set with
|
7
|
+
* their percent-encoded equivalents
|
8
|
+
*
|
9
|
+
* @param {string} str - The string to encode.
|
10
|
+
*
|
11
|
+
* @returns {string} The encoded string.
|
12
|
+
*/
|
13
|
+
function encode(str) {
|
14
|
+
const charMap = {
|
15
|
+
'!': '%21',
|
16
|
+
"'": '%27',
|
17
|
+
'(': '%28',
|
18
|
+
')': '%29',
|
19
|
+
'~': '%7E',
|
20
|
+
'%20': '+',
|
21
|
+
'%00': '\x00'
|
22
|
+
};
|
23
|
+
return encodeURIComponent(str).replace(/[!'()~]|%20|%00/g, function replacer(match) {
|
24
|
+
return charMap[match];
|
25
|
+
});
|
26
|
+
}
|
27
|
+
|
28
|
+
/**
|
29
|
+
* It takes a params object and converts it to a FormData object
|
30
|
+
*
|
31
|
+
* @param {Object<string, any>} params - The parameters to be converted to a FormData object.
|
32
|
+
* @param {Object<string, any>} options - The options object passed to the Axios constructor.
|
33
|
+
*
|
34
|
+
* @returns {void}
|
35
|
+
*/
|
36
|
+
function AxiosURLSearchParams(params, options) {
|
37
|
+
this._pairs = [];
|
38
|
+
|
39
|
+
params && toFormData(params, this, options);
|
40
|
+
}
|
41
|
+
|
42
|
+
const prototype = AxiosURLSearchParams.prototype;
|
43
|
+
|
44
|
+
prototype.append = function append(name, value) {
|
45
|
+
this._pairs.push([name, value]);
|
46
|
+
};
|
47
|
+
|
48
|
+
prototype.toString = function toString(encoder) {
|
49
|
+
const _encode = encoder ? function(value) {
|
50
|
+
return encoder.call(this, value, encode);
|
51
|
+
} : encode;
|
52
|
+
|
53
|
+
return this._pairs.map(function each(pair) {
|
54
|
+
return _encode(pair[0]) + '=' + _encode(pair[1]);
|
55
|
+
}, '').join('&');
|
56
|
+
};
|
57
|
+
|
58
|
+
export default AxiosURLSearchParams;
|
@@ -0,0 +1,71 @@
|
|
1
|
+
const HttpStatusCode = {
|
2
|
+
Continue: 100,
|
3
|
+
SwitchingProtocols: 101,
|
4
|
+
Processing: 102,
|
5
|
+
EarlyHints: 103,
|
6
|
+
Ok: 200,
|
7
|
+
Created: 201,
|
8
|
+
Accepted: 202,
|
9
|
+
NonAuthoritativeInformation: 203,
|
10
|
+
NoContent: 204,
|
11
|
+
ResetContent: 205,
|
12
|
+
PartialContent: 206,
|
13
|
+
MultiStatus: 207,
|
14
|
+
AlreadyReported: 208,
|
15
|
+
ImUsed: 226,
|
16
|
+
MultipleChoices: 300,
|
17
|
+
MovedPermanently: 301,
|
18
|
+
Found: 302,
|
19
|
+
SeeOther: 303,
|
20
|
+
NotModified: 304,
|
21
|
+
UseProxy: 305,
|
22
|
+
Unused: 306,
|
23
|
+
TemporaryRedirect: 307,
|
24
|
+
PermanentRedirect: 308,
|
25
|
+
BadRequest: 400,
|
26
|
+
Unauthorized: 401,
|
27
|
+
PaymentRequired: 402,
|
28
|
+
Forbidden: 403,
|
29
|
+
NotFound: 404,
|
30
|
+
MethodNotAllowed: 405,
|
31
|
+
NotAcceptable: 406,
|
32
|
+
ProxyAuthenticationRequired: 407,
|
33
|
+
RequestTimeout: 408,
|
34
|
+
Conflict: 409,
|
35
|
+
Gone: 410,
|
36
|
+
LengthRequired: 411,
|
37
|
+
PreconditionFailed: 412,
|
38
|
+
PayloadTooLarge: 413,
|
39
|
+
UriTooLong: 414,
|
40
|
+
UnsupportedMediaType: 415,
|
41
|
+
RangeNotSatisfiable: 416,
|
42
|
+
ExpectationFailed: 417,
|
43
|
+
ImATeapot: 418,
|
44
|
+
MisdirectedRequest: 421,
|
45
|
+
UnprocessableEntity: 422,
|
46
|
+
Locked: 423,
|
47
|
+
FailedDependency: 424,
|
48
|
+
TooEarly: 425,
|
49
|
+
UpgradeRequired: 426,
|
50
|
+
PreconditionRequired: 428,
|
51
|
+
TooManyRequests: 429,
|
52
|
+
RequestHeaderFieldsTooLarge: 431,
|
53
|
+
UnavailableForLegalReasons: 451,
|
54
|
+
InternalServerError: 500,
|
55
|
+
NotImplemented: 501,
|
56
|
+
BadGateway: 502,
|
57
|
+
ServiceUnavailable: 503,
|
58
|
+
GatewayTimeout: 504,
|
59
|
+
HttpVersionNotSupported: 505,
|
60
|
+
VariantAlsoNegotiates: 506,
|
61
|
+
InsufficientStorage: 507,
|
62
|
+
LoopDetected: 508,
|
63
|
+
NotExtended: 510,
|
64
|
+
NetworkAuthenticationRequired: 511,
|
65
|
+
};
|
66
|
+
|
67
|
+
Object.entries(HttpStatusCode).forEach(([key, value]) => {
|
68
|
+
HttpStatusCode[value] = key;
|
69
|
+
});
|
70
|
+
|
71
|
+
export default HttpStatusCode;
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# axios // helpers
|
2
|
+
|
3
|
+
The modules found in `helpers/` should be generic modules that are _not_ specific to the domain logic of axios. These modules could theoretically be published to npm on their own and consumed by other modules or apps. Some examples of generic modules are things like:
|
4
|
+
|
5
|
+
- Browser polyfills
|
6
|
+
- Managing cookies
|
7
|
+
- Parsing HTTP headers
|
@@ -0,0 +1,28 @@
|
|
1
|
+
"use strict";
|
2
|
+
|
3
|
+
import stream from "stream";
|
4
|
+
|
5
|
+
class ZlibHeaderTransformStream extends stream.Transform {
|
6
|
+
__transform(chunk, encoding, callback) {
|
7
|
+
this.push(chunk);
|
8
|
+
callback();
|
9
|
+
}
|
10
|
+
|
11
|
+
_transform(chunk, encoding, callback) {
|
12
|
+
if (chunk.length !== 0) {
|
13
|
+
this._transform = this.__transform;
|
14
|
+
|
15
|
+
// Add Default Compression headers if no zlib headers are present
|
16
|
+
if (chunk[0] !== 120) { // Hex: 78
|
17
|
+
const header = Buffer.alloc(2);
|
18
|
+
header[0] = 120; // Hex: 78
|
19
|
+
header[1] = 156; // Hex: 9C
|
20
|
+
this.push(header, encoding);
|
21
|
+
}
|
22
|
+
}
|
23
|
+
|
24
|
+
this.__transform(chunk, encoding, callback);
|
25
|
+
}
|
26
|
+
}
|
27
|
+
|
28
|
+
export default ZlibHeaderTransformStream;
|
package/helpers/bind.js
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
import utils from '../utils.js';
|
4
|
+
import AxiosURLSearchParams from '../helpers/AxiosURLSearchParams.js';
|
5
|
+
|
6
|
+
/**
|
7
|
+
* It replaces all instances of the characters `:`, `$`, `,`, `+`, `[`, and `]` with their
|
8
|
+
* URI encoded counterparts
|
9
|
+
*
|
10
|
+
* @param {string} val The value to be encoded.
|
11
|
+
*
|
12
|
+
* @returns {string} The encoded value.
|
13
|
+
*/
|
14
|
+
function encode(val) {
|
15
|
+
return encodeURIComponent(val).
|
16
|
+
replace(/%3A/gi, ':').
|
17
|
+
replace(/%24/g, '$').
|
18
|
+
replace(/%2C/gi, ',').
|
19
|
+
replace(/%20/g, '+').
|
20
|
+
replace(/%5B/gi, '[').
|
21
|
+
replace(/%5D/gi, ']');
|
22
|
+
}
|
23
|
+
|
24
|
+
/**
|
25
|
+
* Build a URL by appending params to the end
|
26
|
+
*
|
27
|
+
* @param {string} url The base of the url (e.g., http://www.google.com)
|
28
|
+
* @param {object} [params] The params to be appended
|
29
|
+
* @param {?object} options
|
30
|
+
*
|
31
|
+
* @returns {string} The formatted url
|
32
|
+
*/
|
33
|
+
export default function buildURL(url, params, options) {
|
34
|
+
/*eslint no-param-reassign:0*/
|
35
|
+
if (!params) {
|
36
|
+
return url;
|
37
|
+
}
|
38
|
+
|
39
|
+
const _encode = options && options.encode || encode;
|
40
|
+
|
41
|
+
const serializeFn = options && options.serialize;
|
42
|
+
|
43
|
+
let serializedParams;
|
44
|
+
|
45
|
+
if (serializeFn) {
|
46
|
+
serializedParams = serializeFn(params, options);
|
47
|
+
} else {
|
48
|
+
serializedParams = utils.isURLSearchParams(params) ?
|
49
|
+
params.toString() :
|
50
|
+
new AxiosURLSearchParams(params, options).toString(_encode);
|
51
|
+
}
|
52
|
+
|
53
|
+
if (serializedParams) {
|
54
|
+
const hashmarkIndex = url.indexOf("#");
|
55
|
+
|
56
|
+
if (hashmarkIndex !== -1) {
|
57
|
+
url = url.slice(0, hashmarkIndex);
|
58
|
+
}
|
59
|
+
url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams;
|
60
|
+
}
|
61
|
+
|
62
|
+
return url;
|
63
|
+
}
|
@@ -0,0 +1,16 @@
|
|
1
|
+
import utils from "../utils.js";
|
2
|
+
|
3
|
+
const callbackify = (fn, reducer) => {
|
4
|
+
return utils.isAsyncFn(fn) ? function (...args) {
|
5
|
+
const cb = args.pop();
|
6
|
+
fn.apply(this, args).then((value) => {
|
7
|
+
try {
|
8
|
+
reducer ? cb(null, ...reducer(value)) : cb(null, value);
|
9
|
+
} catch (err) {
|
10
|
+
cb(err);
|
11
|
+
}
|
12
|
+
}, cb);
|
13
|
+
} : fn;
|
14
|
+
}
|
15
|
+
|
16
|
+
export default callbackify;
|
@@ -0,0 +1,15 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
/**
|
4
|
+
* Creates a new URL by combining the specified URLs
|
5
|
+
*
|
6
|
+
* @param {string} baseURL The base URL
|
7
|
+
* @param {string} relativeURL The relative URL
|
8
|
+
*
|
9
|
+
* @returns {string} The combined URL
|
10
|
+
*/
|
11
|
+
export default function combineURLs(baseURL, relativeURL) {
|
12
|
+
return relativeURL
|
13
|
+
? baseURL.replace(/\/+$/, '') + '/' + relativeURL.replace(/^\/+/, '')
|
14
|
+
: baseURL;
|
15
|
+
}
|
@@ -0,0 +1,52 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
import utils from './../utils.js';
|
4
|
+
import platform from '../platform/index.js';
|
5
|
+
|
6
|
+
export default platform.isStandardBrowserEnv ?
|
7
|
+
|
8
|
+
// Standard browser envs support document.cookie
|
9
|
+
(function standardBrowserEnv() {
|
10
|
+
return {
|
11
|
+
write: function write(name, value, expires, path, domain, secure) {
|
12
|
+
const cookie = [];
|
13
|
+
cookie.push(name + '=' + encodeURIComponent(value));
|
14
|
+
|
15
|
+
if (utils.isNumber(expires)) {
|
16
|
+
cookie.push('expires=' + new Date(expires).toGMTString());
|
17
|
+
}
|
18
|
+
|
19
|
+
if (utils.isString(path)) {
|
20
|
+
cookie.push('path=' + path);
|
21
|
+
}
|
22
|
+
|
23
|
+
if (utils.isString(domain)) {
|
24
|
+
cookie.push('domain=' + domain);
|
25
|
+
}
|
26
|
+
|
27
|
+
if (secure === true) {
|
28
|
+
cookie.push('secure');
|
29
|
+
}
|
30
|
+
|
31
|
+
document.cookie = cookie.join('; ');
|
32
|
+
},
|
33
|
+
|
34
|
+
read: function read(name) {
|
35
|
+
const match = document.cookie.match(new RegExp('(^|;\\s*)(' + name + ')=([^;]*)'));
|
36
|
+
return (match ? decodeURIComponent(match[3]) : null);
|
37
|
+
},
|
38
|
+
|
39
|
+
remove: function remove(name) {
|
40
|
+
this.write(name, '', Date.now() - 86400000);
|
41
|
+
}
|
42
|
+
};
|
43
|
+
})() :
|
44
|
+
|
45
|
+
// Non standard browser env (web workers, react-native) lack needed support.
|
46
|
+
(function nonStandardBrowserEnv() {
|
47
|
+
return {
|
48
|
+
write: function write() {},
|
49
|
+
read: function read() { return null; },
|
50
|
+
remove: function remove() {}
|
51
|
+
};
|
52
|
+
})();
|
@@ -0,0 +1,26 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
/*eslint no-console:0*/
|
4
|
+
|
5
|
+
/**
|
6
|
+
* Supply a warning to the developer that a method they are using
|
7
|
+
* has been deprecated.
|
8
|
+
*
|
9
|
+
* @param {string} method The name of the deprecated method
|
10
|
+
* @param {string} [instead] The alternate method to use if applicable
|
11
|
+
* @param {string} [docs] The documentation URL to get further details
|
12
|
+
*
|
13
|
+
* @returns {void}
|
14
|
+
*/
|
15
|
+
export default function deprecatedMethod(method, instead, docs) {
|
16
|
+
try {
|
17
|
+
console.warn(
|
18
|
+
'DEPRECATED method `' + method + '`.' +
|
19
|
+
(instead ? ' Use `' + instead + '` instead.' : '') +
|
20
|
+
' This method will be removed in a future release.');
|
21
|
+
|
22
|
+
if (docs) {
|
23
|
+
console.warn('For more information about usage see ' + docs);
|
24
|
+
}
|
25
|
+
} catch (e) { /* Ignore */ }
|
26
|
+
}
|
@@ -0,0 +1,92 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
import utils from '../utils.js';
|
4
|
+
|
5
|
+
/**
|
6
|
+
* It takes a string like `foo[x][y][z]` and returns an array like `['foo', 'x', 'y', 'z']
|
7
|
+
*
|
8
|
+
* @param {string} name - The name of the property to get.
|
9
|
+
*
|
10
|
+
* @returns An array of strings.
|
11
|
+
*/
|
12
|
+
function parsePropPath(name) {
|
13
|
+
// foo[x][y][z]
|
14
|
+
// foo.x.y.z
|
15
|
+
// foo-x-y-z
|
16
|
+
// foo x y z
|
17
|
+
return utils.matchAll(/\w+|\[(\w*)]/g, name).map(match => {
|
18
|
+
return match[0] === '[]' ? '' : match[1] || match[0];
|
19
|
+
});
|
20
|
+
}
|
21
|
+
|
22
|
+
/**
|
23
|
+
* Convert an array to an object.
|
24
|
+
*
|
25
|
+
* @param {Array<any>} arr - The array to convert to an object.
|
26
|
+
*
|
27
|
+
* @returns An object with the same keys and values as the array.
|
28
|
+
*/
|
29
|
+
function arrayToObject(arr) {
|
30
|
+
const obj = {};
|
31
|
+
const keys = Object.keys(arr);
|
32
|
+
let i;
|
33
|
+
const len = keys.length;
|
34
|
+
let key;
|
35
|
+
for (i = 0; i < len; i++) {
|
36
|
+
key = keys[i];
|
37
|
+
obj[key] = arr[key];
|
38
|
+
}
|
39
|
+
return obj;
|
40
|
+
}
|
41
|
+
|
42
|
+
/**
|
43
|
+
* It takes a FormData object and returns a JavaScript object
|
44
|
+
*
|
45
|
+
* @param {string} formData The FormData object to convert to JSON.
|
46
|
+
*
|
47
|
+
* @returns {Object<string, any> | null} The converted object.
|
48
|
+
*/
|
49
|
+
function formDataToJSON(formData) {
|
50
|
+
function buildPath(path, value, target, index) {
|
51
|
+
let name = path[index++];
|
52
|
+
const isNumericKey = Number.isFinite(+name);
|
53
|
+
const isLast = index >= path.length;
|
54
|
+
name = !name && utils.isArray(target) ? target.length : name;
|
55
|
+
|
56
|
+
if (isLast) {
|
57
|
+
if (utils.hasOwnProp(target, name)) {
|
58
|
+
target[name] = [target[name], value];
|
59
|
+
} else {
|
60
|
+
target[name] = value;
|
61
|
+
}
|
62
|
+
|
63
|
+
return !isNumericKey;
|
64
|
+
}
|
65
|
+
|
66
|
+
if (!target[name] || !utils.isObject(target[name])) {
|
67
|
+
target[name] = [];
|
68
|
+
}
|
69
|
+
|
70
|
+
const result = buildPath(path, value, target[name], index);
|
71
|
+
|
72
|
+
if (result && utils.isArray(target[name])) {
|
73
|
+
target[name] = arrayToObject(target[name]);
|
74
|
+
}
|
75
|
+
|
76
|
+
return !isNumericKey;
|
77
|
+
}
|
78
|
+
|
79
|
+
if (utils.isFormData(formData) && utils.isFunction(formData.entries)) {
|
80
|
+
const obj = {};
|
81
|
+
|
82
|
+
utils.forEachEntry(formData, (name, value) => {
|
83
|
+
buildPath(parsePropPath(name), value, obj, 0);
|
84
|
+
});
|
85
|
+
|
86
|
+
return obj;
|
87
|
+
}
|
88
|
+
|
89
|
+
return null;
|
90
|
+
}
|
91
|
+
|
92
|
+
export default formDataToJSON;
|