axios 1.6.7 → 1.7.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of axios might be problematic. Click here for more details.

package/index.d.cts CHANGED
@@ -268,7 +268,8 @@ declare namespace axios {
268
268
  | 'document'
269
269
  | 'json'
270
270
  | 'text'
271
- | 'stream';
271
+ | 'stream'
272
+ | 'formdata';
272
273
 
273
274
  type responseEncoding =
274
275
  | 'ascii' | 'ASCII'
@@ -353,11 +354,12 @@ declare namespace axios {
353
354
  upload?: boolean;
354
355
  download?: boolean;
355
356
  event?: BrowserProgressEvent;
357
+ lengthComputable: boolean;
356
358
  }
357
359
 
358
360
  type Milliseconds = number;
359
361
 
360
- type AxiosAdapterName = 'xhr' | 'http' | string;
362
+ type AxiosAdapterName = 'fetch' | 'xhr' | 'http' | string;
361
363
 
362
364
  type AxiosAdapterConfig = AxiosAdapter | AxiosAdapterName;
363
365
 
@@ -415,6 +417,7 @@ declare namespace axios {
415
417
  lookup?: ((hostname: string, options: object, cb: (err: Error | null, address: LookupAddress | LookupAddress[], family?: AddressFamily) => void) => void) |
416
418
  ((hostname: string, options: object) => Promise<[address: LookupAddressEntry | LookupAddressEntry[], family?: AddressFamily] | LookupAddress>);
417
419
  withXSRFToken?: boolean | ((config: InternalAxiosRequestConfig) => boolean | undefined);
420
+ fetchOptions?: Record<string, any>;
418
421
  }
419
422
 
420
423
  // Alias
package/index.d.ts CHANGED
@@ -209,7 +209,8 @@ export type ResponseType =
209
209
  | 'document'
210
210
  | 'json'
211
211
  | 'text'
212
- | 'stream';
212
+ | 'stream'
213
+ | 'formdata';
213
214
 
214
215
  export type responseEncoding =
215
216
  | 'ascii' | 'ASCII'
@@ -294,11 +295,12 @@ export interface AxiosProgressEvent {
294
295
  upload?: boolean;
295
296
  download?: boolean;
296
297
  event?: BrowserProgressEvent;
298
+ lengthComputable: boolean;
297
299
  }
298
300
 
299
301
  type Milliseconds = number;
300
302
 
301
- type AxiosAdapterName = 'xhr' | 'http' | string;
303
+ type AxiosAdapterName = 'fetch' | 'xhr' | 'http' | string;
302
304
 
303
305
  type AxiosAdapterConfig = AxiosAdapter | AxiosAdapterName;
304
306
 
@@ -356,6 +358,7 @@ export interface AxiosRequestConfig<D = any> {
356
358
  lookup?: ((hostname: string, options: object, cb: (err: Error | null, address: LookupAddress | LookupAddress[], family?: AddressFamily) => void) => void) |
357
359
  ((hostname: string, options: object) => Promise<[address: LookupAddressEntry | LookupAddressEntry[], family?: AddressFamily] | LookupAddress>);
358
360
  withXSRFToken?: boolean | ((config: InternalAxiosRequestConfig) => boolean | undefined);
361
+ fetchOptions?: Record<string, any>;
359
362
  }
360
363
 
361
364
  // Alias
@@ -1,11 +1,13 @@
1
1
  import utils from '../utils.js';
2
2
  import httpAdapter from './http.js';
3
3
  import xhrAdapter from './xhr.js';
4
+ import fetchAdapter from './fetch.js';
4
5
  import AxiosError from "../core/AxiosError.js";
5
6
 
6
7
  const knownAdapters = {
7
8
  http: httpAdapter,
8
- xhr: xhrAdapter
9
+ xhr: xhrAdapter,
10
+ fetch: fetchAdapter
9
11
  }
10
12
 
11
13
  utils.forEach(knownAdapters, (fn, value) => {
@@ -0,0 +1,197 @@
1
+ import platform from "../platform/index.js";
2
+ import utils from "../utils.js";
3
+ import AxiosError from "../core/AxiosError.js";
4
+ import composeSignals from "../helpers/composeSignals.js";
5
+ import {trackStream} from "../helpers/trackStream.js";
6
+ import AxiosHeaders from "../core/AxiosHeaders.js";
7
+ import progressEventReducer from "../helpers/progressEventReducer.js";
8
+ import resolveConfig from "../helpers/resolveConfig.js";
9
+ import settle from "../core/settle.js";
10
+
11
+ const fetchProgressDecorator = (total, fn) => {
12
+ const lengthComputable = total != null;
13
+ return (loaded) => setTimeout(() => fn({
14
+ lengthComputable,
15
+ total,
16
+ loaded
17
+ }));
18
+ }
19
+
20
+ const isFetchSupported = typeof fetch !== 'undefined';
21
+
22
+ const supportsRequestStreams = isFetchSupported && (() => {
23
+ let duplexAccessed = false;
24
+
25
+ const hasContentType = new Request(platform.origin, {
26
+ body: new ReadableStream(),
27
+ method: 'POST',
28
+ get duplex() {
29
+ duplexAccessed = true;
30
+ return 'half';
31
+ },
32
+ }).headers.has('Content-Type');
33
+
34
+ return duplexAccessed && !hasContentType;
35
+ })();
36
+
37
+ const DEFAULT_CHUNK_SIZE = 64 * 1024;
38
+
39
+ const resolvers = {
40
+ stream: (res) => res.body
41
+ };
42
+
43
+ isFetchSupported && ['text', 'arrayBuffer', 'blob', 'formData'].forEach(type => [
44
+ resolvers[type] = utils.isFunction(Response.prototype[type]) ? (res) => res[type]() : (_, config) => {
45
+ throw new AxiosError(`Response type ${type} is not supported`, AxiosError.ERR_NOT_SUPPORT, config);
46
+ }
47
+ ])
48
+
49
+ const getBodyLength = async (body) => {
50
+ if(utils.isBlob(body)) {
51
+ return body.size;
52
+ }
53
+
54
+ if(utils.isSpecCompliantForm(body)) {
55
+ return (await new Request(body).arrayBuffer()).byteLength;
56
+ }
57
+
58
+ if(utils.isArrayBufferView(body)) {
59
+ return body.byteLength;
60
+ }
61
+
62
+ if(utils.isURLSearchParams(body)) {
63
+ body = body + '';
64
+ }
65
+
66
+ if(utils.isString(body)) {
67
+ return (await new TextEncoder().encode(body)).byteLength;
68
+ }
69
+ }
70
+
71
+ const resolveBodyLength = async (headers, body) => {
72
+ const length = utils.toFiniteNumber(headers.getContentLength());
73
+
74
+ return length == null ? getBodyLength(body) : length;
75
+ }
76
+
77
+ export default async (config) => {
78
+ let {
79
+ url,
80
+ method,
81
+ data,
82
+ signal,
83
+ cancelToken,
84
+ timeout,
85
+ onDownloadProgress,
86
+ onUploadProgress,
87
+ responseType,
88
+ headers,
89
+ withCredentials = 'same-origin',
90
+ fetchOptions
91
+ } = resolveConfig(config);
92
+
93
+ responseType = responseType ? (responseType + '').toLowerCase() : 'text';
94
+
95
+ let [composedSignal, stopTimeout] = (signal || cancelToken || timeout) ?
96
+ composeSignals([signal, cancelToken], timeout) : [];
97
+
98
+ let finished, request;
99
+
100
+ const onFinish = () => {
101
+ !finished && setTimeout(() => {
102
+ composedSignal && composedSignal.unsubscribe();
103
+ });
104
+
105
+ finished = true;
106
+ }
107
+
108
+ try {
109
+ if (onUploadProgress && supportsRequestStreams && method !== 'get' && method !== 'head') {
110
+ let requestContentLength = await resolveBodyLength(headers, data);
111
+
112
+ let _request = new Request(url, {
113
+ method,
114
+ body: data,
115
+ duplex: "half"
116
+ });
117
+
118
+ let contentTypeHeader;
119
+
120
+ if (utils.isFormData(data) && (contentTypeHeader = _request.headers.get('content-type'))) {
121
+ headers.setContentType(contentTypeHeader)
122
+ }
123
+
124
+ data = trackStream(_request.body, DEFAULT_CHUNK_SIZE, fetchProgressDecorator(
125
+ requestContentLength,
126
+ progressEventReducer(onUploadProgress)
127
+ ));
128
+ }
129
+
130
+ if (!utils.isString(withCredentials)) {
131
+ withCredentials = withCredentials ? 'cors' : 'omit';
132
+ }
133
+
134
+ request = new Request(url, {
135
+ ...fetchOptions,
136
+ signal: composedSignal,
137
+ method,
138
+ headers: headers.normalize().toJSON(),
139
+ body: data,
140
+ duplex: "half",
141
+ withCredentials
142
+ });
143
+
144
+ let response = await fetch(request);
145
+
146
+ const isStreamResponse = responseType === 'stream' || responseType === 'response';
147
+
148
+ if (onDownloadProgress || isStreamResponse) {
149
+ const options = {};
150
+
151
+ Object.getOwnPropertyNames(response).forEach(prop => {
152
+ options[prop] = response[prop];
153
+ });
154
+
155
+ const responseContentLength = utils.toFiniteNumber(response.headers.get('content-length'));
156
+
157
+ response = new Response(
158
+ trackStream(response.body, DEFAULT_CHUNK_SIZE, onDownloadProgress && fetchProgressDecorator(
159
+ responseContentLength,
160
+ progressEventReducer(onDownloadProgress, true)
161
+ ), isStreamResponse && onFinish),
162
+ options
163
+ );
164
+ }
165
+
166
+ responseType = responseType || 'text';
167
+
168
+ let responseData = await resolvers[utils.findKey(resolvers, responseType) || 'text'](response, config);
169
+
170
+ !isStreamResponse && onFinish();
171
+
172
+ stopTimeout && stopTimeout();
173
+
174
+ return await new Promise((resolve, reject) => {
175
+ settle(resolve, reject, {
176
+ data: responseData,
177
+ headers: AxiosHeaders.from(response.headers),
178
+ status: response.status,
179
+ statusText: response.statusText,
180
+ config,
181
+ request
182
+ })
183
+ })
184
+ } catch (err) {
185
+ onFinish();
186
+
187
+ let {code} = err;
188
+
189
+ if (err.name === 'NetworkError') {
190
+ code = AxiosError.ERR_NETWORK;
191
+ }
192
+
193
+ throw AxiosError.from(err, code, config, request);
194
+ }
195
+ }
196
+
197
+
@@ -19,7 +19,7 @@ import fromDataURI from '../helpers/fromDataURI.js';
19
19
  import stream from 'stream';
20
20
  import AxiosHeaders from '../core/AxiosHeaders.js';
21
21
  import AxiosTransformStream from '../helpers/AxiosTransformStream.js';
22
- import EventEmitter from 'events';
22
+ import {EventEmitter} from 'events';
23
23
  import formDataToStream from "../helpers/formDataToStream.js";
24
24
  import readBlob from "../helpers/readBlob.js";
25
25
  import ZlibHeaderTransformStream from '../helpers/ZlibHeaderTransformStream.js';
@@ -1,93 +1,39 @@
1
- 'use strict';
2
-
3
1
  import utils from './../utils.js';
4
2
  import settle from './../core/settle.js';
5
- import cookies from './../helpers/cookies.js';
6
- import buildURL from './../helpers/buildURL.js';
7
- import buildFullPath from '../core/buildFullPath.js';
8
- import isURLSameOrigin from './../helpers/isURLSameOrigin.js';
9
3
  import transitionalDefaults from '../defaults/transitional.js';
10
4
  import AxiosError from '../core/AxiosError.js';
11
5
  import CanceledError from '../cancel/CanceledError.js';
12
6
  import parseProtocol from '../helpers/parseProtocol.js';
13
7
  import platform from '../platform/index.js';
14
8
  import AxiosHeaders from '../core/AxiosHeaders.js';
15
- import speedometer from '../helpers/speedometer.js';
16
-
17
- function progressEventReducer(listener, isDownloadStream) {
18
- let bytesNotified = 0;
19
- const _speedometer = speedometer(50, 250);
20
-
21
- return e => {
22
- const loaded = e.loaded;
23
- const total = e.lengthComputable ? e.total : undefined;
24
- const progressBytes = loaded - bytesNotified;
25
- const rate = _speedometer(progressBytes);
26
- const inRange = loaded <= total;
27
-
28
- bytesNotified = loaded;
29
-
30
- const data = {
31
- loaded,
32
- total,
33
- progress: total ? (loaded / total) : undefined,
34
- bytes: progressBytes,
35
- rate: rate ? rate : undefined,
36
- estimated: rate && total && inRange ? (total - loaded) / rate : undefined,
37
- event: e
38
- };
39
-
40
- data[isDownloadStream ? 'download' : 'upload'] = true;
41
-
42
- listener(data);
43
- };
44
- }
9
+ import progressEventReducer from '../helpers/progressEventReducer.js';
10
+ import resolveConfig from "../helpers/resolveConfig.js";
45
11
 
46
12
  const isXHRAdapterSupported = typeof XMLHttpRequest !== 'undefined';
47
13
 
48
14
  export default isXHRAdapterSupported && function (config) {
49
15
  return new Promise(function dispatchXhrRequest(resolve, reject) {
50
- let requestData = config.data;
51
- const requestHeaders = AxiosHeaders.from(config.headers).normalize();
52
- let {responseType, withXSRFToken} = config;
16
+ const _config = resolveConfig(config);
17
+ let requestData = _config.data;
18
+ const requestHeaders = AxiosHeaders.from(_config.headers).normalize();
19
+ let {responseType} = _config;
53
20
  let onCanceled;
54
21
  function done() {
55
- if (config.cancelToken) {
56
- config.cancelToken.unsubscribe(onCanceled);
22
+ if (_config.cancelToken) {
23
+ _config.cancelToken.unsubscribe(onCanceled);
57
24
  }
58
25
 
59
- if (config.signal) {
60
- config.signal.removeEventListener('abort', onCanceled);
61
- }
62
- }
63
-
64
- let contentType;
65
-
66
- if (utils.isFormData(requestData)) {
67
- if (platform.hasStandardBrowserEnv || platform.hasStandardBrowserWebWorkerEnv) {
68
- requestHeaders.setContentType(false); // Let the browser set it
69
- } else if ((contentType = requestHeaders.getContentType()) !== false) {
70
- // fix semicolon duplication issue for ReactNative FormData implementation
71
- const [type, ...tokens] = contentType ? contentType.split(';').map(token => token.trim()).filter(Boolean) : [];
72
- requestHeaders.setContentType([type || 'multipart/form-data', ...tokens].join('; '));
26
+ if (_config.signal) {
27
+ _config.signal.removeEventListener('abort', onCanceled);
73
28
  }
74
29
  }
75
30
 
76
31
  let request = new XMLHttpRequest();
77
32
 
78
- // HTTP basic authentication
79
- if (config.auth) {
80
- const username = config.auth.username || '';
81
- const password = config.auth.password ? unescape(encodeURIComponent(config.auth.password)) : '';
82
- requestHeaders.set('Authorization', 'Basic ' + btoa(username + ':' + password));
83
- }
84
-
85
- const fullPath = buildFullPath(config.baseURL, config.url);
86
-
87
- request.open(config.method.toUpperCase(), buildURL(fullPath, config.params, config.paramsSerializer), true);
33
+ request.open(_config.method.toUpperCase(), _config.url, true);
88
34
 
89
35
  // Set the request timeout in MS
90
- request.timeout = config.timeout;
36
+ request.timeout = _config.timeout;
91
37
 
92
38
  function onloadend() {
93
39
  if (!request) {
@@ -149,7 +95,7 @@ export default isXHRAdapterSupported && function (config) {
149
95
  return;
150
96
  }
151
97
 
152
- reject(new AxiosError('Request aborted', AxiosError.ECONNABORTED, config, request));
98
+ reject(new AxiosError('Request aborted', AxiosError.ECONNABORTED, _config, request));
153
99
 
154
100
  // Clean up request
155
101
  request = null;
@@ -159,7 +105,7 @@ export default isXHRAdapterSupported && function (config) {
159
105
  request.onerror = function handleError() {
160
106
  // Real errors are hidden from us by the browser
161
107
  // onerror should only fire if it's a network error
162
- reject(new AxiosError('Network Error', AxiosError.ERR_NETWORK, config, request));
108
+ reject(new AxiosError('Network Error', AxiosError.ERR_NETWORK, _config, request));
163
109
 
164
110
  // Clean up request
165
111
  request = null;
@@ -167,37 +113,21 @@ export default isXHRAdapterSupported && function (config) {
167
113
 
168
114
  // Handle timeout
169
115
  request.ontimeout = function handleTimeout() {
170
- let timeoutErrorMessage = config.timeout ? 'timeout of ' + config.timeout + 'ms exceeded' : 'timeout exceeded';
171
- const transitional = config.transitional || transitionalDefaults;
172
- if (config.timeoutErrorMessage) {
173
- timeoutErrorMessage = config.timeoutErrorMessage;
116
+ let timeoutErrorMessage = _config.timeout ? 'timeout of ' + _config.timeout + 'ms exceeded' : 'timeout exceeded';
117
+ const transitional = _config.transitional || transitionalDefaults;
118
+ if (_config.timeoutErrorMessage) {
119
+ timeoutErrorMessage = _config.timeoutErrorMessage;
174
120
  }
175
121
  reject(new AxiosError(
176
122
  timeoutErrorMessage,
177
123
  transitional.clarifyTimeoutError ? AxiosError.ETIMEDOUT : AxiosError.ECONNABORTED,
178
- config,
124
+ _config,
179
125
  request));
180
126
 
181
127
  // Clean up request
182
128
  request = null;
183
129
  };
184
130
 
185
- // Add xsrf header
186
- // This is only done if running in a standard browser environment.
187
- // Specifically not if we're in a web worker, or react-native.
188
- if(platform.hasStandardBrowserEnv) {
189
- withXSRFToken && utils.isFunction(withXSRFToken) && (withXSRFToken = withXSRFToken(config));
190
-
191
- if (withXSRFToken || (withXSRFToken !== false && isURLSameOrigin(fullPath))) {
192
- // Add xsrf header
193
- const xsrfValue = config.xsrfHeaderName && config.xsrfCookieName && cookies.read(config.xsrfCookieName);
194
-
195
- if (xsrfValue) {
196
- requestHeaders.set(config.xsrfHeaderName, xsrfValue);
197
- }
198
- }
199
- }
200
-
201
131
  // Remove Content-Type if data is undefined
202
132
  requestData === undefined && requestHeaders.setContentType(null);
203
133
 
@@ -209,26 +139,26 @@ export default isXHRAdapterSupported && function (config) {
209
139
  }
210
140
 
211
141
  // Add withCredentials to request if needed
212
- if (!utils.isUndefined(config.withCredentials)) {
213
- request.withCredentials = !!config.withCredentials;
142
+ if (!utils.isUndefined(_config.withCredentials)) {
143
+ request.withCredentials = !!_config.withCredentials;
214
144
  }
215
145
 
216
146
  // Add responseType to request if needed
217
147
  if (responseType && responseType !== 'json') {
218
- request.responseType = config.responseType;
148
+ request.responseType = _config.responseType;
219
149
  }
220
150
 
221
151
  // Handle progress if needed
222
- if (typeof config.onDownloadProgress === 'function') {
223
- request.addEventListener('progress', progressEventReducer(config.onDownloadProgress, true));
152
+ if (typeof _config.onDownloadProgress === 'function') {
153
+ request.addEventListener('progress', progressEventReducer(_config.onDownloadProgress, true));
224
154
  }
225
155
 
226
156
  // Not all browsers support upload events
227
- if (typeof config.onUploadProgress === 'function' && request.upload) {
228
- request.upload.addEventListener('progress', progressEventReducer(config.onUploadProgress));
157
+ if (typeof _config.onUploadProgress === 'function' && request.upload) {
158
+ request.upload.addEventListener('progress', progressEventReducer(_config.onUploadProgress));
229
159
  }
230
160
 
231
- if (config.cancelToken || config.signal) {
161
+ if (_config.cancelToken || _config.signal) {
232
162
  // Handle cancellation
233
163
  // eslint-disable-next-line func-names
234
164
  onCanceled = cancel => {
@@ -240,13 +170,13 @@ export default isXHRAdapterSupported && function (config) {
240
170
  request = null;
241
171
  };
242
172
 
243
- config.cancelToken && config.cancelToken.subscribe(onCanceled);
244
- if (config.signal) {
245
- config.signal.aborted ? onCanceled() : config.signal.addEventListener('abort', onCanceled);
173
+ _config.cancelToken && _config.cancelToken.subscribe(onCanceled);
174
+ if (_config.signal) {
175
+ _config.signal.aborted ? onCanceled() : _config.signal.addEventListener('abort', onCanceled);
246
176
  }
247
177
  }
248
178
 
249
- const protocol = parseProtocol(fullPath);
179
+ const protocol = parseProtocol(_config.url);
250
180
 
251
181
  if (protocol && platform.protocols.indexOf(protocol) === -1) {
252
182
  reject(new AxiosError('Unsupported protocol ' + protocol + ':', AxiosError.ERR_BAD_REQUEST, config));
@@ -100,6 +100,10 @@ class AxiosHeaders {
100
100
  setHeaders(header, valueOrRewrite)
101
101
  } else if(utils.isString(header) && (header = header.trim()) && !isValidHeaderName(header)) {
102
102
  setHeaders(parseHeaders(header), valueOrRewrite);
103
+ } else if (utils.isHeaders(header)) {
104
+ for (const [key, value] of header.entries()) {
105
+ setHeader(value, key, rewrite);
106
+ }
103
107
  } else {
104
108
  header != null && setHeader(valueOrRewrite, header, rewrite);
105
109
  }
@@ -3,7 +3,7 @@
3
3
  import utils from '../utils.js';
4
4
  import AxiosHeaders from "./AxiosHeaders.js";
5
5
 
6
- const headersToObject = (thing) => thing instanceof AxiosHeaders ? thing.toJSON() : thing;
6
+ const headersToObject = (thing) => thing instanceof AxiosHeaders ? { ...thing } : thing;
7
7
 
8
8
  /**
9
9
  * Config-specific merge-function which creates a new config-object
@@ -37,7 +37,7 @@ const defaults = {
37
37
 
38
38
  transitional: transitionalDefaults,
39
39
 
40
- adapter: ['xhr', 'http'],
40
+ adapter: ['xhr', 'http', 'fetch'],
41
41
 
42
42
  transformRequest: [function transformRequest(data, headers) {
43
43
  const contentType = headers.getContentType() || '';
@@ -58,7 +58,8 @@ const defaults = {
58
58
  utils.isBuffer(data) ||
59
59
  utils.isStream(data) ||
60
60
  utils.isFile(data) ||
61
- utils.isBlob(data)
61
+ utils.isBlob(data) ||
62
+ utils.isReadableStream(data)
62
63
  ) {
63
64
  return data;
64
65
  }
@@ -101,6 +102,10 @@ const defaults = {
101
102
  const forcedJSONParsing = transitional && transitional.forcedJSONParsing;
102
103
  const JSONRequested = this.responseType === 'json';
103
104
 
105
+ if (utils.isResponse(data) || utils.isReadableStream(data)) {
106
+ return data;
107
+ }
108
+
104
109
  if (data && utils.isString(data) && ((forcedJSONParsing && !this.responseType) || JSONRequested)) {
105
110
  const silentJSONParsing = transitional && transitional.silentJSONParsing;
106
111
  const strictJSONParsing = !silentJSONParsing && JSONRequested;
package/lib/env/data.js CHANGED
@@ -1 +1 @@
1
- export const VERSION = "1.6.7";
1
+ export const VERSION = "1.7.0-beta.0";
@@ -65,19 +65,20 @@ class AxiosTransformStream extends stream.Transform{
65
65
 
66
66
  process.nextTick(() => {
67
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
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
+ lengthComputable: totalBytes != null
75
76
  });
76
77
  });
77
78
  }, internals.ticksRate);
78
79
 
79
80
  const onFinish = () => {
80
- internals.updateProgress(true);
81
+ internals.updateProgress.call(true);
81
82
  };
82
83
 
83
84
  this.once('end', onFinish);
@@ -0,0 +1,46 @@
1
+ import CanceledError from "../cancel/CanceledError.js";
2
+ import AxiosError from "../core/AxiosError.js";
3
+
4
+ const composeSignals = (signals, timeout) => {
5
+ let controller = new AbortController();
6
+
7
+ let aborted;
8
+
9
+ const onabort = function (cancel) {
10
+ if (!aborted) {
11
+ aborted = true;
12
+ unsubscribe();
13
+ const err = cancel instanceof Error ? cancel : this.reason;
14
+ controller.abort(err instanceof AxiosError ? err : new CanceledError(err instanceof Error ? err.message : err));
15
+ }
16
+ }
17
+
18
+ let timer = timeout && setTimeout(() => {
19
+ onabort(new AxiosError(`timeout ${timeout} of ms exceeded`, AxiosError.ETIMEDOUT))
20
+ }, timeout)
21
+
22
+ const unsubscribe = () => {
23
+ if (signals) {
24
+ timer && clearTimeout(timer);
25
+ timer = null;
26
+ signals.forEach(signal => {
27
+ signal &&
28
+ (signal.removeEventListener ? signal.removeEventListener('abort', onabort) : signal.unsubscribe(onabort));
29
+ });
30
+ signals = null;
31
+ }
32
+ }
33
+
34
+ signals.forEach((signal) => signal && signal.addEventListener && signal.addEventListener('abort', onabort));
35
+
36
+ const {signal} = controller;
37
+
38
+ signal.unsubscribe = unsubscribe;
39
+
40
+ return [signal, () => {
41
+ timer && clearTimeout(timer);
42
+ timer = null;
43
+ }];
44
+ }
45
+
46
+ export default composeSignals;
@@ -0,0 +1,32 @@
1
+ import speedometer from "./speedometer.js";
2
+ import throttle from "./throttle.js";
3
+
4
+ export default (listener, isDownloadStream, freq = 3) => {
5
+ let bytesNotified = 0;
6
+ const _speedometer = speedometer(50, 250);
7
+
8
+ return throttle(e => {
9
+ const loaded = e.loaded;
10
+ const total = e.lengthComputable ? e.total : undefined;
11
+ const progressBytes = loaded - bytesNotified;
12
+ const rate = _speedometer(progressBytes);
13
+ const inRange = loaded <= total;
14
+
15
+ bytesNotified = loaded;
16
+
17
+ const data = {
18
+ loaded,
19
+ total,
20
+ progress: total ? (loaded / total) : undefined,
21
+ bytes: progressBytes,
22
+ rate: rate ? rate : undefined,
23
+ estimated: rate && total && inRange ? (total - loaded) / rate : undefined,
24
+ event: e,
25
+ lengthComputable: total != null
26
+ };
27
+
28
+ data[isDownloadStream ? 'download' : 'upload'] = true;
29
+
30
+ listener(data);
31
+ }, freq);
32
+ }