source: imaps-frontend/node_modules/axios/lib/helpers/toFormData.js@ d565449

main
Last change on this file since d565449 was d565449, checked in by stefan toskovski <stefantoska84@…>, 4 weeks ago

Update repo after prototype presentation

  • Property mode set to 100644
File size: 5.9 KB
Line 
1'use strict';
2
3import utils from '../utils.js';
4import AxiosError from '../core/AxiosError.js';
5// temporary hotfix to avoid circular references until AxiosURLSearchParams is refactored
6import PlatformFormData from '../platform/node/classes/FormData.js';
7
8/**
9 * Determines if the given thing is a array or js object.
10 *
11 * @param {string} thing - The object or array to be visited.
12 *
13 * @returns {boolean}
14 */
15function isVisitable(thing) {
16 return utils.isPlainObject(thing) || utils.isArray(thing);
17}
18
19/**
20 * It removes the brackets from the end of a string
21 *
22 * @param {string} key - The key of the parameter.
23 *
24 * @returns {string} the key without the brackets.
25 */
26function removeBrackets(key) {
27 return utils.endsWith(key, '[]') ? key.slice(0, -2) : key;
28}
29
30/**
31 * It takes a path, a key, and a boolean, and returns a string
32 *
33 * @param {string} path - The path to the current key.
34 * @param {string} key - The key of the current object being iterated over.
35 * @param {string} dots - If true, the key will be rendered with dots instead of brackets.
36 *
37 * @returns {string} The path to the current key.
38 */
39function renderKey(path, key, dots) {
40 if (!path) return key;
41 return path.concat(key).map(function each(token, i) {
42 // eslint-disable-next-line no-param-reassign
43 token = removeBrackets(token);
44 return !dots && i ? '[' + token + ']' : token;
45 }).join(dots ? '.' : '');
46}
47
48/**
49 * If the array is an array and none of its elements are visitable, then it's a flat array.
50 *
51 * @param {Array<any>} arr - The array to check
52 *
53 * @returns {boolean}
54 */
55function isFlatArray(arr) {
56 return utils.isArray(arr) && !arr.some(isVisitable);
57}
58
59const predicates = utils.toFlatObject(utils, {}, null, function filter(prop) {
60 return /^is[A-Z]/.test(prop);
61});
62
63/**
64 * Convert a data object to FormData
65 *
66 * @param {Object} obj
67 * @param {?Object} [formData]
68 * @param {?Object} [options]
69 * @param {Function} [options.visitor]
70 * @param {Boolean} [options.metaTokens = true]
71 * @param {Boolean} [options.dots = false]
72 * @param {?Boolean} [options.indexes = false]
73 *
74 * @returns {Object}
75 **/
76
77/**
78 * It converts an object into a FormData object
79 *
80 * @param {Object<any, any>} obj - The object to convert to form data.
81 * @param {string} formData - The FormData object to append to.
82 * @param {Object<string, any>} options
83 *
84 * @returns
85 */
86function toFormData(obj, formData, options) {
87 if (!utils.isObject(obj)) {
88 throw new TypeError('target must be an object');
89 }
90
91 // eslint-disable-next-line no-param-reassign
92 formData = formData || new (PlatformFormData || FormData)();
93
94 // eslint-disable-next-line no-param-reassign
95 options = utils.toFlatObject(options, {
96 metaTokens: true,
97 dots: false,
98 indexes: false
99 }, false, function defined(option, source) {
100 // eslint-disable-next-line no-eq-null,eqeqeq
101 return !utils.isUndefined(source[option]);
102 });
103
104 const metaTokens = options.metaTokens;
105 // eslint-disable-next-line no-use-before-define
106 const visitor = options.visitor || defaultVisitor;
107 const dots = options.dots;
108 const indexes = options.indexes;
109 const _Blob = options.Blob || typeof Blob !== 'undefined' && Blob;
110 const useBlob = _Blob && utils.isSpecCompliantForm(formData);
111
112 if (!utils.isFunction(visitor)) {
113 throw new TypeError('visitor must be a function');
114 }
115
116 function convertValue(value) {
117 if (value === null) return '';
118
119 if (utils.isDate(value)) {
120 return value.toISOString();
121 }
122
123 if (!useBlob && utils.isBlob(value)) {
124 throw new AxiosError('Blob is not supported. Use a Buffer instead.');
125 }
126
127 if (utils.isArrayBuffer(value) || utils.isTypedArray(value)) {
128 return useBlob && typeof Blob === 'function' ? new Blob([value]) : Buffer.from(value);
129 }
130
131 return value;
132 }
133
134 /**
135 * Default visitor.
136 *
137 * @param {*} value
138 * @param {String|Number} key
139 * @param {Array<String|Number>} path
140 * @this {FormData}
141 *
142 * @returns {boolean} return true to visit the each prop of the value recursively
143 */
144 function defaultVisitor(value, key, path) {
145 let arr = value;
146
147 if (value && !path && typeof value === 'object') {
148 if (utils.endsWith(key, '{}')) {
149 // eslint-disable-next-line no-param-reassign
150 key = metaTokens ? key : key.slice(0, -2);
151 // eslint-disable-next-line no-param-reassign
152 value = JSON.stringify(value);
153 } else if (
154 (utils.isArray(value) && isFlatArray(value)) ||
155 ((utils.isFileList(value) || utils.endsWith(key, '[]')) && (arr = utils.toArray(value))
156 )) {
157 // eslint-disable-next-line no-param-reassign
158 key = removeBrackets(key);
159
160 arr.forEach(function each(el, index) {
161 !(utils.isUndefined(el) || el === null) && formData.append(
162 // eslint-disable-next-line no-nested-ternary
163 indexes === true ? renderKey([key], index, dots) : (indexes === null ? key : key + '[]'),
164 convertValue(el)
165 );
166 });
167 return false;
168 }
169 }
170
171 if (isVisitable(value)) {
172 return true;
173 }
174
175 formData.append(renderKey(path, key, dots), convertValue(value));
176
177 return false;
178 }
179
180 const stack = [];
181
182 const exposedHelpers = Object.assign(predicates, {
183 defaultVisitor,
184 convertValue,
185 isVisitable
186 });
187
188 function build(value, path) {
189 if (utils.isUndefined(value)) return;
190
191 if (stack.indexOf(value) !== -1) {
192 throw Error('Circular reference detected in ' + path.join('.'));
193 }
194
195 stack.push(value);
196
197 utils.forEach(value, function each(el, key) {
198 const result = !(utils.isUndefined(el) || el === null) && visitor.call(
199 formData, el, utils.isString(key) ? key.trim() : key, path, exposedHelpers
200 );
201
202 if (result === true) {
203 build(el, path ? path.concat(key) : [key]);
204 }
205 });
206
207 stack.pop();
208 }
209
210 if (!utils.isObject(obj)) {
211 throw new TypeError('data must be an object');
212 }
213
214 build(obj);
215
216 return formData;
217}
218
219export default toFormData;
Note: See TracBrowser for help on using the repository browser.