-
Notifications
You must be signed in to change notification settings - Fork 5
/
restRequestBuilder.ts
148 lines (118 loc) · 4.41 KB
/
restRequestBuilder.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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import type { IStringifyOptions } from "qs";
import { stringify } from "qs";
import type { IApiConnector } from "./types";
const cleanupRegex = /\/+$/g; // removes trailing slash
export type Deserializer<T> = (response: Response) => Promise<T>;
export const ContentTypes = {
json: "application/json,text/json",
};
export function appendAcceptHeader(params: RequestInit | undefined, acceptContentType: string): RequestInit {
return {
...params,
headers: {
...params?.headers,
Accept: acceptContentType,
},
};
}
export function appendUrl(base: string, ...segments: any[]) {
const basePath = base.replace(cleanupRegex, "");
return segments.length ? `${basePath}/${segments.join("/")}` : basePath;
}
/**
* Fluent URL builder that makes the network call with the underlying IApiConnector
* Check https://github.com/ljharb/qs for query string customizations
*/
export class RestRequestBuilder {
static DefaultQueryStringOptions: IStringifyOptions = { skipNulls: true };
protected urlValue: string;
queryStringOptions?: IStringifyOptions;
objectContentType: string = ContentTypes.json;
objectDeserializer: Deserializer<unknown> = x => x.json();
get url() {
return this.urlValue;
}
constructor(
protected apiConnector: IApiConnector,
private baseUrl: string,
protected params?: RequestInit
) {
this.reset();
}
reset() {
this.urlValue = this.baseUrl.replace(cleanupRegex, "");
}
path(path: string): this {
this.urlValue += "/" + path;
return this;
}
all(path: string): this {
this.urlValue += "/" + path;
return this;
}
one(path: string, id?: any): this {
this.urlValue += "/" + path;
if (id !== undefined) {
this.urlValue += `/${id}`;
}
return this;
}
get<T>(queryParams?: any): Promise<T> {
const requestUrl = this.appendQuery(this.urlValue, queryParams);
const params = appendAcceptHeader(this.params, this.objectContentType);
return this.apiConnector.get(requestUrl, params).then(this.objectDeserializer as Deserializer<T>);
}
getRaw(queryParams?: any): Promise<Response> {
const requestUrl = this.appendQuery(this.urlValue, queryParams);
return this.apiConnector.get(requestUrl, this.params);
}
post<T>(content: any): Promise<T> {
const params = appendAcceptHeader(this.params, this.objectContentType);
return this.apiConnector.postObject(this.urlValue, content, params).then(this.objectDeserializer as Deserializer<T>);
}
postOnly(content: any): Promise<Response> {
return this.apiConnector.postObject(this.urlValue, content, this.params);
}
postData(data?: BodyInit): Promise<Response> {
return this.apiConnector.post(this.urlValue, data, this.params);
}
put<T>(content: any): Promise<T> {
const params = appendAcceptHeader(this.params, this.objectContentType);
return this.apiConnector.putObject(this.urlValue, content, params).then(this.objectDeserializer as Deserializer<T>);
}
putOnly(content: any): Promise<Response> {
return this.apiConnector.putObject(this.urlValue, content, this.params);
}
putData(data?: BodyInit): Promise<Response> {
return this.apiConnector.put(this.urlValue, data, this.params);
}
patch<T>(content: any): Promise<T> {
const params = appendAcceptHeader(this.params, this.objectContentType);
return this.apiConnector.patchObject(this.urlValue, content, params).then(this.objectDeserializer as Deserializer<T>);
}
patchOnly(content: any): Promise<Response> {
return this.apiConnector.patchObject(this.urlValue, content, this.params);
}
patchData(data?: BodyInit): Promise<Response> {
return this.apiConnector.patch(this.urlValue, data, this.params);
}
delete(content?: any): Promise<Response> {
return content
? this.apiConnector.deleteObject(this.urlValue, content, this.params)
: this.apiConnector.delete(this.urlValue, undefined, this.params);
}
withBaseUrl(url: string) {
this.urlValue = url;
return this;
}
getQueryString(query: any, queryStringOptions?: IStringifyOptions) {
return stringify(query, queryStringOptions ?? this.queryStringOptions ?? RestRequestBuilder.DefaultQueryStringOptions);
}
appendQuery(url: string, query?: any, queryStringOptions?: IStringifyOptions) {
if (!query) {
return url;
}
const queryString = typeof query === "string" ? query : this.getQueryString(query, queryStringOptions);
return `${url}?${queryString}`;
}
}