-
-
Notifications
You must be signed in to change notification settings - Fork 98
/
queryString.ts
107 lines (97 loc) · 3.11 KB
/
queryString.ts
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import type { Wretch, Config, WretchAddon } from "../types.js"
function stringify(value?: string | null): string | null {
return typeof value !== "undefined" ? value : ""
}
const appendQueryParams = (url: string, qp: object | string, replace: boolean, config: Config) => {
let queryString: string
if (typeof qp === "string") {
queryString = qp
} else {
const usp = config.polyfill("URLSearchParams", true, true)
for (const key in qp) {
const value = qp[key]
if (qp[key] instanceof Array) {
for (const val of value)
usp.append(key, stringify(val))
} else {
usp.append(key, stringify(value))
}
}
queryString = usp.toString()
}
const split = url.split("?")
if (!queryString)
return replace ? split[0] : url
if (replace || split.length < 2)
return split[0] + "?" + queryString
return url + "&" + queryString
}
export interface QueryStringAddon {
/**
* Converts a javascript object to query parameters, then appends this query string
* to the current url. String values are used as the query string verbatim.
*
* Pass `true` as the second argument to replace existing query parameters.
*
* ```
* import QueryAddon from "wretch/addons/queryString"
*
* let w = wretch("http://example.com").addon(QueryStringAddon);
* // url is http://example.com
* w = w.query({ a: 1, b: 2 });
* // url is now http://example.com?a=1&b=2
* w = w.query({ c: 3, d: [4, 5] });
* // url is now http://example.com?a=1&b=2c=3&d=4&d=5
* w = w.query("five&six&seven=eight");
* // url is now http://example.com?a=1&b=2c=3&d=4&d=5&five&six&seven=eight
* w = w.query({ reset: true }, true);
* // url is now http://example.com?reset=true
* ```
*
* ##### **Note that .query is not meant to handle complex cases with nested objects.**
*
* For this kind of usage, you can use `wretch` in conjunction with other libraries
* (like [`qs`](https://github.com/ljharb/qs)).
*
* ```js
* // Using wretch with qs
*
* const queryObject = { some: { nested: "objects" } };
* const w = wretch("https://example.com/").addon(QueryStringAddon)
*
* // Use .qs inside .query :
*
* w.query(qs.stringify(queryObject));
*
* // Use .defer :
*
* const qsWretch = w.defer((w, url, { qsQuery, qsOptions }) => (
* qsQuery ? w.query(qs.stringify(qsQuery, qsOptions)) : w
* ));
*
* qsWretch
* .url("https://example.com/")
* .options({ qs: { query: queryObject } });
* ```
*
* @param qp - An object which will be converted, or a string which will be used verbatim.
*/
query<T extends QueryStringAddon, C, R>(this: T & Wretch<T, C, R>, qp: object | string, replace?: boolean): this
}
/**
* Adds the ability to append query parameters from a javascript object.
*
* ```js
* import QueryAddon from "wretch/addons/queryString"
*
* wretch().addon(QueryAddon)
* ```
*/
const queryString: WretchAddon<QueryStringAddon> = {
wretch: {
query(qp, replace = false) {
return { ...this, _url: appendQueryParams(this._url, qp, replace, this._config) }
}
}
}
export default queryString