qs 2.2.4 → 2.3.2
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/CHANGELOG.md +14 -0
- package/README.md +8 -1
- package/lib/stringify.js +28 -9
- package/lib/utils.js +25 -32
- package/package.json +1 -2
- package/test/parse.js +19 -4
- package/test/stringify.js +41 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,18 @@
|
|
|
1
1
|
|
|
2
|
+
## [**2.3.1**](https://github.com/hapijs/qs/issues?milestone=16&state=closed)
|
|
3
|
+
- [**#52**](https://github.com/hapijs/qs/issues/52) Return "undefined" and "false" instead of throwing "TypeError".
|
|
4
|
+
|
|
5
|
+
## [**2.3.0**](https://github.com/hapijs/qs/issues?milestone=15&state=closed)
|
|
6
|
+
- [**#50**](https://github.com/hapijs/qs/issues/50) add option to omit array indices, closes #46
|
|
7
|
+
|
|
8
|
+
## [**2.2.5**](https://github.com/hapijs/qs/issues?milestone=14&state=closed)
|
|
9
|
+
- [**#39**](https://github.com/hapijs/qs/issues/39) Is there an alternative to Buffer.isBuffer?
|
|
10
|
+
- [**#49**](https://github.com/hapijs/qs/issues/49) refactor utils.merge, fixes #45
|
|
11
|
+
- [**#41**](https://github.com/hapijs/qs/issues/41) avoid browserifying Buffer, for #39
|
|
12
|
+
|
|
13
|
+
## [**2.2.4**](https://github.com/hapijs/qs/issues?milestone=13&state=closed)
|
|
14
|
+
- [**#38**](https://github.com/hapijs/qs/issues/38) how to handle object keys beginning with a number
|
|
15
|
+
|
|
2
16
|
## [**2.2.3**](https://github.com/hapijs/qs/issues?milestone=12&state=closed)
|
|
3
17
|
- [**#37**](https://github.com/hapijs/qs/issues/37) parser discards first empty value in array
|
|
4
18
|
- [**#36**](https://github.com/hapijs/qs/issues/36) Update to lab 4.x
|
package/README.md
CHANGED
|
@@ -184,13 +184,20 @@ Qs.stringify({ a: { b: 'c' } });
|
|
|
184
184
|
|
|
185
185
|
Examples beyond this point will be shown as though the output is not URI encoded for clarity. Please note that the return values in these cases *will* be URI encoded during real usage.
|
|
186
186
|
|
|
187
|
-
When arrays are stringified, they are
|
|
187
|
+
When arrays are stringified, by default they are given explicit indices:
|
|
188
188
|
|
|
189
189
|
```javascript
|
|
190
190
|
Qs.stringify({ a: ['b', 'c', 'd'] });
|
|
191
191
|
// 'a[0]=b&a[1]=c&a[2]=d'
|
|
192
192
|
```
|
|
193
193
|
|
|
194
|
+
You may override this by setting the `indices` option to `false`:
|
|
195
|
+
|
|
196
|
+
```javascript
|
|
197
|
+
Qs.stringify({ a: ['b', 'c', 'd'] }, { indices: false });
|
|
198
|
+
// 'a=b&a=c&a=d'
|
|
199
|
+
```
|
|
200
|
+
|
|
194
201
|
Empty strings and null values will omit the value, but the equals sign (=) remains in place:
|
|
195
202
|
|
|
196
203
|
```javascript
|
package/lib/stringify.js
CHANGED
|
@@ -6,11 +6,12 @@ var Utils = require('./utils');
|
|
|
6
6
|
// Declare internals
|
|
7
7
|
|
|
8
8
|
var internals = {
|
|
9
|
-
delimiter: '&'
|
|
9
|
+
delimiter: '&',
|
|
10
|
+
indices: true
|
|
10
11
|
};
|
|
11
12
|
|
|
12
13
|
|
|
13
|
-
internals.stringify = function (obj, prefix) {
|
|
14
|
+
internals.stringify = function (obj, prefix, options) {
|
|
14
15
|
|
|
15
16
|
if (Utils.isBuffer(obj)) {
|
|
16
17
|
obj = obj.toString();
|
|
@@ -31,9 +32,20 @@ internals.stringify = function (obj, prefix) {
|
|
|
31
32
|
|
|
32
33
|
var values = [];
|
|
33
34
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
if (typeof obj === 'undefined') {
|
|
36
|
+
return values;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
var objKeys = Object.keys(obj);
|
|
40
|
+
for (var i = 0, il = objKeys.length; i < il; ++i) {
|
|
41
|
+
var key = objKeys[i];
|
|
42
|
+
if (!options.indices &&
|
|
43
|
+
Array.isArray(obj)) {
|
|
44
|
+
|
|
45
|
+
values = values.concat(internals.stringify(obj[key], prefix, options));
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
values = values.concat(internals.stringify(obj[key], prefix + '[' + key + ']', options));
|
|
37
49
|
}
|
|
38
50
|
}
|
|
39
51
|
|
|
@@ -45,13 +57,20 @@ module.exports = function (obj, options) {
|
|
|
45
57
|
|
|
46
58
|
options = options || {};
|
|
47
59
|
var delimiter = typeof options.delimiter === 'undefined' ? internals.delimiter : options.delimiter;
|
|
60
|
+
options.indices = typeof options.indices === 'boolean' ? options.indices : internals.indices;
|
|
48
61
|
|
|
49
62
|
var keys = [];
|
|
50
63
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
64
|
+
if (typeof obj !== 'object' ||
|
|
65
|
+
obj === null) {
|
|
66
|
+
|
|
67
|
+
return '';
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
var objKeys = Object.keys(obj);
|
|
71
|
+
for (var i = 0, il = objKeys.length; i < il; ++i) {
|
|
72
|
+
var key = objKeys[i];
|
|
73
|
+
keys = keys.concat(internals.stringify(obj[key], key, options));
|
|
55
74
|
}
|
|
56
75
|
|
|
57
76
|
return keys.join(delimiter);
|
package/lib/utils.js
CHANGED
|
@@ -26,29 +26,26 @@ exports.merge = function (target, source) {
|
|
|
26
26
|
return target;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
if (
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
else {
|
|
36
|
-
target[i] = source[i];
|
|
37
|
-
}
|
|
38
|
-
}
|
|
29
|
+
if (typeof source !== 'object') {
|
|
30
|
+
if (Array.isArray(target)) {
|
|
31
|
+
target.push(source);
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
target[source] = true;
|
|
39
35
|
}
|
|
40
36
|
|
|
41
37
|
return target;
|
|
42
38
|
}
|
|
43
39
|
|
|
44
|
-
if (
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
40
|
+
if (typeof target !== 'object') {
|
|
41
|
+
target = [target].concat(source);
|
|
42
|
+
return target;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (Array.isArray(target) &&
|
|
46
|
+
!Array.isArray(source)) {
|
|
47
|
+
|
|
48
|
+
target = exports.arrayToObject(target);
|
|
52
49
|
}
|
|
53
50
|
|
|
54
51
|
var keys = Object.keys(source);
|
|
@@ -56,18 +53,11 @@ exports.merge = function (target, source) {
|
|
|
56
53
|
var key = keys[k];
|
|
57
54
|
var value = source[key];
|
|
58
55
|
|
|
59
|
-
if (
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
if (!target[key]) {
|
|
63
|
-
target[key] = value;
|
|
64
|
-
}
|
|
65
|
-
else {
|
|
66
|
-
target[key] = exports.merge(target[key], value);
|
|
67
|
-
}
|
|
56
|
+
if (!target[key]) {
|
|
57
|
+
target[key] = value;
|
|
68
58
|
}
|
|
69
59
|
else {
|
|
70
|
-
target[key] = value;
|
|
60
|
+
target[key] = exports.merge(target[key], value);
|
|
71
61
|
}
|
|
72
62
|
}
|
|
73
63
|
|
|
@@ -130,10 +120,13 @@ exports.isRegExp = function (obj) {
|
|
|
130
120
|
|
|
131
121
|
exports.isBuffer = function (obj) {
|
|
132
122
|
|
|
133
|
-
if (
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
else {
|
|
123
|
+
if (obj === null ||
|
|
124
|
+
typeof obj === 'undefined') {
|
|
125
|
+
|
|
137
126
|
return false;
|
|
138
127
|
}
|
|
128
|
+
|
|
129
|
+
return !!(obj.constructor &&
|
|
130
|
+
obj.constructor.isBuffer &&
|
|
131
|
+
obj.constructor.isBuffer(obj));
|
|
139
132
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "qs",
|
|
3
|
-
"version": "2.2
|
|
3
|
+
"version": "2.3.2",
|
|
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",
|
|
@@ -19,7 +19,6 @@
|
|
|
19
19
|
"querystring",
|
|
20
20
|
"qs"
|
|
21
21
|
],
|
|
22
|
-
"author": "Nathan LaFreniere <quitlahok@gmail.com>",
|
|
23
22
|
"licenses": [
|
|
24
23
|
{
|
|
25
24
|
"type": "BSD",
|
package/test/parse.js
CHANGED
|
@@ -13,13 +13,11 @@ var internals = {};
|
|
|
13
13
|
|
|
14
14
|
var lab = exports.lab = Lab.script();
|
|
15
15
|
var expect = Lab.expect;
|
|
16
|
-
var before = lab.before;
|
|
17
|
-
var after = lab.after;
|
|
18
16
|
var describe = lab.experiment;
|
|
19
17
|
var it = lab.test;
|
|
20
18
|
|
|
21
19
|
|
|
22
|
-
describe('
|
|
20
|
+
describe('parse()', function () {
|
|
23
21
|
|
|
24
22
|
it('parses a simple string', function (done) {
|
|
25
23
|
|
|
@@ -82,6 +80,17 @@ describe('#parse', function () {
|
|
|
82
80
|
done();
|
|
83
81
|
});
|
|
84
82
|
|
|
83
|
+
it('parses a mix of simple and explicit arrays', function (done) {
|
|
84
|
+
|
|
85
|
+
expect(Qs.parse('a=b&a[]=c')).to.deep.equal({ a: ['b', 'c'] });
|
|
86
|
+
expect(Qs.parse('a[]=b&a=c')).to.deep.equal({ a: ['b', 'c'] });
|
|
87
|
+
expect(Qs.parse('a[0]=b&a=c')).to.deep.equal({ a: ['b', 'c'] });
|
|
88
|
+
expect(Qs.parse('a=b&a[0]=c')).to.deep.equal({ a: ['b', 'c'] });
|
|
89
|
+
expect(Qs.parse('a[1]=b&a=c')).to.deep.equal({ a: ['b', 'c'] });
|
|
90
|
+
expect(Qs.parse('a=b&a[1]=c')).to.deep.equal({ a: ['b', 'c'] });
|
|
91
|
+
done();
|
|
92
|
+
});
|
|
93
|
+
|
|
85
94
|
it('parses a nested array', function (done) {
|
|
86
95
|
|
|
87
96
|
expect(Qs.parse('a[b][]=c&a[b][]=d')).to.deep.equal({ a: { b: ['c', 'd'] } });
|
|
@@ -149,6 +158,12 @@ describe('#parse', function () {
|
|
|
149
158
|
done();
|
|
150
159
|
});
|
|
151
160
|
|
|
161
|
+
it('can add keys to objects', function (done) {
|
|
162
|
+
|
|
163
|
+
expect(Qs.parse('a[b]=c&a=d')).to.deep.equal({ a: { b: 'c', d: true } });
|
|
164
|
+
done();
|
|
165
|
+
});
|
|
166
|
+
|
|
152
167
|
it('correctly prunes undefined values when converting an array to an object', function (done) {
|
|
153
168
|
|
|
154
169
|
expect(Qs.parse('a[2]=b&a[99999999]=c')).to.deep.equal({ a: { '2': 'b', '99999999': 'c' } });
|
|
@@ -369,7 +384,7 @@ describe('#parse', function () {
|
|
|
369
384
|
|
|
370
385
|
var a = Object.create(null);
|
|
371
386
|
a.b = 'c';
|
|
372
|
-
|
|
387
|
+
|
|
373
388
|
expect(Qs.parse(a)).to.deep.equal({ b: 'c' });
|
|
374
389
|
expect(Qs.parse({ a: a })).to.deep.equal({ a: { b: 'c' } });
|
|
375
390
|
done();
|
package/test/stringify.js
CHANGED
|
@@ -13,13 +13,11 @@ var internals = {};
|
|
|
13
13
|
|
|
14
14
|
var lab = exports.lab = Lab.script();
|
|
15
15
|
var expect = Lab.expect;
|
|
16
|
-
var before = lab.before;
|
|
17
|
-
var after = lab.after;
|
|
18
16
|
var describe = lab.experiment;
|
|
19
17
|
var it = lab.test;
|
|
20
18
|
|
|
21
19
|
|
|
22
|
-
describe('
|
|
20
|
+
describe('stringify()', function () {
|
|
23
21
|
|
|
24
22
|
it('stringifies a querystring object', function (done) {
|
|
25
23
|
|
|
@@ -42,6 +40,12 @@ describe('#stringify', function () {
|
|
|
42
40
|
done();
|
|
43
41
|
});
|
|
44
42
|
|
|
43
|
+
it('omits array indices when asked', function (done) {
|
|
44
|
+
|
|
45
|
+
expect(Qs.stringify({ a: ['b', 'c', 'd'] }, { indices: false })).to.equal('a=b&a=c&a=d');
|
|
46
|
+
done();
|
|
47
|
+
});
|
|
48
|
+
|
|
45
49
|
it('stringifies a nested array value', function (done) {
|
|
46
50
|
|
|
47
51
|
expect(Qs.stringify({ a: { b: ['c', 'd'] } })).to.equal('a%5Bb%5D%5B0%5D=c&a%5Bb%5D%5B1%5D=d');
|
|
@@ -55,6 +59,12 @@ describe('#stringify', function () {
|
|
|
55
59
|
done();
|
|
56
60
|
});
|
|
57
61
|
|
|
62
|
+
it('does not omit object keys when indices = false', function (done) {
|
|
63
|
+
|
|
64
|
+
expect(Qs.stringify({ a: [{ b: 'c' }] }, { indices: false })).to.equal('a%5Bb%5D=c');
|
|
65
|
+
done();
|
|
66
|
+
});
|
|
67
|
+
|
|
58
68
|
it('stringifies a complicated object', function (done) {
|
|
59
69
|
|
|
60
70
|
expect(Qs.stringify({ a: { b: 'c', d: 'e' } })).to.equal('a%5Bb%5D=c&a%5Bd%5D=e');
|
|
@@ -70,6 +80,34 @@ describe('#stringify', function () {
|
|
|
70
80
|
done();
|
|
71
81
|
});
|
|
72
82
|
|
|
83
|
+
it('stringifies an empty object', function (done) {
|
|
84
|
+
|
|
85
|
+
var obj = Object.create(null);
|
|
86
|
+
obj.a = 'b';
|
|
87
|
+
expect(Qs.stringify(obj)).to.equal('a=b');
|
|
88
|
+
done();
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('returns an empty string for invalid input', function (done) {
|
|
92
|
+
|
|
93
|
+
expect(Qs.stringify(undefined)).to.equal('');
|
|
94
|
+
expect(Qs.stringify(false)).to.equal('');
|
|
95
|
+
expect(Qs.stringify(null)).to.equal('');
|
|
96
|
+
expect(Qs.stringify('')).to.equal('');
|
|
97
|
+
done();
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('stringifies an object with an empty object as a child', function (done) {
|
|
101
|
+
|
|
102
|
+
var obj = {
|
|
103
|
+
a: Object.create(null)
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
obj.a.b = 'c';
|
|
107
|
+
expect(Qs.stringify(obj)).to.equal('a%5Bb%5D=c');
|
|
108
|
+
done();
|
|
109
|
+
});
|
|
110
|
+
|
|
73
111
|
it('drops keys with a value of undefined', function (done) {
|
|
74
112
|
|
|
75
113
|
expect(Qs.stringify({ a: undefined })).to.equal('');
|