source: node_modules/axios/lib/utils.js

main
Last change on this file was d24f17c, checked in by Aleksandar Panovski <apano77@…>, 15 months ago

Initial commit

  • Property mode set to 100644
File size: 17.1 KB
Line 
1'use strict';
2
3import bind from './helpers/bind.js';
4
5// utils is a library of generic helper functions non-specific to axios
6
7const {toString} = Object.prototype;
8const {getPrototypeOf} = Object;
9
10const kindOf = (cache => thing => {
11 const str = toString.call(thing);
12 return cache[str] || (cache[str] = str.slice(8, -1).toLowerCase());
13})(Object.create(null));
14
15const kindOfTest = (type) => {
16 type = type.toLowerCase();
17 return (thing) => kindOf(thing) === type
18}
19
20const typeOfTest = type => thing => typeof thing === type;
21
22/**
23 * Determine if a value is an Array
24 *
25 * @param {Object} val The value to test
26 *
27 * @returns {boolean} True if value is an Array, otherwise false
28 */
29const {isArray} = Array;
30
31/**
32 * Determine if a value is undefined
33 *
34 * @param {*} val The value to test
35 *
36 * @returns {boolean} True if the value is undefined, otherwise false
37 */
38const isUndefined = typeOfTest('undefined');
39
40/**
41 * Determine if a value is a Buffer
42 *
43 * @param {*} val The value to test
44 *
45 * @returns {boolean} True if value is a Buffer, otherwise false
46 */
47function isBuffer(val) {
48 return val !== null && !isUndefined(val) && val.constructor !== null && !isUndefined(val.constructor)
49 && isFunction(val.constructor.isBuffer) && val.constructor.isBuffer(val);
50}
51
52/**
53 * Determine if a value is an ArrayBuffer
54 *
55 * @param {*} val The value to test
56 *
57 * @returns {boolean} True if value is an ArrayBuffer, otherwise false
58 */
59const isArrayBuffer = kindOfTest('ArrayBuffer');
60
61
62/**
63 * Determine if a value is a view on an ArrayBuffer
64 *
65 * @param {*} val The value to test
66 *
67 * @returns {boolean} True if value is a view on an ArrayBuffer, otherwise false
68 */
69function isArrayBufferView(val) {
70 let result;
71 if ((typeof ArrayBuffer !== 'undefined') && (ArrayBuffer.isView)) {
72 result = ArrayBuffer.isView(val);
73 } else {
74 result = (val) && (val.buffer) && (isArrayBuffer(val.buffer));
75 }
76 return result;
77}
78
79/**
80 * Determine if a value is a String
81 *
82 * @param {*} val The value to test
83 *
84 * @returns {boolean} True if value is a String, otherwise false
85 */
86const isString = typeOfTest('string');
87
88/**
89 * Determine if a value is a Function
90 *
91 * @param {*} val The value to test
92 * @returns {boolean} True if value is a Function, otherwise false
93 */
94const isFunction = typeOfTest('function');
95
96/**
97 * Determine if a value is a Number
98 *
99 * @param {*} val The value to test
100 *
101 * @returns {boolean} True if value is a Number, otherwise false
102 */
103const isNumber = typeOfTest('number');
104
105/**
106 * Determine if a value is an Object
107 *
108 * @param {*} thing The value to test
109 *
110 * @returns {boolean} True if value is an Object, otherwise false
111 */
112const isObject = (thing) => thing !== null && typeof thing === 'object';
113
114/**
115 * Determine if a value is a Boolean
116 *
117 * @param {*} thing The value to test
118 * @returns {boolean} True if value is a Boolean, otherwise false
119 */
120const isBoolean = thing => thing === true || thing === false;
121
122/**
123 * Determine if a value is a plain Object
124 *
125 * @param {*} val The value to test
126 *
127 * @returns {boolean} True if value is a plain Object, otherwise false
128 */
129const isPlainObject = (val) => {
130 if (kindOf(val) !== 'object') {
131 return false;
132 }
133
134 const prototype = getPrototypeOf(val);
135 return (prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null) && !(Symbol.toStringTag in val) && !(Symbol.iterator in val);
136}
137
138/**
139 * Determine if a value is a Date
140 *
141 * @param {*} val The value to test
142 *
143 * @returns {boolean} True if value is a Date, otherwise false
144 */
145const isDate = kindOfTest('Date');
146
147/**
148 * Determine if a value is a File
149 *
150 * @param {*} val The value to test
151 *
152 * @returns {boolean} True if value is a File, otherwise false
153 */
154const isFile = kindOfTest('File');
155
156/**
157 * Determine if a value is a Blob
158 *
159 * @param {*} val The value to test
160 *
161 * @returns {boolean} True if value is a Blob, otherwise false
162 */
163const isBlob = kindOfTest('Blob');
164
165/**
166 * Determine if a value is a FileList
167 *
168 * @param {*} val The value to test
169 *
170 * @returns {boolean} True if value is a File, otherwise false
171 */
172const isFileList = kindOfTest('FileList');
173
174/**
175 * Determine if a value is a Stream
176 *
177 * @param {*} val The value to test
178 *
179 * @returns {boolean} True if value is a Stream, otherwise false
180 */
181const isStream = (val) => isObject(val) && isFunction(val.pipe);
182
183/**
184 * Determine if a value is a FormData
185 *
186 * @param {*} thing The value to test
187 *
188 * @returns {boolean} True if value is an FormData, otherwise false
189 */
190const isFormData = (thing) => {
191 let kind;
192 return thing && (
193 (typeof FormData === 'function' && thing instanceof FormData) || (
194 isFunction(thing.append) && (
195 (kind = kindOf(thing)) === 'formdata' ||
196 // detect form-data instance
197 (kind === 'object' && isFunction(thing.toString) && thing.toString() === '[object FormData]')
198 )
199 )
200 )
201}
202
203/**
204 * Determine if a value is a URLSearchParams object
205 *
206 * @param {*} val The value to test
207 *
208 * @returns {boolean} True if value is a URLSearchParams object, otherwise false
209 */
210const isURLSearchParams = kindOfTest('URLSearchParams');
211
212/**
213 * Trim excess whitespace off the beginning and end of a string
214 *
215 * @param {String} str The String to trim
216 *
217 * @returns {String} The String freed of excess whitespace
218 */
219const trim = (str) => str.trim ?
220 str.trim() : str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
221
222/**
223 * Iterate over an Array or an Object invoking a function for each item.
224 *
225 * If `obj` is an Array callback will be called passing
226 * the value, index, and complete array for each item.
227 *
228 * If 'obj' is an Object callback will be called passing
229 * the value, key, and complete object for each property.
230 *
231 * @param {Object|Array} obj The object to iterate
232 * @param {Function} fn The callback to invoke for each item
233 *
234 * @param {Boolean} [allOwnKeys = false]
235 * @returns {any}
236 */
237function forEach(obj, fn, {allOwnKeys = false} = {}) {
238 // Don't bother if no value provided
239 if (obj === null || typeof obj === 'undefined') {
240 return;
241 }
242
243 let i;
244 let l;
245
246 // Force an array if not already something iterable
247 if (typeof obj !== 'object') {
248 /*eslint no-param-reassign:0*/
249 obj = [obj];
250 }
251
252 if (isArray(obj)) {
253 // Iterate over array values
254 for (i = 0, l = obj.length; i < l; i++) {
255 fn.call(null, obj[i], i, obj);
256 }
257 } else {
258 // Iterate over object keys
259 const keys = allOwnKeys ? Object.getOwnPropertyNames(obj) : Object.keys(obj);
260 const len = keys.length;
261 let key;
262
263 for (i = 0; i < len; i++) {
264 key = keys[i];
265 fn.call(null, obj[key], key, obj);
266 }
267 }
268}
269
270function findKey(obj, key) {
271 key = key.toLowerCase();
272 const keys = Object.keys(obj);
273 let i = keys.length;
274 let _key;
275 while (i-- > 0) {
276 _key = keys[i];
277 if (key === _key.toLowerCase()) {
278 return _key;
279 }
280 }
281 return null;
282}
283
284const _global = (() => {
285 /*eslint no-undef:0*/
286 if (typeof globalThis !== "undefined") return globalThis;
287 return typeof self !== "undefined" ? self : (typeof window !== 'undefined' ? window : global)
288})();
289
290const isContextDefined = (context) => !isUndefined(context) && context !== _global;
291
292/**
293 * Accepts varargs expecting each argument to be an object, then
294 * immutably merges the properties of each object and returns result.
295 *
296 * When multiple objects contain the same key the later object in
297 * the arguments list will take precedence.
298 *
299 * Example:
300 *
301 * ```js
302 * var result = merge({foo: 123}, {foo: 456});
303 * console.log(result.foo); // outputs 456
304 * ```
305 *
306 * @param {Object} obj1 Object to merge
307 *
308 * @returns {Object} Result of all merge properties
309 */
310function merge(/* obj1, obj2, obj3, ... */) {
311 const {caseless} = isContextDefined(this) && this || {};
312 const result = {};
313 const assignValue = (val, key) => {
314 const targetKey = caseless && findKey(result, key) || key;
315 if (isPlainObject(result[targetKey]) && isPlainObject(val)) {
316 result[targetKey] = merge(result[targetKey], val);
317 } else if (isPlainObject(val)) {
318 result[targetKey] = merge({}, val);
319 } else if (isArray(val)) {
320 result[targetKey] = val.slice();
321 } else {
322 result[targetKey] = val;
323 }
324 }
325
326 for (let i = 0, l = arguments.length; i < l; i++) {
327 arguments[i] && forEach(arguments[i], assignValue);
328 }
329 return result;
330}
331
332/**
333 * Extends object a by mutably adding to it the properties of object b.
334 *
335 * @param {Object} a The object to be extended
336 * @param {Object} b The object to copy properties from
337 * @param {Object} thisArg The object to bind function to
338 *
339 * @param {Boolean} [allOwnKeys]
340 * @returns {Object} The resulting value of object a
341 */
342const extend = (a, b, thisArg, {allOwnKeys}= {}) => {
343 forEach(b, (val, key) => {
344 if (thisArg && isFunction(val)) {
345 a[key] = bind(val, thisArg);
346 } else {
347 a[key] = val;
348 }
349 }, {allOwnKeys});
350 return a;
351}
352
353/**
354 * Remove byte order marker. This catches EF BB BF (the UTF-8 BOM)
355 *
356 * @param {string} content with BOM
357 *
358 * @returns {string} content value without BOM
359 */
360const stripBOM = (content) => {
361 if (content.charCodeAt(0) === 0xFEFF) {
362 content = content.slice(1);
363 }
364 return content;
365}
366
367/**
368 * Inherit the prototype methods from one constructor into another
369 * @param {function} constructor
370 * @param {function} superConstructor
371 * @param {object} [props]
372 * @param {object} [descriptors]
373 *
374 * @returns {void}
375 */
376const inherits = (constructor, superConstructor, props, descriptors) => {
377 constructor.prototype = Object.create(superConstructor.prototype, descriptors);
378 constructor.prototype.constructor = constructor;
379 Object.defineProperty(constructor, 'super', {
380 value: superConstructor.prototype
381 });
382 props && Object.assign(constructor.prototype, props);
383}
384
385/**
386 * Resolve object with deep prototype chain to a flat object
387 * @param {Object} sourceObj source object
388 * @param {Object} [destObj]
389 * @param {Function|Boolean} [filter]
390 * @param {Function} [propFilter]
391 *
392 * @returns {Object}
393 */
394const toFlatObject = (sourceObj, destObj, filter, propFilter) => {
395 let props;
396 let i;
397 let prop;
398 const merged = {};
399
400 destObj = destObj || {};
401 // eslint-disable-next-line no-eq-null,eqeqeq
402 if (sourceObj == null) return destObj;
403
404 do {
405 props = Object.getOwnPropertyNames(sourceObj);
406 i = props.length;
407 while (i-- > 0) {
408 prop = props[i];
409 if ((!propFilter || propFilter(prop, sourceObj, destObj)) && !merged[prop]) {
410 destObj[prop] = sourceObj[prop];
411 merged[prop] = true;
412 }
413 }
414 sourceObj = filter !== false && getPrototypeOf(sourceObj);
415 } while (sourceObj && (!filter || filter(sourceObj, destObj)) && sourceObj !== Object.prototype);
416
417 return destObj;
418}
419
420/**
421 * Determines whether a string ends with the characters of a specified string
422 *
423 * @param {String} str
424 * @param {String} searchString
425 * @param {Number} [position= 0]
426 *
427 * @returns {boolean}
428 */
429const endsWith = (str, searchString, position) => {
430 str = String(str);
431 if (position === undefined || position > str.length) {
432 position = str.length;
433 }
434 position -= searchString.length;
435 const lastIndex = str.indexOf(searchString, position);
436 return lastIndex !== -1 && lastIndex === position;
437}
438
439
440/**
441 * Returns new array from array like object or null if failed
442 *
443 * @param {*} [thing]
444 *
445 * @returns {?Array}
446 */
447const toArray = (thing) => {
448 if (!thing) return null;
449 if (isArray(thing)) return thing;
450 let i = thing.length;
451 if (!isNumber(i)) return null;
452 const arr = new Array(i);
453 while (i-- > 0) {
454 arr[i] = thing[i];
455 }
456 return arr;
457}
458
459/**
460 * Checking if the Uint8Array exists and if it does, it returns a function that checks if the
461 * thing passed in is an instance of Uint8Array
462 *
463 * @param {TypedArray}
464 *
465 * @returns {Array}
466 */
467// eslint-disable-next-line func-names
468const isTypedArray = (TypedArray => {
469 // eslint-disable-next-line func-names
470 return thing => {
471 return TypedArray && thing instanceof TypedArray;
472 };
473})(typeof Uint8Array !== 'undefined' && getPrototypeOf(Uint8Array));
474
475/**
476 * For each entry in the object, call the function with the key and value.
477 *
478 * @param {Object<any, any>} obj - The object to iterate over.
479 * @param {Function} fn - The function to call for each entry.
480 *
481 * @returns {void}
482 */
483const forEachEntry = (obj, fn) => {
484 const generator = obj && obj[Symbol.iterator];
485
486 const iterator = generator.call(obj);
487
488 let result;
489
490 while ((result = iterator.next()) && !result.done) {
491 const pair = result.value;
492 fn.call(obj, pair[0], pair[1]);
493 }
494}
495
496/**
497 * It takes a regular expression and a string, and returns an array of all the matches
498 *
499 * @param {string} regExp - The regular expression to match against.
500 * @param {string} str - The string to search.
501 *
502 * @returns {Array<boolean>}
503 */
504const matchAll = (regExp, str) => {
505 let matches;
506 const arr = [];
507
508 while ((matches = regExp.exec(str)) !== null) {
509 arr.push(matches);
510 }
511
512 return arr;
513}
514
515/* Checking if the kindOfTest function returns true when passed an HTMLFormElement. */
516const isHTMLForm = kindOfTest('HTMLFormElement');
517
518const toCamelCase = str => {
519 return str.toLowerCase().replace(/[-_\s]([a-z\d])(\w*)/g,
520 function replacer(m, p1, p2) {
521 return p1.toUpperCase() + p2;
522 }
523 );
524};
525
526/* Creating a function that will check if an object has a property. */
527const hasOwnProperty = (({hasOwnProperty}) => (obj, prop) => hasOwnProperty.call(obj, prop))(Object.prototype);
528
529/**
530 * Determine if a value is a RegExp object
531 *
532 * @param {*} val The value to test
533 *
534 * @returns {boolean} True if value is a RegExp object, otherwise false
535 */
536const isRegExp = kindOfTest('RegExp');
537
538const reduceDescriptors = (obj, reducer) => {
539 const descriptors = Object.getOwnPropertyDescriptors(obj);
540 const reducedDescriptors = {};
541
542 forEach(descriptors, (descriptor, name) => {
543 let ret;
544 if ((ret = reducer(descriptor, name, obj)) !== false) {
545 reducedDescriptors[name] = ret || descriptor;
546 }
547 });
548
549 Object.defineProperties(obj, reducedDescriptors);
550}
551
552/**
553 * Makes all methods read-only
554 * @param {Object} obj
555 */
556
557const freezeMethods = (obj) => {
558 reduceDescriptors(obj, (descriptor, name) => {
559 // skip restricted props in strict mode
560 if (isFunction(obj) && ['arguments', 'caller', 'callee'].indexOf(name) !== -1) {
561 return false;
562 }
563
564 const value = obj[name];
565
566 if (!isFunction(value)) return;
567
568 descriptor.enumerable = false;
569
570 if ('writable' in descriptor) {
571 descriptor.writable = false;
572 return;
573 }
574
575 if (!descriptor.set) {
576 descriptor.set = () => {
577 throw Error('Can not rewrite read-only method \'' + name + '\'');
578 };
579 }
580 });
581}
582
583const toObjectSet = (arrayOrString, delimiter) => {
584 const obj = {};
585
586 const define = (arr) => {
587 arr.forEach(value => {
588 obj[value] = true;
589 });
590 }
591
592 isArray(arrayOrString) ? define(arrayOrString) : define(String(arrayOrString).split(delimiter));
593
594 return obj;
595}
596
597const noop = () => {}
598
599const toFiniteNumber = (value, defaultValue) => {
600 value = +value;
601 return Number.isFinite(value) ? value : defaultValue;
602}
603
604const ALPHA = 'abcdefghijklmnopqrstuvwxyz'
605
606const DIGIT = '0123456789';
607
608const ALPHABET = {
609 DIGIT,
610 ALPHA,
611 ALPHA_DIGIT: ALPHA + ALPHA.toUpperCase() + DIGIT
612}
613
614const generateString = (size = 16, alphabet = ALPHABET.ALPHA_DIGIT) => {
615 let str = '';
616 const {length} = alphabet;
617 while (size--) {
618 str += alphabet[Math.random() * length|0]
619 }
620
621 return str;
622}
623
624/**
625 * If the thing is a FormData object, return true, otherwise return false.
626 *
627 * @param {unknown} thing - The thing to check.
628 *
629 * @returns {boolean}
630 */
631function isSpecCompliantForm(thing) {
632 return !!(thing && isFunction(thing.append) && thing[Symbol.toStringTag] === 'FormData' && thing[Symbol.iterator]);
633}
634
635const toJSONObject = (obj) => {
636 const stack = new Array(10);
637
638 const visit = (source, i) => {
639
640 if (isObject(source)) {
641 if (stack.indexOf(source) >= 0) {
642 return;
643 }
644
645 if(!('toJSON' in source)) {
646 stack[i] = source;
647 const target = isArray(source) ? [] : {};
648
649 forEach(source, (value, key) => {
650 const reducedValue = visit(value, i + 1);
651 !isUndefined(reducedValue) && (target[key] = reducedValue);
652 });
653
654 stack[i] = undefined;
655
656 return target;
657 }
658 }
659
660 return source;
661 }
662
663 return visit(obj, 0);
664}
665
666const isAsyncFn = kindOfTest('AsyncFunction');
667
668const isThenable = (thing) =>
669 thing && (isObject(thing) || isFunction(thing)) && isFunction(thing.then) && isFunction(thing.catch);
670
671export default {
672 isArray,
673 isArrayBuffer,
674 isBuffer,
675 isFormData,
676 isArrayBufferView,
677 isString,
678 isNumber,
679 isBoolean,
680 isObject,
681 isPlainObject,
682 isUndefined,
683 isDate,
684 isFile,
685 isBlob,
686 isRegExp,
687 isFunction,
688 isStream,
689 isURLSearchParams,
690 isTypedArray,
691 isFileList,
692 forEach,
693 merge,
694 extend,
695 trim,
696 stripBOM,
697 inherits,
698 toFlatObject,
699 kindOf,
700 kindOfTest,
701 endsWith,
702 toArray,
703 forEachEntry,
704 matchAll,
705 isHTMLForm,
706 hasOwnProperty,
707 hasOwnProp: hasOwnProperty, // an alias to avoid ESLint no-prototype-builtins detection
708 reduceDescriptors,
709 freezeMethods,
710 toObjectSet,
711 toCamelCase,
712 noop,
713 toFiniteNumber,
714 findKey,
715 global: _global,
716 isContextDefined,
717 ALPHABET,
718 generateString,
719 isSpecCompliantForm,
720 toJSONObject,
721 isAsyncFn,
722 isThenable
723};
Note: See TracBrowser for help on using the repository browser.