-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathSearch.ts
More file actions
51 lines (51 loc) · 1.69 KB
/
Search.ts
File metadata and controls
51 lines (51 loc) · 1.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
export function stringify(data: { [key: string]: any }): string {
const result: string[] = []
const map = (key: string, value: any) => {
switch (typeof value) {
default:
case "bigint":
case "boolean":
case "number":
case "string":
result.push(`${key}=${encodeURIComponent(value.toString())}`)
break
case "undefined":
break
case "object":
for (const property in value)
if (Object.prototype.hasOwnProperty.call(value, property))
map(key ? key + `[${property}]` : property, value[property])
break
}
}
map("", data)
return result.join("&")
}
export function parse(data: string): { [key: string]: any } {
const convertArrays = (target: Record<string, any>): Record<string, any> | any[] => {
return typeof target == "object" &&
Object.keys(target)
.sort()
.every((k, i) => `${k}` == `${i}`)
? Object.entries(target)
.sort()
.map(entry => (typeof entry[1] == "object" ? convertArrays(entry[1]) : entry[1]))
: typeof target == "object"
? Object.fromEntries(Object.entries(target).map(entry => [entry[0], convertArrays(entry[1])]))
: target
}
const insert = (target: { [key: string]: any }, key: string[], value: string): any => {
target[key[0]] = key.length > 1 ? insert(target[key[0]] ?? {}, key.slice(1), value) : value
return target
}
const entries = data
.split("&")
.map<[string, string]>(d => d.split("=", 2) as [string, string])
.map<[string[], string]>(([k, v]) => [
decodeURIComponent(k)
.split("[")
.map(p => p.replace("]", "")),
decodeURIComponent(v.replace(/\+/g, " ")),
])
return entries.reduce<{ [key: string]: any }>((result, [key, value]) => convertArrays(insert(result, key, value)), {})
}