Skip to content

Commit 04bd7ad

Browse files
committed
fix: Do not add quotes to search params
1 parent afb4b24 commit 04bd7ad

File tree

4 files changed

+50
-62
lines changed

4 files changed

+50
-62
lines changed

packages/router-core/src/qss.ts

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -39,23 +39,6 @@ export function encode(
3939
return result.toString()
4040
}
4141

42-
/**
43-
* Converts a string value to its appropriate type (string, number, boolean).
44-
* @param mix - The string value to convert.
45-
* @returns The converted value.
46-
* @example
47-
* // Example input: toValue("123")
48-
* // Expected output: 123
49-
*/
50-
/** Convert a string into a primitive boolean/number when possible. */
51-
function toValue(str: unknown) {
52-
if (!str) return ''
53-
54-
if (str === 'false') return false
55-
if (str === 'true') return true
56-
return +str * 0 === 0 && +str + '' === str ? +str : str
57-
}
58-
5942
/**
6043
* Decodes a query string into an object.
6144
* @param str - The query string to decode.
@@ -73,11 +56,11 @@ export function decode(str: any): any {
7356
for (const [key, value] of searchParams.entries()) {
7457
const previousValue = result[key]
7558
if (previousValue == null) {
76-
result[key] = toValue(value)
59+
result[key] = value
7760
} else if (Array.isArray(previousValue)) {
78-
previousValue.push(toValue(value))
61+
previousValue.push(value)
7962
} else {
80-
result[key] = [previousValue, toValue(value)]
63+
result[key] = [previousValue, value]
8164
}
8265
}
8366

packages/router-core/src/searchParams.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,10 @@ export function parseSearchWith(parser: (str: string) => any) {
3535
const value = query[key]
3636
if (typeof value === 'string') {
3737
try {
38-
query[key] = parser(value)
38+
const parsed = parser(value)
39+
if (parsed && typeof parsed === 'object') {
40+
query[key] = parsed
41+
}
3942
} catch (_err) {
4043
// silent
4144
}
@@ -75,8 +78,10 @@ export function stringifySearchWith(
7578
try {
7679
// Check if it's a valid parseable string.
7780
// If it is, then stringify it again.
78-
parser(val)
79-
return stringify(val)
81+
const parsed = parser(val)
82+
if (parsed && typeof parsed === 'object') {
83+
return stringify(val)
84+
}
8085
} catch (_err) {
8186
// silent
8287
}

packages/router-core/tests/qss.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ describe('decode function', () => {
6161
it('should handle decoding a top-level key with a special character', () => {
6262
const queryString = 'foo%3Dbar=1'
6363
const decodedObj = decode(queryString)
64-
expect(decodedObj).toEqual({ 'foo=bar': 1 })
64+
expect(decodedObj).toEqual({ 'foo=bar': '1' })
6565
})
6666

6767
it('should handle decoding a top-level key with a special character and without a value', () => {

packages/router-core/tests/searchParams.test.ts

Lines changed: 38 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2,43 +2,43 @@ import { describe, expect, test } from 'vitest'
22
import { defaultParseSearch, defaultStringifySearch } from '../src'
33

44
describe('Search Params serialization and deserialization', () => {
5-
/*
6-
* JSON-compatible objects can be serialized into a string,
7-
* and then deserialized back into the original object.
8-
*/
95
test.each([
10-
[{}, ''],
11-
[{ foo: '' }, '?foo='],
12-
[{ foo: 'bar' }, '?foo=bar'],
13-
[{ foo: 'bar baz' }, '?foo=bar+baz'],
14-
[{ foo: 123 }, '?foo=123'],
15-
[{ foo: '123' }, '?foo=%22123%22'],
16-
[{ foo: true }, '?foo=true'],
17-
[{ foo: 'true' }, '?foo=%22true%22'],
18-
[{ foo: null }, '?foo=null'],
19-
[{ foo: 'null' }, '?foo=%22null%22'],
20-
[{ foo: 'undefined' }, '?foo=undefined'],
21-
[{ foo: {} }, '?foo=%7B%7D'],
22-
[{ foo: '{}' }, '?foo=%22%7B%7D%22'],
23-
[{ foo: [] }, '?foo=%5B%5D'],
24-
[{ foo: '[]' }, '?foo=%22%5B%5D%22'],
25-
[{ foo: [1, 2, 3] }, '?foo=%5B1%2C2%2C3%5D'],
26-
[{ foo: '1,2,3' }, '?foo=1%2C2%2C3'],
27-
[{ foo: { bar: 'baz' } }, '?foo=%7B%22bar%22%3A%22baz%22%7D'],
28-
[{ 0: 1 }, '?0=1'],
29-
[{ 'foo=bar': 1 }, '?foo%3Dbar=1'],
30-
[{ '{}': 1 }, '?%7B%7D=1'],
31-
[{ '': 1 }, '?=1'],
32-
[{ '=': '=' }, '?%3D=%3D'],
33-
[{ '=': '', '': '=' }, '?%3D=&=%3D'],
34-
[{ 'foo=2&bar': 3 }, '?foo%3D2%26bar=3'],
35-
[{ 'foo?': 1 }, '?foo%3F=1'],
36-
[{ foo: 'bar=' }, '?foo=bar%3D'],
37-
[{ foo: '2&bar=3' }, '?foo=2%26bar%3D3'],
38-
])('isomorphism %j', (input, expected) => {
39-
const str = defaultStringifySearch(input)
40-
expect(str).toEqual(expected)
41-
expect(defaultParseSearch(str)).toEqual(input)
6+
['', {}],
7+
['?foo=', { foo: '' }],
8+
['?foo=bar', { foo: 'bar' }],
9+
['?foo=%22bar%22', { foo: '"bar"' }],
10+
['?foo=bar+baz', { foo: 'bar baz' }],
11+
['?foo=%22bar+baz%22', { foo: '"bar baz"' }],
12+
['?foo=123', { foo: '123' }],
13+
['?foo=%22123%22', { foo: '"123"' }],
14+
['?foo=true', { foo: 'true' }],
15+
['?foo=%22true%22', { foo: '"true"' }],
16+
['?foo=null', { foo: 'null' }],
17+
['?foo=%22null%22', { foo: '"null"' }],
18+
['?foo=undefined', { foo: 'undefined' }],
19+
['?foo=%22undefined%22', { foo: '"undefined"' }],
20+
['?foo=%7B%7D', { foo: {} }],
21+
['?foo=%22%7B%7D%22', { foo: '"{}"' }],
22+
['?foo=%5B%5D', { foo: [] }],
23+
['?foo=%22%5B%5D%22', { foo: '"[]"' }],
24+
['?foo=%5B1%2C2%2C3%5D', { foo: [1, 2, 3] }],
25+
['?foo=1%2C2%2C3', { foo: '1,2,3' }],
26+
['?foo=%7B%22bar%22%3A%22baz%22%7D', { foo: { bar: 'baz' } }],
27+
['?0=1', { 0: '1' }],
28+
['?foo%3Dbar=1', { 'foo=bar': '1' }],
29+
['?%7B%7D=1', { '{}': '1' }],
30+
['?=1', { '': '1' }],
31+
['?%3D=%3D', { '=': '=' }],
32+
['?%3D=&=%3D', { '=': '', '': '=' }],
33+
['?foo%3D2%26bar=3', { 'foo=2&bar': '3' }],
34+
['?foo%3F=1', { 'foo?': '1' }],
35+
['?foo=bar%3D', { foo: 'bar=' }],
36+
['?foo=2%26bar%3D3', { foo: '2&bar=3' }],
37+
])('isomorphism %j', (input, expectedObj) => {
38+
const parsed = defaultParseSearch(input)
39+
expect(parsed).toEqual(expectedObj)
40+
const str = defaultStringifySearch(parsed)
41+
expect(str).toEqual(input)
4242
})
4343

4444
test('undefined values are removed during stringification', () => {
@@ -67,8 +67,8 @@ describe('Search Params serialization and deserialization', () => {
6767
['?foo=[]', { foo: [] }],
6868
['?foo=1,2,3', { foo: '1,2,3' }],
6969
['?foo={"bar":"baz"}', { foo: { bar: 'baz' } }],
70-
['?foo=1&foo=2', { foo: [1, 2] }],
71-
['?foo=""', { foo: '' }],
70+
['?foo=1&foo=2', { foo: ['1', '2'] }],
71+
['?foo=""', { foo: '""' }],
7272
['?foo=""""', { foo: '""""' }],
7373
['?foo=()', { foo: '()' }],
7474
['?foo=[{}]', { foo: [{}] }],

0 commit comments

Comments
 (0)