qs 2.3.1 → 2.4.1
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/.travis.yml +3 -1
- package/CHANGELOG.md +12 -2
- package/Makefile +4 -4
- package/README.md +13 -0
- package/index.js +1 -1
- package/lib/parse.js +5 -0
- package/lib/stringify.js +29 -9
- package/lib/utils.js +9 -3
- package/package.json +3 -2
- package/test/parse.js +31 -18
- package/test/stringify.js +33 -1
package/.travis.yml
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
|
|
2
|
-
## [**2.3.
|
|
2
|
+
## [**2.3.3**](https://github.com/hapijs/qs/issues?milestone=18&state=open)
|
|
3
|
+
- [**#59**](https://github.com/hapijs/qs/issues/59) make sure array indexes are >= 0, closes #57
|
|
4
|
+
- [**#58**](https://github.com/hapijs/qs/issues/58) make qs usable for browser loader
|
|
5
|
+
|
|
6
|
+
## [**2.3.2**](https://github.com/hapijs/qs/issues?milestone=17&state=closed)
|
|
7
|
+
- [**#55**](https://github.com/hapijs/qs/issues/55) allow merging a string into an object
|
|
8
|
+
|
|
9
|
+
## [**2.3.1**](https://github.com/hapijs/qs/issues?milestone=16&state=closed)
|
|
10
|
+
- [**#52**](https://github.com/hapijs/qs/issues/52) Return "undefined" and "false" instead of throwing "TypeError".
|
|
11
|
+
|
|
12
|
+
## [**2.3.0**](https://github.com/hapijs/qs/issues?milestone=15&state=closed)
|
|
3
13
|
- [**#50**](https://github.com/hapijs/qs/issues/50) add option to omit array indices, closes #46
|
|
4
14
|
|
|
5
15
|
## [**2.2.5**](https://github.com/hapijs/qs/issues?milestone=14&state=closed)
|
|
6
|
-
- [**#49**](https://github.com/hapijs/qs/issues/49) refactor utils.merge, fixes #45
|
|
7
16
|
- [**#39**](https://github.com/hapijs/qs/issues/39) Is there an alternative to Buffer.isBuffer?
|
|
17
|
+
- [**#49**](https://github.com/hapijs/qs/issues/49) refactor utils.merge, fixes #45
|
|
8
18
|
- [**#41**](https://github.com/hapijs/qs/issues/41) avoid browserifying Buffer, for #39
|
|
9
19
|
|
|
10
20
|
## [**2.2.4**](https://github.com/hapijs/qs/issues?milestone=13&state=closed)
|
package/Makefile
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
test:
|
|
2
|
-
@node node_modules/lab/bin/lab
|
|
2
|
+
@node node_modules/lab/bin/lab -a code -L
|
|
3
3
|
test-cov:
|
|
4
|
-
@node node_modules/lab/bin/lab -t 100
|
|
4
|
+
@node node_modules/lab/bin/lab -a code -t 100 -L
|
|
5
5
|
test-cov-html:
|
|
6
|
-
@node node_modules/lab/bin/lab -r html -o coverage.html
|
|
6
|
+
@node node_modules/lab/bin/lab -a code -L -r html -o coverage.html
|
|
7
7
|
|
|
8
|
-
.PHONY: test test-cov test-cov-html
|
|
8
|
+
.PHONY: test test-cov test-cov-html
|
package/README.md
CHANGED
|
@@ -153,6 +153,8 @@ Qs.parse('a[1]=b', { arrayLimit: 0 });
|
|
|
153
153
|
// { a: { '1': 'b' } }
|
|
154
154
|
```
|
|
155
155
|
|
|
156
|
+
To disable array parsing entirely, set `arrayLimit` to `-1`.
|
|
157
|
+
|
|
156
158
|
If you mix notations, **qs** will merge the two items into an object:
|
|
157
159
|
|
|
158
160
|
```javascript
|
|
@@ -198,6 +200,17 @@ Qs.stringify({ a: ['b', 'c', 'd'] }, { indices: false });
|
|
|
198
200
|
// 'a=b&a=c&a=d'
|
|
199
201
|
```
|
|
200
202
|
|
|
203
|
+
You may use the `arrayFormat` option to specify the format of the output array
|
|
204
|
+
|
|
205
|
+
```javascript
|
|
206
|
+
Qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'indices' })
|
|
207
|
+
// 'a[0]=b&a[1]=c'
|
|
208
|
+
Qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'brackets' })
|
|
209
|
+
// 'a[]=b&a[]=c'
|
|
210
|
+
Qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'repeat' })
|
|
211
|
+
// 'a=b&a=c'
|
|
212
|
+
```
|
|
213
|
+
|
|
201
214
|
Empty strings and null values will omit the value, but the equals sign (=) remains in place:
|
|
202
215
|
|
|
203
216
|
```javascript
|
package/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
module.exports = require('./lib');
|
|
1
|
+
module.exports = require('./lib/');
|
package/lib/parse.js
CHANGED
|
@@ -29,6 +29,10 @@ internals.parseValues = function (str, options) {
|
|
|
29
29
|
var key = Utils.decode(part.slice(0, pos));
|
|
30
30
|
var val = Utils.decode(part.slice(pos + 1));
|
|
31
31
|
|
|
32
|
+
if (Object.prototype.hasOwnProperty(key)) {
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
|
|
32
36
|
if (!obj.hasOwnProperty(key)) {
|
|
33
37
|
obj[key] = val;
|
|
34
38
|
}
|
|
@@ -62,6 +66,7 @@ internals.parseObject = function (chain, val, options) {
|
|
|
62
66
|
if (!isNaN(index) &&
|
|
63
67
|
root !== cleanRoot &&
|
|
64
68
|
indexString === cleanRoot &&
|
|
69
|
+
index >= 0 &&
|
|
65
70
|
index <= options.arrayLimit) {
|
|
66
71
|
|
|
67
72
|
obj = [];
|
package/lib/stringify.js
CHANGED
|
@@ -7,11 +7,21 @@ var Utils = require('./utils');
|
|
|
7
7
|
|
|
8
8
|
var internals = {
|
|
9
9
|
delimiter: '&',
|
|
10
|
-
|
|
10
|
+
arrayPrefixGenerators: {
|
|
11
|
+
brackets: function (prefix, key) {
|
|
12
|
+
return prefix + '[]';
|
|
13
|
+
},
|
|
14
|
+
indices: function (prefix, key) {
|
|
15
|
+
return prefix + '[' + key + ']';
|
|
16
|
+
},
|
|
17
|
+
repeat: function (prefix, key) {
|
|
18
|
+
return prefix;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
11
21
|
};
|
|
12
22
|
|
|
13
23
|
|
|
14
|
-
internals.stringify = function (obj, prefix,
|
|
24
|
+
internals.stringify = function (obj, prefix, generateArrayPrefix) {
|
|
15
25
|
|
|
16
26
|
if (Utils.isBuffer(obj)) {
|
|
17
27
|
obj = obj.toString();
|
|
@@ -39,13 +49,11 @@ internals.stringify = function (obj, prefix, options) {
|
|
|
39
49
|
var objKeys = Object.keys(obj);
|
|
40
50
|
for (var i = 0, il = objKeys.length; i < il; ++i) {
|
|
41
51
|
var key = objKeys[i];
|
|
42
|
-
if (
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
values = values.concat(internals.stringify(obj[key], prefix, options));
|
|
52
|
+
if (Array.isArray(obj)) {
|
|
53
|
+
values = values.concat(internals.stringify(obj[key], generateArrayPrefix(prefix, key), generateArrayPrefix));
|
|
46
54
|
}
|
|
47
55
|
else {
|
|
48
|
-
values = values.concat(internals.stringify(obj[key], prefix + '[' + key + ']',
|
|
56
|
+
values = values.concat(internals.stringify(obj[key], prefix + '[' + key + ']', generateArrayPrefix));
|
|
49
57
|
}
|
|
50
58
|
}
|
|
51
59
|
|
|
@@ -57,7 +65,6 @@ module.exports = function (obj, options) {
|
|
|
57
65
|
|
|
58
66
|
options = options || {};
|
|
59
67
|
var delimiter = typeof options.delimiter === 'undefined' ? internals.delimiter : options.delimiter;
|
|
60
|
-
options.indices = typeof options.indices === 'boolean' ? options.indices : internals.indices;
|
|
61
68
|
|
|
62
69
|
var keys = [];
|
|
63
70
|
|
|
@@ -67,10 +74,23 @@ module.exports = function (obj, options) {
|
|
|
67
74
|
return '';
|
|
68
75
|
}
|
|
69
76
|
|
|
77
|
+
var arrayFormat;
|
|
78
|
+
if (options.arrayFormat in internals.arrayPrefixGenerators) {
|
|
79
|
+
arrayFormat = options.arrayFormat;
|
|
80
|
+
}
|
|
81
|
+
else if ('indices' in options) {
|
|
82
|
+
arrayFormat = options.indices ? 'indices' : 'repeat';
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
arrayFormat = 'indices';
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
var generateArrayPrefix = internals.arrayPrefixGenerators[arrayFormat];
|
|
89
|
+
|
|
70
90
|
var objKeys = Object.keys(obj);
|
|
71
91
|
for (var i = 0, il = objKeys.length; i < il; ++i) {
|
|
72
92
|
var key = objKeys[i];
|
|
73
|
-
keys = keys.concat(internals.stringify(obj[key], key,
|
|
93
|
+
keys = keys.concat(internals.stringify(obj[key], key, generateArrayPrefix));
|
|
74
94
|
}
|
|
75
95
|
|
|
76
96
|
return keys.join(delimiter);
|
package/lib/utils.js
CHANGED
|
@@ -27,7 +27,13 @@ exports.merge = function (target, source) {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
if (typeof source !== 'object') {
|
|
30
|
-
|
|
30
|
+
if (Array.isArray(target)) {
|
|
31
|
+
target.push(source);
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
target[source] = true;
|
|
35
|
+
}
|
|
36
|
+
|
|
31
37
|
return target;
|
|
32
38
|
}
|
|
33
39
|
|
|
@@ -88,7 +94,7 @@ exports.compact = function (obj, refs) {
|
|
|
88
94
|
if (Array.isArray(obj)) {
|
|
89
95
|
var compacted = [];
|
|
90
96
|
|
|
91
|
-
for (var i = 0,
|
|
97
|
+
for (var i = 0, il = obj.length; i < il; ++i) {
|
|
92
98
|
if (typeof obj[i] !== 'undefined') {
|
|
93
99
|
compacted.push(obj[i]);
|
|
94
100
|
}
|
|
@@ -98,7 +104,7 @@ exports.compact = function (obj, refs) {
|
|
|
98
104
|
}
|
|
99
105
|
|
|
100
106
|
var keys = Object.keys(obj);
|
|
101
|
-
for (
|
|
107
|
+
for (i = 0, il = keys.length; i < il; ++i) {
|
|
102
108
|
var key = keys[i];
|
|
103
109
|
obj[key] = exports.compact(obj[key], refs);
|
|
104
110
|
}
|
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "qs",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.1",
|
|
4
4
|
"description": "A querystring parser that supports nesting and arrays, with a depth limit",
|
|
5
5
|
"homepage": "https://github.com/hapijs/qs",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"dependencies": {},
|
|
8
8
|
"devDependencies": {
|
|
9
|
-
"
|
|
9
|
+
"code": "1.x.x",
|
|
10
|
+
"lab": "5.x.x"
|
|
10
11
|
},
|
|
11
12
|
"scripts": {
|
|
12
13
|
"test": "make test-cov"
|
package/test/parse.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
/* eslint no-extend-native:0 */
|
|
1
2
|
// Load modules
|
|
2
3
|
|
|
4
|
+
var Code = require('code');
|
|
3
5
|
var Lab = require('lab');
|
|
4
6
|
var Qs = require('../');
|
|
5
7
|
|
|
@@ -12,7 +14,7 @@ var internals = {};
|
|
|
12
14
|
// Test shortcuts
|
|
13
15
|
|
|
14
16
|
var lab = exports.lab = Lab.script();
|
|
15
|
-
var expect =
|
|
17
|
+
var expect = Code.expect;
|
|
16
18
|
var describe = lab.experiment;
|
|
17
19
|
var it = lab.test;
|
|
18
20
|
|
|
@@ -158,6 +160,12 @@ describe('parse()', function () {
|
|
|
158
160
|
done();
|
|
159
161
|
});
|
|
160
162
|
|
|
163
|
+
it('can add keys to objects', function (done) {
|
|
164
|
+
|
|
165
|
+
expect(Qs.parse('a[b]=c&a=d')).to.deep.equal({ a: { b: 'c', d: true } });
|
|
166
|
+
done();
|
|
167
|
+
});
|
|
168
|
+
|
|
161
169
|
it('correctly prunes undefined values when converting an array to an object', function (done) {
|
|
162
170
|
|
|
163
171
|
expect(Qs.parse('a[2]=b&a[99999999]=c')).to.deep.equal({ a: { '2': 'b', '99999999': 'c' } });
|
|
@@ -179,7 +187,7 @@ describe('parse()', function () {
|
|
|
179
187
|
|
|
180
188
|
it('cannot override prototypes', function (done) {
|
|
181
189
|
|
|
182
|
-
var obj = Qs.parse('toString=bad&bad[toString]=bad&constructor=bad');
|
|
190
|
+
var obj = Qs.parse('hasOwnProperty=bad&toString=bad&bad[toString]=bad&constructor=bad');
|
|
183
191
|
expect(typeof obj.toString).to.equal('function');
|
|
184
192
|
expect(typeof obj.bad.toString).to.equal('function');
|
|
185
193
|
expect(typeof obj.constructor).to.equal('function');
|
|
@@ -296,6 +304,8 @@ describe('parse()', function () {
|
|
|
296
304
|
|
|
297
305
|
it('allows overriding array limit', function (done) {
|
|
298
306
|
|
|
307
|
+
expect(Qs.parse('a[0]=b', { arrayLimit: -1 })).to.deep.equal({ a: { '0': 'b' } });
|
|
308
|
+
expect(Qs.parse('a[-1]=b', { arrayLimit: -1 })).to.deep.equal({ a: { '-1': 'b' } });
|
|
299
309
|
expect(Qs.parse('a[0]=b&a[1]=c', { arrayLimit: 0 })).to.deep.equal({ a: { '0': 'b', '1': 'c' } });
|
|
300
310
|
done();
|
|
301
311
|
});
|
|
@@ -303,14 +313,14 @@ describe('parse()', function () {
|
|
|
303
313
|
it('parses an object', function (done) {
|
|
304
314
|
|
|
305
315
|
var input = {
|
|
306
|
-
|
|
307
|
-
|
|
316
|
+
'user[name]': {'pop[bob]': 3},
|
|
317
|
+
'user[email]': null
|
|
308
318
|
};
|
|
309
319
|
|
|
310
320
|
var expected = {
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
321
|
+
'user': {
|
|
322
|
+
'name': {'pop[bob]': 3},
|
|
323
|
+
'email': null
|
|
314
324
|
}
|
|
315
325
|
};
|
|
316
326
|
|
|
@@ -323,14 +333,14 @@ describe('parse()', function () {
|
|
|
323
333
|
it('parses an object and not child values', function (done) {
|
|
324
334
|
|
|
325
335
|
var input = {
|
|
326
|
-
|
|
327
|
-
|
|
336
|
+
'user[name]': {'pop[bob]': { 'test': 3 }},
|
|
337
|
+
'user[email]': null
|
|
328
338
|
};
|
|
329
339
|
|
|
330
340
|
var expected = {
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
341
|
+
'user': {
|
|
342
|
+
'name': {'pop[bob]': { 'test': 3 }},
|
|
343
|
+
'email': null
|
|
334
344
|
}
|
|
335
345
|
};
|
|
336
346
|
|
|
@@ -344,8 +354,9 @@ describe('parse()', function () {
|
|
|
344
354
|
|
|
345
355
|
var tempBuffer = global.Buffer;
|
|
346
356
|
delete global.Buffer;
|
|
347
|
-
|
|
357
|
+
var result = Qs.parse('a=b&c=d');
|
|
348
358
|
global.Buffer = tempBuffer;
|
|
359
|
+
expect(result).to.deep.equal({ a: 'b', c: 'd' });
|
|
349
360
|
done();
|
|
350
361
|
});
|
|
351
362
|
|
|
@@ -365,10 +376,10 @@ describe('parse()', function () {
|
|
|
365
376
|
expect(function () {
|
|
366
377
|
|
|
367
378
|
parsed = Qs.parse({ 'foo[bar]': 'baz', 'foo[baz]': a });
|
|
368
|
-
}).to.not.throw(
|
|
379
|
+
}).to.not.throw();
|
|
369
380
|
|
|
370
|
-
expect(parsed).to.
|
|
371
|
-
expect(parsed.foo).to.
|
|
381
|
+
expect(parsed).to.contain('foo');
|
|
382
|
+
expect(parsed.foo).to.contain('bar', 'baz');
|
|
372
383
|
expect(parsed.foo.bar).to.equal('baz');
|
|
373
384
|
expect(parsed.foo.baz).to.deep.equal(a);
|
|
374
385
|
done();
|
|
@@ -378,9 +389,11 @@ describe('parse()', function () {
|
|
|
378
389
|
|
|
379
390
|
var a = Object.create(null);
|
|
380
391
|
a.b = 'c';
|
|
381
|
-
|
|
392
|
+
|
|
382
393
|
expect(Qs.parse(a)).to.deep.equal({ b: 'c' });
|
|
383
|
-
|
|
394
|
+
var result = Qs.parse({ a: a });
|
|
395
|
+
expect(result).to.contain('a');
|
|
396
|
+
expect(result.a).to.deep.equal(a);
|
|
384
397
|
done();
|
|
385
398
|
});
|
|
386
399
|
|
package/test/stringify.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
/* eslint no-extend-native:0 */
|
|
1
2
|
// Load modules
|
|
2
3
|
|
|
4
|
+
var Code = require('code');
|
|
3
5
|
var Lab = require('lab');
|
|
4
6
|
var Qs = require('../');
|
|
5
7
|
|
|
@@ -12,7 +14,7 @@ var internals = {};
|
|
|
12
14
|
// Test shortcuts
|
|
13
15
|
|
|
14
16
|
var lab = exports.lab = Lab.script();
|
|
15
|
-
var expect =
|
|
17
|
+
var expect = Code.expect;
|
|
16
18
|
var describe = lab.experiment;
|
|
17
19
|
var it = lab.test;
|
|
18
20
|
|
|
@@ -65,6 +67,36 @@ describe('stringify()', function () {
|
|
|
65
67
|
done();
|
|
66
68
|
});
|
|
67
69
|
|
|
70
|
+
it('uses indices notation for arrays when indices=true', function (done) {
|
|
71
|
+
|
|
72
|
+
expect(Qs.stringify({ a: ['b', 'c'] }, { indices: true })).to.equal('a%5B0%5D=b&a%5B1%5D=c');
|
|
73
|
+
done();
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('uses indices notation for arrays when no arrayFormat is specified', function (done) {
|
|
77
|
+
|
|
78
|
+
expect(Qs.stringify({ a: ['b', 'c'] })).to.equal('a%5B0%5D=b&a%5B1%5D=c');
|
|
79
|
+
done();
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('uses indices notation for arrays when no arrayFormat=indices', function (done) {
|
|
83
|
+
|
|
84
|
+
expect(Qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'indices' })).to.equal('a%5B0%5D=b&a%5B1%5D=c');
|
|
85
|
+
done();
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('uses repeat notation for arrays when no arrayFormat=repeat', function (done) {
|
|
89
|
+
|
|
90
|
+
expect(Qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'repeat' })).to.equal('a=b&a=c');
|
|
91
|
+
done();
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('uses brackets notation for arrays when no arrayFormat=brackets', function (done) {
|
|
95
|
+
|
|
96
|
+
expect(Qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'brackets' })).to.equal('a%5B%5D=b&a%5B%5D=c');
|
|
97
|
+
done();
|
|
98
|
+
});
|
|
99
|
+
|
|
68
100
|
it('stringifies a complicated object', function (done) {
|
|
69
101
|
|
|
70
102
|
expect(Qs.stringify({ a: { b: 'c', d: 'e' } })).to.equal('a%5Bb%5D=c&a%5Bd%5D=e');
|