source: node_modules/axios/lib/utils.js@ ff72ad2

Last change on this file since ff72ad2 was ff72ad2, checked in by ste08 <sjovanoska@…>, 2 months ago

Adding review works\!

  • Property mode set to 100644
File size: 17.8 KB
RevLine 
[57e58a3]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
212const [isReadableStream, isRequest, isResponse, isHeaders] = ['ReadableStream', 'Request', 'Response', 'Headers'].map(kindOfTest);
213
214/**
215 * Trim excess whitespace off the beginning and end of a string
216 *
217 * @param {String} str The String to trim
218 *
219 * @returns {String} The String freed of excess whitespace
220 */
221const trim = (str) => str.trim ?
222 str.trim() : str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
223
224/**
225 * Iterate over an Array or an Object invoking a function for each item.
226 *
227 * If `obj` is an Array callback will be called passing
228 * the value, index, and complete array for each item.
229 *
230 * If 'obj' is an Object callback will be called passing
231 * the value, key, and complete object for each property.
232 *
233 * @param {Object|Array} obj The object to iterate
234 * @param {Function} fn The callback to invoke for each item
235 *
236 * @param {Boolean} [allOwnKeys = false]
237 * @returns {any}
238 */
239function forEach(obj, fn, {allOwnKeys = false} = {}) {
240 // Don't bother if no value provided
241 if (obj === null || typeof obj === 'undefined') {
242 return;
243 }
244
245 let i;
246 let l;
247
248 // Force an array if not already something iterable
249 if (typeof obj !== 'object') {
250 /*eslint no-param-reassign:0*/
251 obj = [obj];
252 }
253
254 if (isArray(obj)) {
255 // Iterate over array values
256 for (i = 0, l = obj.length; i < l; i++) {
257 fn.call(null, obj[i], i, obj);
258 }
259 } else {
260 // Iterate over object keys
261 const keys = allOwnKeys ? Object.getOwnPropertyNames(obj) : Object.keys(obj);
262 const len = keys.length;
263 let key;
264
265 for (i = 0; i < len; i++) {
266 key = keys[i];
267 fn.call(null, obj[key], key, obj);
268 }
269 }
270}
271
272function findKey(obj, key) {
273 key = key.toLowerCase();
274 const keys = Object.keys(obj);
275 let i = keys.length;
276 let _key;
277 while (i-- > 0) {
278 _key = keys[i];
279 if (key === _key.toLowerCase()) {
280 return _key;
281 }
282 }
283 return null;
284}
285
286const _global = (() => {
287 /*eslint no-undef:0*/
288 if (typeof globalThis !== "undefined") return globalThis;
289 return typeof self !== "undefined" ? self : (typeof window !== 'undefined' ? window : global)
290})();
291
292const isContextDefined = (context) => !isUndefined(context) && context !== _global;
293
294/**
295 * Accepts varargs expecting each argument to be an object, then
296 * immutably merges the properties of each object and returns result.
297 *
298 * When multiple objects contain the same key the later object in
299 * the arguments list will take precedence.
300 *
301 * Example:
302 *
303 * ```js
304 * var result = merge({foo: 123}, {foo: 456});
305 * console.log(result.foo); // outputs 456
306 * ```
307 *
308 * @param {Object} obj1 Object to merge
309 *
310 * @returns {Object} Result of all merge properties
311 */
312function merge(/* obj1, obj2, obj3, ... */) {
313 const {caseless} = isContextDefined(this) && this || {};
314 const result = {};
315 const assignValue = (val, key) => {
316 const targetKey = caseless && findKey(result, key) || key;
317 if (isPlainObject(result[targetKey]) && isPlainObject(val)) {
318 result[targetKey] = merge(result[targetKey], val);
319 } else if (isPlainObject(val)) {
320 result[targetKey] = merge({}, val);
321 } else if (isArray(val)) {
322 result[targetKey] = val.slice();
323 } else {
324 result[targetKey] = val;
325 }
326 }
327
328 for (let i = 0, l = arguments.length; i < l; i++) {
329 arguments[i] && forEach(arguments[i], assignValue);
330 }
331 return result;
332}
333
334/**
335 * Extends object a by mutably adding to it the properties of object b.
336 *
337 * @param {Object} a The object to be extended
338 * @param {Object} b The object to copy properties from
339 * @param {Object} thisArg The object to bind function to
340 *
341 * @param {Boolean} [allOwnKeys]
342 * @returns {Object} The resulting value of object a
343 */
344const extend = (a, b, thisArg, {allOwnKeys}= {}) => {
345 forEach(b, (val, key) => {
346 if (thisArg && isFunction(val)) {
347 a[key] = bind(val, thisArg);
348 } else {
349 a[key] = val;
350 }
351 }, {allOwnKeys});
352 return a;
353}
354
355/**
356 * Remove byte order marker. This catches EF BB BF (the UTF-8 BOM)
357 *
358 * @param {string} content with BOM
359 *
360 * @returns {string} content value without BOM
361 */
362const stripBOM = (content) => {
363 if (content.charCodeAt(0) === 0xFEFF) {
364 content = content.slice(1);
365 }
366 return content;
367}
368
369/**
370 * Inherit the prototype methods from one constructor into another
371 * @param {function} constructor
372 * @param {function} superConstructor
373 * @param {object} [props]
374 * @param {object} [descriptors]
375 *
376 * @returns {void}
377 */
378const inherits = (constructor, superConstructor, props, descriptors) => {
379 constructor.prototype = Object.create(superConstructor.prototype, descriptors);
380 constructor.prototype.constructor = constructor;
381 Object.defineProperty(constructor, 'super', {
382 value: superConstructor.prototype
383 });
384 props && Object.assign(constructor.prototype, props);
385}
386
387/**
388 * Resolve object with deep prototype chain to a flat object
389 * @param {Object} sourceObj source object
390 * @param {Object} [destObj]
391 * @param {Function|Boolean} [filter]
392 * @param {Function} [propFilter]
393 *
394 * @returns {Object}
395 */
396const toFlatObject = (sourceObj, destObj, filter, propFilter) => {
397 let props;
398 let i;
399 let prop;
400 const merged = {};
401
402 destObj = destObj || {};
403 // eslint-disable-next-line no-eq-null,eqeqeq
404 if (sourceObj == null) return destObj;
405
406 do {
407 props = Object.getOwnPropertyNames(sourceObj);
408 i = props.length;
409 while (i-- > 0) {
410 prop = props[i];
411 if ((!propFilter || propFilter(prop, sourceObj, destObj)) && !merged[prop]) {
412 destObj[prop] = sourceObj[prop];
413 merged[prop] = true;
414 }
415 }
416 sourceObj = filter !== false && getPrototypeOf(sourceObj);
417 } while (sourceObj && (!filter || filter(sourceObj, destObj)) && sourceObj !== Object.prototype);
418
419 return destObj;
420}
421
422/**
423 * Determines whether a string ends with the characters of a specified string
424 *
425 * @param {String} str
426 * @param {String} searchString
427 * @param {Number} [position= 0]
428 *
429 * @returns {boolean}
430 */
431const endsWith = (str, searchString, position) => {
432 str = String(str);
433 if (position === undefined || position > str.length) {
434 position = str.length;
435 }
436 position -= searchString.length;
437 const lastIndex = str.indexOf(searchString, position);
438 return lastIndex !== -1 && lastIndex === position;
439}
440
441
442/**
443 * Returns new array from array like object or null if failed
444 *
445 * @param {*} [thing]
446 *
447 * @returns {?Array}
448 */
449const toArray = (thing) => {
450 if (!thing) return null;
451 if (isArray(thing)) return thing;
452 let i = thing.length;
453 if (!isNumber(i)) return null;
454 const arr = new Array(i);
455 while (i-- > 0) {
456 arr[i] = thing[i];
457 }
458 return arr;
459}
460
461/**
462 * Checking if the Uint8Array exists and if it does, it returns a function that checks if the
463 * thing passed in is an instance of Uint8Array
464 *
465 * @param {TypedArray}
466 *
467 * @returns {Array}
468 */
469// eslint-disable-next-line func-names
470const isTypedArray = (TypedArray => {
471 // eslint-disable-next-line func-names
472 return thing => {
473 return TypedArray && thing instanceof TypedArray;
474 };
475})(typeof Uint8Array !== 'undefined' && getPrototypeOf(Uint8Array));
476
477/**
478 * For each entry in the object, call the function with the key and value.
479 *
480 * @param {Object<any, any>} obj - The object to iterate over.
481 * @param {Function} fn - The function to call for each entry.
482 *
483 * @returns {void}
484 */
485const forEachEntry = (obj, fn) => {
486 const generator = obj && obj[Symbol.iterator];
487
488 const iterator = generator.call(obj);
489
490 let result;
491
492 while ((result = iterator.next()) && !result.done) {
493 const pair = result.value;
494 fn.call(obj, pair[0], pair[1]);
495 }
496}
497
498/**
499 * It takes a regular expression and a string, and returns an array of all the matches
500 *
501 * @param {string} regExp - The regular expression to match against.
502 * @param {string} str - The string to search.
503 *
504 * @returns {Array<boolean>}
505 */
506const matchAll = (regExp, str) => {
507 let matches;
508 const arr = [];
509
510 while ((matches = regExp.exec(str)) !== null) {
511 arr.push(matches);
512 }
513
514 return arr;
515}
516
517/* Checking if the kindOfTest function returns true when passed an HTMLFormElement. */
518const isHTMLForm = kindOfTest('HTMLFormElement');
519
520const toCamelCase = str => {
521 return str.toLowerCase().replace(/[-_\s]([a-z\d])(\w*)/g,
522 function replacer(m, p1, p2) {
523 return p1.toUpperCase() + p2;
524 }
525 );
526};
527
528/* Creating a function that will check if an object has a property. */
529const hasOwnProperty = (({hasOwnProperty}) => (obj, prop) => hasOwnProperty.call(obj, prop))(Object.prototype);
530
531/**
532 * Determine if a value is a RegExp object
533 *
534 * @param {*} val The value to test
535 *
536 * @returns {boolean} True if value is a RegExp object, otherwise false
537 */
538const isRegExp = kindOfTest('RegExp');
539
540const reduceDescriptors = (obj, reducer) => {
541 const descriptors = Object.getOwnPropertyDescriptors(obj);
542 const reducedDescriptors = {};
543
544 forEach(descriptors, (descriptor, name) => {
545 let ret;
546 if ((ret = reducer(descriptor, name, obj)) !== false) {
547 reducedDescriptors[name] = ret || descriptor;
548 }
549 });
550
551 Object.defineProperties(obj, reducedDescriptors);
552}
553
554/**
555 * Makes all methods read-only
556 * @param {Object} obj
557 */
558
559const freezeMethods = (obj) => {
560 reduceDescriptors(obj, (descriptor, name) => {
561 // skip restricted props in strict mode
562 if (isFunction(obj) && ['arguments', 'caller', 'callee'].indexOf(name) !== -1) {
563 return false;
564 }
565
566 const value = obj[name];
567
568 if (!isFunction(value)) return;
569
570 descriptor.enumerable = false;
571
572 if ('writable' in descriptor) {
573 descriptor.writable = false;
574 return;
575 }
576
577 if (!descriptor.set) {
578 descriptor.set = () => {
579 throw Error('Can not rewrite read-only method \'' + name + '\'');
580 };
581 }
582 });
583}
584
585const toObjectSet = (arrayOrString, delimiter) => {
586 const obj = {};
587
588 const define = (arr) => {
589 arr.forEach(value => {
590 obj[value] = true;
591 });
592 }
593
594 isArray(arrayOrString) ? define(arrayOrString) : define(String(arrayOrString).split(delimiter));
595
596 return obj;
597}
598
599const noop = () => {}
600
601const toFiniteNumber = (value, defaultValue) => {
602 return value != null && Number.isFinite(value = +value) ? value : defaultValue;
603}
604
605/**
606 * If the thing is a FormData object, return true, otherwise return false.
607 *
608 * @param {unknown} thing - The thing to check.
609 *
610 * @returns {boolean}
611 */
612function isSpecCompliantForm(thing) {
613 return !!(thing && isFunction(thing.append) && thing[Symbol.toStringTag] === 'FormData' && thing[Symbol.iterator]);
614}
615
616const toJSONObject = (obj) => {
617 const stack = new Array(10);
618
619 const visit = (source, i) => {
620
621 if (isObject(source)) {
622 if (stack.indexOf(source) >= 0) {
623 return;
624 }
625
626 if(!('toJSON' in source)) {
627 stack[i] = source;
628 const target = isArray(source) ? [] : {};
629
630 forEach(source, (value, key) => {
631 const reducedValue = visit(value, i + 1);
632 !isUndefined(reducedValue) && (target[key] = reducedValue);
633 });
634
635 stack[i] = undefined;
636
637 return target;
638 }
639 }
640
641 return source;
642 }
643
644 return visit(obj, 0);
645}
646
647const isAsyncFn = kindOfTest('AsyncFunction');
648
649const isThenable = (thing) =>
650 thing && (isObject(thing) || isFunction(thing)) && isFunction(thing.then) && isFunction(thing.catch);
651
652// original code
653// https://github.com/DigitalBrainJS/AxiosPromise/blob/16deab13710ec09779922131f3fa5954320f83ab/lib/utils.js#L11-L34
654
655const _setImmediate = ((setImmediateSupported, postMessageSupported) => {
656 if (setImmediateSupported) {
657 return setImmediate;
658 }
659
660 return postMessageSupported ? ((token, callbacks) => {
661 _global.addEventListener("message", ({source, data}) => {
662 if (source === _global && data === token) {
663 callbacks.length && callbacks.shift()();
664 }
665 }, false);
666
667 return (cb) => {
668 callbacks.push(cb);
669 _global.postMessage(token, "*");
670 }
671 })(`axios@${Math.random()}`, []) : (cb) => setTimeout(cb);
672})(
673 typeof setImmediate === 'function',
674 isFunction(_global.postMessage)
675);
676
677const asap = typeof queueMicrotask !== 'undefined' ?
678 queueMicrotask.bind(_global) : ( typeof process !== 'undefined' && process.nextTick || _setImmediate);
679
680// *********************
681
682export default {
683 isArray,
684 isArrayBuffer,
685 isBuffer,
686 isFormData,
687 isArrayBufferView,
688 isString,
689 isNumber,
690 isBoolean,
691 isObject,
692 isPlainObject,
693 isReadableStream,
694 isRequest,
695 isResponse,
696 isHeaders,
697 isUndefined,
698 isDate,
699 isFile,
700 isBlob,
701 isRegExp,
702 isFunction,
703 isStream,
704 isURLSearchParams,
705 isTypedArray,
706 isFileList,
707 forEach,
708 merge,
709 extend,
710 trim,
711 stripBOM,
712 inherits,
713 toFlatObject,
714 kindOf,
715 kindOfTest,
716 endsWith,
717 toArray,
718 forEachEntry,
719 matchAll,
720 isHTMLForm,
721 hasOwnProperty,
722 hasOwnProp: hasOwnProperty, // an alias to avoid ESLint no-prototype-builtins detection
723 reduceDescriptors,
724 freezeMethods,
725 toObjectSet,
726 toCamelCase,
727 noop,
728 toFiniteNumber,
729 findKey,
730 global: _global,
731 isContextDefined,
732 isSpecCompliantForm,
733 toJSONObject,
734 isAsyncFn,
735 isThenable,
736 setImmediate: _setImmediate,
737 asap
738};
Note: See TracBrowser for help on using the repository browser.