qs 6.2.4 → 6.3.3

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.
package/.editorconfig CHANGED
@@ -39,7 +39,6 @@ max_line_length = off
39
39
 
40
40
  [dist/*]
41
41
  max_line_length = off
42
- insert_final_newline = off
43
42
 
44
43
  [.nycrc]
45
- indent_style = off
44
+ indent_style = tab
package/.eslintrc CHANGED
@@ -14,7 +14,6 @@
14
14
  "id-length": [2, { "min": 1, "max": 25, "properties": "never" }],
15
15
  "indent": [2, 4],
16
16
  "max-lines-per-function": 0,
17
- "max-lines": 0,
18
17
  "max-params": [2, 12],
19
18
  "max-statements": [2, 45],
20
19
  "multiline-comment-style": 0,
@@ -22,7 +21,6 @@
22
21
  "no-magic-numbers": 0,
23
22
  "no-param-reassign": 1,
24
23
  "no-restricted-syntax": [2, "BreakStatement", "DebuggerStatement", "ForInStatement", "LabeledStatement", "WithStatement"],
25
- "sort-keys": 0,
26
24
  },
27
25
 
28
26
  "overrides": [
package/CHANGELOG.md CHANGED
@@ -1,11 +1,14 @@
1
- ## **6.2.4**
1
+ ## **6.3.3**
2
2
  - [Fix] `parse`: ignore `__proto__` keys (#428)
3
+ - [Fix] fix for an impossible situation: when the formatter is called with a non-string value
3
4
  - [Fix] `utils.merge`: avoid a crash with a null target and an array source
4
- - [Fix] `utils.merge`: avoid a crash with a null target and a truthy non-array source
5
+ - [Fix]` `utils.merge`: avoid a crash with a null target and a truthy non-array source
6
+ - [Fix] `stringify`: fix a crash with `strictNullHandling` and a custom `filter`/`serializeDate` (#279)
5
7
  - [Fix] `utils`: `merge`: fix crash when `source` is a truthy primitive & no options are provided
6
8
  - [Fix] when `parseArrays` is false, properly handle keys ending in `[]`
7
9
  - [Robustness] `stringify`: avoid relying on a global `undefined` (#427)
8
10
  - [Refactor] use cached `Array.isArray`
11
+ - [Refactor] `stringify`: Avoid arr = arr.concat(...), push to the existing instance (#269)
9
12
  - [Docs] Clarify the need for "arrayLimit" option
10
13
  - [meta] fix README.md (#399)
11
14
  - [meta] Clean up license text so it’s properly detected as BSD-3-Clause
@@ -15,14 +18,38 @@
15
18
  - [Tests] remove nonexistent tape option
16
19
  - [Dev Deps] backport from main
17
20
 
18
- ## **6.2.3**
21
+ ## **6.3.2**
19
22
  - [Fix] follow `allowPrototypes` option during merge (#201, #200)
23
+ - [Dev Deps] update `eslint`
20
24
  - [Fix] chmod a-x
21
25
  - [Fix] support keys starting with brackets (#202, #200)
22
26
  - [Tests] up to `node` `v7.7`, `v6.10`,` v4.8`; disable osx builds since they block linux builds
23
27
 
24
- ## **6.2.2**
25
- - [Fix] ensure that `allowPrototypes: false` does not ever shadow Object.prototype properties
28
+ ## **6.3.1**
29
+ - [Fix] ensure that `allowPrototypes: false` does not ever shadow Object.prototype properties (thanks, @snyk!)
30
+ - [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `browserify`, `iconv-lite`, `qs-iconv`, `tape`
31
+ - [Tests] on all node minors; improve test matrix
32
+ - [Docs] document stringify option `allowDots` (#195)
33
+ - [Docs] add empty object and array values example (#195)
34
+ - [Docs] Fix minor inconsistency/typo (#192)
35
+ - [Docs] document stringify option `sort` (#191)
36
+ - [Refactor] `stringify`: throw faster with an invalid encoder
37
+ - [Refactor] remove unnecessary escapes (#184)
38
+ - Remove contributing.md, since `qs` is no longer part of `hapi` (#183)
39
+
40
+ ## **6.3.0**
41
+ - [New] Add support for RFC 1738 (#174, #173)
42
+ - [New] `stringify`: Add `serializeDate` option to customize Date serialization (#159)
43
+ - [Fix] ensure `utils.merge` handles merging two arrays
44
+ - [Refactor] only constructors should be capitalized
45
+ - [Refactor] capitalized var names are for constructors only
46
+ - [Refactor] avoid using a sparse array
47
+ - [Robustness] `formats`: cache `String#replace`
48
+ - [Dev Deps] update `browserify`, `eslint`, `@ljharb/eslint-config`; add `safe-publish-latest`
49
+ - [Tests] up to `node` `v6.8`, `v4.6`; improve test matrix
50
+ - [Tests] flesh out arrayLimit/arrayFormat tests (#107)
51
+ - [Tests] skip Object.create tests when null objects are not available
52
+ - [Tests] Turn on eslint for test files (#175)
26
53
 
27
54
  ## **6.2.1**
28
55
  - [Fix] ensure `key[]=x&key[]&key[]=y` results in 3, not 2, values
package/README.md CHANGED
@@ -39,11 +39,11 @@ assert.deepEqual(qs.parse('foo[bar]=baz'), {
39
39
  });
40
40
  ```
41
41
 
42
- When using the `plainObjects` option the parsed value is returned as a plain object, created via `Object.create(null)` and as such you should be aware that prototype methods will not exist on it and a user may set those names to whatever value they like:
42
+ When using the `plainObjects` option the parsed value is returned as a null object, created via `Object.create(null)` and as such you should be aware that prototype methods will not exist on it and a user may set those names to whatever value they like:
43
43
 
44
44
  ```javascript
45
- var plainObject = qs.parse('a[hasOwnProperty]=b', { plainObjects: true });
46
- assert.deepEqual(plainObject, { a: { hasOwnProperty: 'b' } });
45
+ var nullObject = qs.parse('a[hasOwnProperty]=b', { plainObjects: true });
46
+ assert.deepEqual(nullObject, { a: { hasOwnProperty: 'b' } });
47
47
  ```
48
48
 
49
49
  By default parameters that would overwrite properties on the object prototype are ignored, if you wish to keep the data from those fields either use `plainObjects` as mentioned above, or set `allowPrototypes` to `true` which will allow user input to overwrite those properties. *WARNING* It is generally a bad idea to enable this option as it can cause problems when attempting to use the properties that have been overwritten. Always be careful with this option.
@@ -285,7 +285,7 @@ qs.stringify({ a: ['b', 'c', 'd'] }, { indices: false });
285
285
  // 'a=b&a=c&a=d'
286
286
  ```
287
287
 
288
- You may use the `arrayFormat` option to specify the format of the output array
288
+ You may use the `arrayFormat` option to specify the format of the output array:
289
289
 
290
290
  ```javascript
291
291
  qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'indices' })
@@ -296,12 +296,36 @@ qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'repeat' })
296
296
  // 'a=b&a=c'
297
297
  ```
298
298
 
299
+ When objects are stringified, by default they use bracket notation:
300
+
301
+ ```javascript
302
+ qs.stringify({ a: { b: { c: 'd', e: 'f' } } });
303
+ // 'a[b][c]=d&a[b][e]=f'
304
+ ```
305
+
306
+ You may override this to use dot notation by setting the `allowDots` option to `true`:
307
+
308
+ ```javascript
309
+ qs.stringify({ a: { b: { c: 'd', e: 'f' } } }, { allowDots: true });
310
+ // 'a.b.c=d&a.b.e=f'
311
+ ```
312
+
299
313
  Empty strings and null values will omit the value, but the equals sign (=) remains in place:
300
314
 
301
315
  ```javascript
302
316
  assert.equal(qs.stringify({ a: '' }), 'a=');
303
317
  ```
304
318
 
319
+ Key with no values (such as an empty object or array) will return nothing:
320
+
321
+ ```javascript
322
+ assert.equal(qs.stringify({ a: [] }), '');
323
+ assert.equal(qs.stringify({ a: {} }), '');
324
+ assert.equal(qs.stringify({ a: [{}] }), '');
325
+ assert.equal(qs.stringify({ a: { b: []} }), '');
326
+ assert.equal(qs.stringify({ a: { b: {}} }), '');
327
+ ```
328
+
305
329
  Properties that are set to `undefined` will be omitted entirely:
306
330
 
307
331
  ```javascript
@@ -314,6 +338,26 @@ The delimiter may be overridden with stringify as well:
314
338
  assert.equal(qs.stringify({ a: 'b', c: 'd' }, { delimiter: ';' }), 'a=b;c=d');
315
339
  ```
316
340
 
341
+ If you only want to override the serialization of `Date` objects, you can provide a `serializeDate` option:
342
+
343
+ ```javascript
344
+ var date = new Date(7);
345
+ assert.equal(qs.stringify({ a: date }), 'a=1970-01-01T00:00:00.007Z'.replace(/:/g, '%3A'));
346
+ assert.equal(
347
+ qs.stringify({ a: date }, { serializeDate: function (d) { return d.getTime(); } }),
348
+ 'a=7'
349
+ );
350
+ ```
351
+
352
+ You may use the `sort` option to affect the order of parameter keys:
353
+
354
+ ```javascript
355
+ function alphabeticalSort(a, b) {
356
+ return a.localeCompare(b);
357
+ }
358
+ assert.equal(qs.stringify({ a: 'c', z: 'y', b : 'f' }, { sort: alphabeticalSort }), 'a=c&b=f&z=y');
359
+ ```
360
+
317
361
  Finally, you can use the `filter` option to restrict which keys will be included in the stringified output.
318
362
  If you pass a function, it will be called for each key to obtain the replacement value. Otherwise, if you
319
363
  pass an array, it will be used to select properties and array indices for stringification:
@@ -398,3 +442,14 @@ var decoder = require('qs-iconv/decoder')('shift_jis');
398
442
  var obj = qs.parse('a=%82%B1%82%F1%82%C9%82%BF%82%CD%81I', { decoder: decoder });
399
443
  assert.deepEqual(obj, { a: 'こんにちは!' });
400
444
  ```
445
+
446
+ ### RFC 3986 and RFC 1738 space encoding
447
+
448
+ RFC3986 used as default option and encodes ' ' to *%20* which is backward compatible.
449
+ In the same time, output can be stringified as per RFC1738 with ' ' equal to '+'.
450
+
451
+ ```
452
+ assert.equal(qs.stringify({ a: 'b c' }), 'a=b%20c');
453
+ assert.equal(qs.stringify({ a: 'b c' }, { format : 'RFC3986' }), 'a=b%20c');
454
+ assert.equal(qs.stringify({ a: 'b c' }, { format : 'RFC1738' }), 'a=b+c');
455
+ ```
package/component.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "qs",
3
3
  "repository": "hapijs/qs",
4
4
  "description": "query-string parser / stringifier with nesting support",
5
- "version": "6.2.4",
5
+ "version": "6.3.3",
6
6
  "keywords": ["querystring", "query", "parser"],
7
7
  "main": "lib/index.js",
8
8
  "scripts": [
package/dist/qs.js CHANGED
@@ -1,34 +1,56 @@
1
1
  (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Qs = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
2
2
  'use strict';
3
3
 
4
- var Stringify = require('./stringify');
5
- var Parse = require('./parse');
4
+ var replace = String.prototype.replace;
5
+ var percentTwenties = /%20/g;
6
6
 
7
7
  module.exports = {
8
- stringify: Stringify,
9
- parse: Parse
8
+ 'default': 'RFC3986',
9
+ formatters: {
10
+ RFC1738: function (value) {
11
+ return replace.call(value, percentTwenties, '+');
12
+ },
13
+ RFC3986: function (value) {
14
+ return String(value);
15
+ }
16
+ },
17
+ RFC1738: 'RFC1738',
18
+ RFC3986: 'RFC3986'
19
+ };
20
+
21
+ },{}],2:[function(require,module,exports){
22
+ 'use strict';
23
+
24
+ var stringify = require('./stringify');
25
+ var parse = require('./parse');
26
+ var formats = require('./formats');
27
+
28
+ module.exports = {
29
+ formats: formats,
30
+ parse: parse,
31
+ stringify: stringify
10
32
  };
11
33
 
12
- },{"./parse":2,"./stringify":3}],2:[function(require,module,exports){
34
+ },{"./formats":1,"./parse":3,"./stringify":4}],3:[function(require,module,exports){
13
35
  'use strict';
14
36
 
15
- var Utils = require('./utils');
37
+ var utils = require('./utils');
16
38
 
17
39
  var has = Object.prototype.hasOwnProperty;
18
40
 
19
41
  var defaults = {
42
+ allowDots: false,
43
+ allowPrototypes: false,
44
+ arrayLimit: 20,
45
+ decoder: utils.decode,
20
46
  delimiter: '&',
21
47
  depth: 5,
22
- arrayLimit: 20,
23
48
  parameterLimit: 1000,
24
- strictNullHandling: false,
25
49
  plainObjects: false,
26
- allowPrototypes: false,
27
- allowDots: false,
28
- decoder: Utils.decode
50
+ strictNullHandling: false
29
51
  };
30
52
 
31
- var parseValues = function parseValues(str, options) {
53
+ var parseValues = function parseQueryStringValues(str, options) {
32
54
  var obj = {};
33
55
  var parts = str.split(options.delimiter, options.parameterLimit === Infinity ? undefined : options.parameterLimit);
34
56
 
@@ -54,7 +76,7 @@ var parseValues = function parseValues(str, options) {
54
76
  return obj;
55
77
  };
56
78
 
57
- var parseObject = function parseObject(chain, val, options) {
79
+ var parseObject = function parseObjectRecursive(chain, val, options) {
58
80
  if (!chain.length) {
59
81
  return val;
60
82
  }
@@ -88,7 +110,7 @@ var parseObject = function parseObject(chain, val, options) {
88
110
  return obj;
89
111
  };
90
112
 
91
- var parseKeys = function parseKeys(givenKey, val, options) {
113
+ var parseKeys = function parseQueryStringKeys(givenKey, val, options) {
92
114
  if (!givenKey) {
93
115
  return;
94
116
  }
@@ -149,7 +171,7 @@ module.exports = function (str, opts) {
149
171
  throw new TypeError('Decoder has to be a function.');
150
172
  }
151
173
 
152
- options.delimiter = typeof options.delimiter === 'string' || Utils.isRegExp(options.delimiter) ? options.delimiter : defaults.delimiter;
174
+ options.delimiter = typeof options.delimiter === 'string' || utils.isRegExp(options.delimiter) ? options.delimiter : defaults.delimiter;
153
175
  options.depth = typeof options.depth === 'number' ? options.depth : defaults.depth;
154
176
  options.arrayLimit = typeof options.arrayLimit === 'number' ? options.arrayLimit : defaults.arrayLimit;
155
177
  options.parseArrays = options.parseArrays !== false;
@@ -173,16 +195,17 @@ module.exports = function (str, opts) {
173
195
  for (var i = 0; i < keys.length; ++i) {
174
196
  var key = keys[i];
175
197
  var newObj = parseKeys(key, tempObj[key], options);
176
- obj = Utils.merge(obj, newObj, options);
198
+ obj = utils.merge(obj, newObj, options);
177
199
  }
178
200
 
179
- return Utils.compact(obj);
201
+ return utils.compact(obj);
180
202
  };
181
203
 
182
- },{"./utils":4}],3:[function(require,module,exports){
204
+ },{"./utils":5}],4:[function(require,module,exports){
183
205
  'use strict';
184
206
 
185
- var Utils = require('./utils');
207
+ var utils = require('./utils');
208
+ var formats = require('./formats');
186
209
 
187
210
  var arrayPrefixGenerators = {
188
211
  brackets: function brackets(prefix) {
@@ -196,15 +219,25 @@ var arrayPrefixGenerators = {
196
219
  }
197
220
  };
198
221
 
222
+ var isArray = Array.isArray;
223
+ var push = Array.prototype.push;
224
+ var pushToArray = function (arr, valueOrArray) {
225
+ push.apply(arr, isArray(valueOrArray) ? valueOrArray : [valueOrArray]);
226
+ };
227
+
228
+ var toISO = Date.prototype.toISOString;
229
+
199
230
  var defaults = {
200
231
  delimiter: '&',
201
- strictNullHandling: false,
202
- skipNulls: false,
203
232
  encode: true,
204
- encoder: Utils.encode
233
+ encoder: utils.encode,
234
+ serializeDate: function serializeDate(date) {
235
+ return toISO.call(date);
236
+ },
237
+ skipNulls: false,
238
+ strictNullHandling: false
205
239
  };
206
240
 
207
- var isArray = Array.isArray;
208
241
  var stringify = function stringify(
209
242
  object,
210
243
  prefix,
@@ -214,14 +247,18 @@ var stringify = function stringify(
214
247
  encoder,
215
248
  filter,
216
249
  sort,
217
- allowDots
250
+ allowDots,
251
+ serializeDate,
252
+ formatter
218
253
  ) {
219
254
  var obj = object;
220
255
  if (typeof filter === 'function') {
221
256
  obj = filter(prefix, obj);
222
257
  } else if (obj instanceof Date) {
223
- obj = obj.toISOString();
224
- } else if (obj === null) {
258
+ obj = serializeDate(obj);
259
+ }
260
+
261
+ if (obj === null) {
225
262
  if (strictNullHandling) {
226
263
  return encoder ? encoder(prefix) : prefix;
227
264
  }
@@ -229,11 +266,11 @@ var stringify = function stringify(
229
266
  obj = '';
230
267
  }
231
268
 
232
- if (typeof obj === 'string' || typeof obj === 'number' || typeof obj === 'boolean' || Utils.isBuffer(obj)) {
269
+ if (typeof obj === 'string' || typeof obj === 'number' || typeof obj === 'boolean' || utils.isBuffer(obj)) {
233
270
  if (encoder) {
234
- return [encoder(prefix) + '=' + encoder(obj)];
271
+ return [formatter(encoder(prefix)) + '=' + formatter(encoder(obj))];
235
272
  }
236
- return [prefix + '=' + String(obj)];
273
+ return [formatter(prefix) + '=' + formatter(String(obj))];
237
274
  }
238
275
 
239
276
  var values = [];
@@ -258,7 +295,7 @@ var stringify = function stringify(
258
295
  }
259
296
 
260
297
  if (isArray(obj)) {
261
- values = values.concat(stringify(
298
+ pushToArray(values, stringify(
262
299
  obj[key],
263
300
  generateArrayPrefix(prefix, key),
264
301
  generateArrayPrefix,
@@ -267,10 +304,12 @@ var stringify = function stringify(
267
304
  encoder,
268
305
  filter,
269
306
  sort,
270
- allowDots
307
+ allowDots,
308
+ serializeDate,
309
+ formatter
271
310
  ));
272
311
  } else {
273
- values = values.concat(stringify(
312
+ pushToArray(values, stringify(
274
313
  obj[key],
275
314
  prefix + (allowDots ? '.' + key : '[' + key + ']'),
276
315
  generateArrayPrefix,
@@ -279,7 +318,9 @@ var stringify = function stringify(
279
318
  encoder,
280
319
  filter,
281
320
  sort,
282
- allowDots
321
+ allowDots,
322
+ serializeDate,
323
+ formatter
283
324
  ));
284
325
  }
285
326
  }
@@ -290,6 +331,11 @@ var stringify = function stringify(
290
331
  module.exports = function (object, opts) {
291
332
  var obj = object;
292
333
  var options = opts || {};
334
+
335
+ if (options.encoder !== null && typeof options.encoder !== 'undefined' && typeof options.encoder !== 'function') {
336
+ throw new TypeError('Encoder has to be a function.');
337
+ }
338
+
293
339
  var delimiter = typeof options.delimiter === 'undefined' ? defaults.delimiter : options.delimiter;
294
340
  var strictNullHandling = typeof options.strictNullHandling === 'boolean' ? options.strictNullHandling : defaults.strictNullHandling;
295
341
  var skipNulls = typeof options.skipNulls === 'boolean' ? options.skipNulls : defaults.skipNulls;
@@ -297,19 +343,22 @@ module.exports = function (object, opts) {
297
343
  var encoder = encode ? typeof options.encoder === 'function' ? options.encoder : defaults.encoder : null;
298
344
  var sort = typeof options.sort === 'function' ? options.sort : null;
299
345
  var allowDots = typeof options.allowDots === 'undefined' ? false : options.allowDots;
346
+ var serializeDate = typeof options.serializeDate === 'function' ? options.serializeDate : defaults.serializeDate;
347
+ if (typeof options.format === 'undefined') {
348
+ options.format = formats['default'];
349
+ } else if (!Object.prototype.hasOwnProperty.call(formats.formatters, options.format)) {
350
+ throw new TypeError('Unknown format option provided.');
351
+ }
352
+ var formatter = formats.formatters[options.format];
300
353
  var objKeys;
301
354
  var filter;
302
355
 
303
- if (options.encoder !== null && typeof options.encoder !== 'undefined' && typeof options.encoder !== 'function') {
304
- throw new TypeError('Encoder has to be a function.');
305
- }
306
-
307
356
  if (typeof options.filter === 'function') {
308
357
  filter = options.filter;
309
358
  obj = filter('', obj);
310
359
  } else if (isArray(options.filter)) {
311
- objKeys = options.filter;
312
360
  filter = options.filter;
361
+ objKeys = filter;
313
362
  }
314
363
 
315
364
  var keys = [];
@@ -343,8 +392,7 @@ module.exports = function (object, opts) {
343
392
  if (skipNulls && obj[key] === null) {
344
393
  continue;
345
394
  }
346
-
347
- keys = keys.concat(stringify(
395
+ pushToArray(keys, stringify(
348
396
  obj[key],
349
397
  key,
350
398
  generateArrayPrefix,
@@ -353,27 +401,29 @@ module.exports = function (object, opts) {
353
401
  encoder,
354
402
  filter,
355
403
  sort,
356
- allowDots
404
+ allowDots,
405
+ serializeDate,
406
+ formatter
357
407
  ));
358
408
  }
359
409
 
360
410
  return keys.join(delimiter);
361
411
  };
362
412
 
363
- },{"./utils":4}],4:[function(require,module,exports){
413
+ },{"./formats":1,"./utils":5}],5:[function(require,module,exports){
364
414
  'use strict';
365
415
 
416
+ var has = Object.prototype.hasOwnProperty;
417
+
366
418
  var hexTable = (function () {
367
- var array = new Array(256);
419
+ var array = [];
368
420
  for (var i = 0; i < 256; ++i) {
369
- array[i] = '%' + ((i < 16 ? '0' : '') + i.toString(16)).toUpperCase();
421
+ array.push('%' + ((i < 16 ? '0' : '') + i.toString(16)).toUpperCase());
370
422
  }
371
423
 
372
424
  return array;
373
425
  }());
374
426
 
375
- var has = Object.prototype.hasOwnProperty;
376
-
377
427
  exports.arrayToObject = function (source, options) {
378
428
  var obj = options && options.plainObjects ? Object.create(null) : {};
379
429
  for (var i = 0; i < source.length; ++i) {
@@ -385,27 +435,13 @@ exports.arrayToObject = function (source, options) {
385
435
  return obj;
386
436
  };
387
437
 
388
- var isArray = Array.isArray;
389
-
390
- var arrayToObject = function arrayToObject(source, options) {
391
- var obj = options && options.plainObjects ? Object.create(null) : {};
392
- for (var i = 0; i < source.length; ++i) {
393
- if (typeof source[i] !== 'undefined') {
394
- obj[i] = source[i];
395
- }
396
- }
397
-
398
- return obj;
399
- };
400
-
401
- exports.merge = function merge(target, source, options) {
402
- /* eslint no-param-reassign: 0 */
438
+ exports.merge = function (target, source, options) {
403
439
  if (!source) {
404
440
  return target;
405
441
  }
406
442
 
407
443
  if (typeof source !== 'object') {
408
- if (isArray(target)) {
444
+ if (Array.isArray(target)) {
409
445
  target.push(source);
410
446
  } else if (target && typeof target === 'object') {
411
447
  if ((options && (options.plainObjects || options.allowPrototypes)) || !has.call(Object.prototype, source)) {
@@ -423,16 +459,15 @@ exports.merge = function merge(target, source, options) {
423
459
  }
424
460
 
425
461
  var mergeTarget = target;
426
- if (isArray(target) && !isArray(source)) {
427
- mergeTarget = arrayToObject(target, options);
462
+ if (Array.isArray(target) && !Array.isArray(source)) {
463
+ mergeTarget = exports.arrayToObject(target, options);
428
464
  }
429
465
 
430
- if (isArray(target) && isArray(source)) {
466
+ if (Array.isArray(target) && Array.isArray(source)) {
431
467
  source.forEach(function (item, i) {
432
468
  if (has.call(target, i)) {
433
- var targetItem = target[i];
434
- if (targetItem && typeof targetItem === 'object' && item && typeof item === 'object') {
435
- target[i] = merge(targetItem, item, options);
469
+ if (target[i] && typeof target[i] === 'object') {
470
+ target[i] = exports.merge(target[i], item, options);
436
471
  } else {
437
472
  target.push(item);
438
473
  }
@@ -446,8 +481,8 @@ exports.merge = function merge(target, source, options) {
446
481
  return Object.keys(source).reduce(function (acc, key) {
447
482
  var value = source[key];
448
483
 
449
- if (has.call(acc, key)) {
450
- acc[key] = merge(acc[key], value, options);
484
+ if (Object.prototype.hasOwnProperty.call(acc, key)) {
485
+ acc[key] = exports.merge(acc[key], value, options);
451
486
  } else {
452
487
  acc[key] = value;
453
488
  }
@@ -529,7 +564,7 @@ exports.compact = function (obj, references) {
529
564
 
530
565
  refs.push(obj);
531
566
 
532
- if (isArray(obj)) {
567
+ if (Array.isArray(obj)) {
533
568
  var compacted = [];
534
569
 
535
570
  for (var i = 0; i < obj.length; ++i) {
@@ -544,10 +579,9 @@ exports.compact = function (obj, references) {
544
579
  }
545
580
 
546
581
  var keys = Object.keys(obj);
547
- for (var j = 0; j < keys.length; ++j) {
548
- var key = keys[j];
582
+ keys.forEach(function (key) {
549
583
  obj[key] = exports.compact(obj[key], refs);
550
- }
584
+ });
551
585
 
552
586
  return obj;
553
587
  };
@@ -564,5 +598,5 @@ exports.isBuffer = function (obj) {
564
598
  return !!(obj.constructor && obj.constructor.isBuffer && obj.constructor.isBuffer(obj));
565
599
  };
566
600
 
567
- },{}]},{},[1])(1)
601
+ },{}]},{},[2])(2)
568
602
  });
package/lib/formats.js ADDED
@@ -0,0 +1,18 @@
1
+ 'use strict';
2
+
3
+ var replace = String.prototype.replace;
4
+ var percentTwenties = /%20/g;
5
+
6
+ module.exports = {
7
+ 'default': 'RFC3986',
8
+ formatters: {
9
+ RFC1738: function (value) {
10
+ return replace.call(value, percentTwenties, '+');
11
+ },
12
+ RFC3986: function (value) {
13
+ return String(value);
14
+ }
15
+ },
16
+ RFC1738: 'RFC1738',
17
+ RFC3986: 'RFC3986'
18
+ };
package/lib/index.js CHANGED
@@ -1,9 +1,11 @@
1
1
  'use strict';
2
2
 
3
- var Stringify = require('./stringify');
4
- var Parse = require('./parse');
3
+ var stringify = require('./stringify');
4
+ var parse = require('./parse');
5
+ var formats = require('./formats');
5
6
 
6
7
  module.exports = {
7
- stringify: Stringify,
8
- parse: Parse
8
+ formats: formats,
9
+ parse: parse,
10
+ stringify: stringify
9
11
  };