22const { apiConfig, generateResponses } = it;
33%>
44
5- export type RequestParams = Omit<RequestInit, "body" | "method"> & {
6- secure?: boolean;
5+ export type QueryParamsType = Record<string | number, any>;
6+ export type ResponseFormat = keyof Omit<Body, "body" | "bodyUsed">;
7+
8+ export interface FullRequestParams extends Omit<RequestInit, "body"> {
9+ /** set parameter to `true` for call `securityWorker` for this request */
10+ secure?: boolean;
11+ /** request path */
12+ path: string;
13+ /** content type of request body */
14+ type?: ContentType;
15+ /** query params */
16+ query?: QueryParamsType;
17+ /** format of response (i.e. response.json() -> format: "json") */
18+ format?: keyof Omit<Body, "body" | "bodyUsed">;
19+ /** request body */
20+ body?: unknown;
21+ /** base url */
22+ baseUrl?: string;
723}
824
9- export type RequestQueryParamsType = Record<string | number, any>;
25+ export type RequestParams = Omit<FullRequestParams, "body" | "method" | "query" | "path">
1026
1127
1228interface ApiConfig<<%~ apiConfig.generic.map(g => g.name).join(', ') %>> {
1329 baseUrl?: string;
14- baseApiParams?: RequestParams;
30+ baseApiParams?: Omit< RequestParams, "baseUrl"> ;
1531 securityWorker?: (securityData: SecurityDataType) => RequestParams;
1632}
1733
@@ -28,10 +44,10 @@ interface HttpResponse<D extends unknown, E extends unknown = unknown> extends R
2844 error: E;
2945}
3046
31- enum BodyType {
32- Json,
33- FormData,
34- UrlEncoded,
47+ export enum ContentType {
48+ Json = "application/json" ,
49+ FormData = "multipart/form-data" ,
50+ UrlEncoded = "application/x-www-form-urlencoded" ,
3551}
3652
3753export class HttpClient<<%~ apiConfig.generic.map(g => `${g.name} = unknown`).join(', ') %>> {
@@ -42,7 +58,7 @@ export class HttpClient<<%~ apiConfig.generic.map(g => `${g.name} = unknown`).jo
4258 private baseApiParams: RequestParams = {
4359 credentials: 'same-origin',
4460 headers: {
45- 'Content-Type': 'application/json'
61+ 'Content-Type': ContentType.Json
4662 },
4763 redirect: 'follow',
4864 referrerPolicy: 'no-referrer',
@@ -56,91 +72,103 @@ export class HttpClient<<%~ apiConfig.generic.map(g => `${g.name} = unknown`).jo
5672 this.securityData = data
5773 }
5874
59- private addQueryParam(query: RequestQueryParamsType, key: string) {
60- return encodeURIComponent(key) + "=" + encodeURIComponent(Array.isArray(query[key]) ? query[key].join(",") : query[key])
75+ private addQueryParam(query: QueryParamsType, key: string) {
76+ const value = query[key];
77+
78+ return (
79+ encodeURIComponent(key) + "=" + encodeURIComponent(
80+ Array.isArray(value) ? value.join(",") :
81+ typeof value === "number" ? value :
82+ `${value}`
83+ )
84+ );
6185 }
6286
63- protected toQueryString(rawQuery?: RequestQueryParamsType ): string {
87+ protected toQueryString(rawQuery?: QueryParamsType ): string {
6488 const query = rawQuery || {};
6589 const keys = Object.keys(query).filter((key) => "undefined" !== typeof query[key]);
6690 return keys
6791 .map((key) =>
6892 typeof query[key] === "object" && !Array.isArray(query[key])
69- ? this.toQueryString(query[key] as object )
93+ ? this.toQueryString(query[key] as QueryParamsType )
7094 : this.addQueryParam(query, key),
7195 )
7296 .join("&");
7397 }
7498
75- protected addQueryParams(rawQuery?: RequestQueryParamsType ): string {
99+ protected addQueryParams(rawQuery?: QueryParamsType ): string {
76100 const queryString = this.toQueryString(rawQuery);
77101 return queryString ? `?${queryString}` : "";
78102 }
79103
80- private bodyFormatters : Record<BodyType , (input: any) => any> = {
81- [BodyType .Json]: JSON.stringify,
82- [BodyType .FormData]: (input: any) =>
104+ private contentFormatters : Record<ContentType , (input: any) => any> = {
105+ [ContentType .Json]: JSON.stringify,
106+ [ContentType .FormData]: (input: any) =>
83107 Object.keys(input).reduce((data, key) => {
84108 data.append(key, input[key]);
85109 return data;
86110 }, new FormData()),
87- [BodyType .UrlEncoded]: (input: any) => this.toQueryString(input),
111+ [ContentType .UrlEncoded]: (input: any) => this.toQueryString(input),
88112 }
89113
90- private mergeRequestOptions(params : RequestParams, securityParams ?: RequestParams): RequestParams {
114+ private mergeRequestParams(params1 : RequestParams, params2 ?: RequestParams): RequestParams {
91115 return {
92116 ...this.baseApiParams,
93- ...params ,
94- ...(securityParams || {}),
117+ ...params1 ,
118+ ...(params2 || {}),
95119 headers: {
96120 ...(this.baseApiParams.headers || {}),
97- ...(params .headers || {}),
98- ...((securityParams && securityParams .headers) || {})
99- }
100- }
121+ ...(params1 .headers || {}),
122+ ...((params2 && params2 .headers) || {}),
123+ },
124+ };
101125 }
102-
103- private safeParseResponse = <T = any, E = any>(response: Response): Promise<HttpResponse<T, E>> => {
104- const r = response as HttpResponse<T, E>;
105- r.data = null as unknown as T;
106- r.error = null as unknown as E;
107-
108- return response
109- .json()
110- .then((data) => {
111- if (r.ok) {
112- r.data = data;
113- } else {
114- r.error = data;
115- }
116- return r;
117- })
118- .catch((e) => {
119- r.error = e;
120- return r;
121- });
122- }
123-
124- public request = <T = any, E = any>(
125- path: string,
126- method: string,
127- { secure, ...params }: RequestParams = {},
128- body?: any,
129- bodyType?: BodyType,
130- secureByDefault?: boolean,
131- ): <% if (generateResponses) { %>TPromise<HttpResponse<T, E>><% } else { %>Promise<HttpResponse<T>><% } %> => {
132- const requestUrl = `${this.baseUrl}${path}`;
133- const secureOptions = (secureByDefault || secure) && this.securityWorker ? this.securityWorker(this.securityData) : {};
134- const requestOptions = {
135- ...this.mergeRequestOptions(params, secureOptions),
136- method,
137- body: body ? this.bodyFormatters[bodyType || BodyType.Json](body) : null,
126+
127+ public request = <T = any, E = any>({
128+ body,
129+ secure,
130+ path,
131+ type = ContentType.Json,
132+ query,
133+ format = "json",
134+ baseUrl,
135+ ...params
136+ }: FullRequestParams): <% if (generateResponses) { %>TPromise<HttpResponse<T, E>><% } else { %>Promise<HttpResponse<T, E>><% } %> => {
137+ const secureParams = (secure && this.securityWorker) ? this.securityWorker(this.securityData) : {};
138+ const requestParams = this.mergeRequestParams(params, secureParams);
139+ const queryString = query && this.toQueryString(query);
140+
141+ return fetch(
142+ `${baseUrl || this.baseUrl || ""}${path}${queryString ? `?${queryString}` : ""}`,
143+ {
144+ headers: {
145+ "Content-Type": type,
146+ ...(requestParams.headers || {}),
147+ },
148+ ...requestParams,
149+ body: body ? (this.contentFormatters[type] ? this.contentFormatters[type](body) : body) : null,
138150 }
139-
140- return fetch(requestUrl, requestOptions).then(async response => {
141- const data = await this.safeParseResponse<T, E>(response);
142- if (!response.ok) throw data
143- return data
144- })
145- }
151+ ).then(async (response) => {
152+ const r = response as HttpResponse<T, E>;
153+ r.data = (null as unknown) as T;
154+ r.error = (null as unknown) as E;
155+
156+ const data = await response[format]()
157+ .then((data) => {
158+ if (r.ok) {
159+ r.data = data;
160+ } else {
161+ r.error = data;
162+ }
163+ return r;
164+ })
165+ .catch((e) => {
166+ r.error = e;
167+ return r;
168+ });
169+
170+ if (!response.ok) throw data;
171+ return data;
172+ });
173+ };
146174}
0 commit comments