Skip to content

Commit f572893

Browse files
committed
feat: added promise support
1 parent edf01c3 commit f572893

File tree

3 files changed

+151
-38
lines changed

3 files changed

+151
-38
lines changed

projects/openapi-fetch-angular/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "openapi-fetch-angular",
33
"description": "Fast, typesafe fetch client for your OpenAPI schema. Works with Angular HTTPClient API.",
4-
"version": "0.0.2",
4+
"version": "0.1.0",
55
"license": "MIT",
66
"author": "Luna Simons <[email protected]> (https://bddvlpr.com)",
77
"contributors": [

projects/openapi-fetch-angular/src/lib/openapi-client.service.ts

Lines changed: 135 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,17 @@ import {
66
} from '@angular/common/http';
77
import { Injectable } from '@angular/core';
88
import {
9-
ClientMethod,
9+
ClientObservableMethod,
1010
ClientOptions,
11+
ClientPromiseMethod,
1112
FetchOptions,
1213
} from './openapi-client.types';
1314
import {
1415
createFinalURL,
1516
createQuerySerializer,
1617
mergeHeaders,
1718
} from './openapi-serializer';
18-
import { lastValueFrom } from 'rxjs';
19+
import { filter, lastValueFrom, map } from 'rxjs';
1920

2021
export const DEFAULT_HEADERS = new HttpHeaders({
2122
'Content-Type': 'application/json',
@@ -26,13 +27,28 @@ export const DEFAULT_HEADERS = new HttpHeaders({
2627
})
2728
export abstract class OpenAPIClientService<Paths extends {}> {
2829
get;
30+
getPromise;
31+
2932
put;
33+
putPromise;
34+
3035
post;
36+
postPromise;
37+
3138
delete;
39+
deletePromise;
40+
3241
options;
42+
optionsPromise;
43+
3344
head;
45+
headPromise;
46+
3447
patch;
48+
patchPromise;
49+
3550
trace;
51+
tracePromise;
3652

3753
constructor(http: HttpClient, clientOptions: ClientOptions) {
3854
let {
@@ -48,7 +64,68 @@ export abstract class OpenAPIClientService<Paths extends {}> {
4864
}
4965
baseHeaders = mergeHeaders(DEFAULT_HEADERS, baseHeaders);
5066

51-
const coreFetch = async (url: any, fetchOptions: FetchOptions<any>) => {
67+
const coreObservableFetch = (url: any, fetchOptions: FetchOptions<any>) => {
68+
let {
69+
headers,
70+
params = {},
71+
querySerializer: requestQuerySerializer,
72+
...init
73+
} = fetchOptions || {};
74+
75+
let querySerializer =
76+
typeof globalQuerySerializer === 'function'
77+
? globalQuerySerializer
78+
: createQuerySerializer(globalQuerySerializer);
79+
if (requestQuerySerializer) {
80+
querySerializer =
81+
typeof requestQuerySerializer === 'function'
82+
? requestQuerySerializer
83+
: createQuerySerializer({
84+
...(typeof globalQuerySerializer === 'object'
85+
? globalQuerySerializer
86+
: {}),
87+
...requestQuerySerializer,
88+
});
89+
}
90+
91+
const requestInit = {
92+
...baseOptions,
93+
...init,
94+
headers: mergeHeaders(baseHeaders, headers, params.headers),
95+
};
96+
97+
const request = new HttpRequest(
98+
requestInit.method as any,
99+
createFinalURL(url, { baseUrl, params, querySerializer }),
100+
requestInit.body ?? null,
101+
requestInit,
102+
);
103+
104+
return http.request(request).pipe(
105+
filter((response) => response instanceof HttpResponse),
106+
map((response) => {
107+
if (!(response instanceof HttpResponse)) {
108+
throw new Error(
109+
'Invalid response! This should not never happen, please report this issue.',
110+
);
111+
}
112+
return response.ok
113+
? {
114+
data: response.body,
115+
response,
116+
}
117+
: {
118+
error: response.body,
119+
response,
120+
};
121+
}),
122+
);
123+
};
124+
125+
const corePromiseFetch = async (
126+
url: any,
127+
fetchOptions: FetchOptions<any>,
128+
) => {
52129
let {
53130
headers,
54131
params = {},
@@ -100,36 +177,60 @@ export abstract class OpenAPIClientService<Paths extends {}> {
100177
};
101178
};
102179

103-
this.get = (async (url, init) => {
104-
return coreFetch(url, { ...init, method: 'GET' });
105-
}) as ClientMethod<Paths, 'get'>;
106-
107-
this.put = (async (url, init) => {
108-
return coreFetch(url, { ...init, method: 'PUT' });
109-
}) as ClientMethod<Paths, 'put'>;
110-
111-
this.post = (async (url, init) => {
112-
return coreFetch(url, { ...init, method: 'POST' });
113-
}) as ClientMethod<Paths, 'post'>;
114-
115-
this.delete = (async (url, init) => {
116-
return coreFetch(url, { ...init, method: 'DELETE' });
117-
}) as ClientMethod<Paths, 'delete'>;
118-
119-
this.options = (async (url, init) => {
120-
return coreFetch(url, { ...init, method: 'OPTIONS' });
121-
}) as ClientMethod<Paths, 'options'>;
122-
123-
this.head = (async (url, init) => {
124-
return coreFetch(url, { ...init, method: 'HEAD' });
125-
}) as ClientMethod<Paths, 'head'>;
126-
127-
this.patch = (async (url, init) => {
128-
return coreFetch(url, { ...init, method: 'PATCH' });
129-
}) as ClientMethod<Paths, 'patch'>;
130-
131-
this.trace = (async (url, init) => {
132-
return coreFetch(url, { ...init, method: 'TRACE' });
133-
}) as ClientMethod<Paths, 'trace'>;
180+
this.get = ((url, init) => {
181+
return coreObservableFetch(url, { ...init, method: 'GET' });
182+
}) as ClientObservableMethod<Paths, 'get'>;
183+
this.getPromise = (async (url, init) => {
184+
return corePromiseFetch(url, { ...init, method: 'GET' });
185+
}) as ClientPromiseMethod<Paths, 'get'>;
186+
187+
this.put = ((url, init) => {
188+
return coreObservableFetch(url, { ...init, method: 'PUT' });
189+
}) as ClientObservableMethod<Paths, 'get'>;
190+
this.putPromise = (async (url, init) => {
191+
return corePromiseFetch(url, { ...init, method: 'PUT' });
192+
}) as ClientPromiseMethod<Paths, 'put'>;
193+
194+
this.post = ((url, init) => {
195+
return coreObservableFetch(url, { ...init, method: 'POST' });
196+
}) as ClientObservableMethod<Paths, 'post'>;
197+
this.postPromise = (async (url, init) => {
198+
return corePromiseFetch(url, { ...init, method: 'POST' });
199+
}) as ClientPromiseMethod<Paths, 'post'>;
200+
201+
this.delete = ((url, init) => {
202+
return coreObservableFetch(url, { ...init, method: 'DELETE' });
203+
}) as ClientObservableMethod<Paths, 'delete'>;
204+
this.deletePromise = (async (url, init) => {
205+
return corePromiseFetch(url, { ...init, method: 'DELETE' });
206+
}) as ClientPromiseMethod<Paths, 'delete'>;
207+
208+
this.options = ((url, init) => {
209+
return coreObservableFetch(url, { ...init, method: 'OPTIONS' });
210+
}) as ClientObservableMethod<Paths, 'options'>;
211+
this.optionsPromise = (async (url, init) => {
212+
return corePromiseFetch(url, { ...init, method: 'OPTIONS' });
213+
}) as ClientPromiseMethod<Paths, 'options'>;
214+
215+
this.head = ((url, init) => {
216+
return coreObservableFetch(url, { ...init, method: 'HEAD' });
217+
}) as ClientObservableMethod<Paths, 'head'>;
218+
this.headPromise = (async (url, init) => {
219+
return corePromiseFetch(url, { ...init, method: 'HEAD' });
220+
}) as ClientPromiseMethod<Paths, 'head'>;
221+
222+
this.patch = ((url, init) => {
223+
return coreObservableFetch(url, { ...init, method: 'PATCH' });
224+
}) as ClientObservableMethod<Paths, 'patch'>;
225+
this.patchPromise = (async (url, init) => {
226+
return corePromiseFetch(url, { ...init, method: 'PATCH' });
227+
}) as ClientPromiseMethod<Paths, 'patch'>;
228+
229+
this.trace = ((url, init) => {
230+
return coreObservableFetch(url, { ...init, method: 'TRACE' });
231+
}) as ClientObservableMethod<Paths, 'trace'>;
232+
this.tracePromise = (async (url, init) => {
233+
return corePromiseFetch(url, { ...init, method: 'TRACE' });
234+
}) as ClientPromiseMethod<Paths, 'trace'>;
134235
}
135236
}

projects/openapi-fetch-angular/src/lib/openapi-client.types.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
ResponseObjectMap,
1111
SuccessResponse,
1212
} from 'openapi-typescript-helpers';
13+
import { Observable } from 'rxjs';
1314

1415
export type QuerySerializer<T> = (
1516
query: T extends { parameters: any }
@@ -80,20 +81,20 @@ export type MaybeOptionalInit<P extends PathMethods, M extends keyof P> =
8081
export type FetchResponse<T> =
8182
| {
8283
data: FilterKeys<SuccessResponse<ResponseObjectMap<T>>, MediaType>;
83-
error?: never;
84+
error: never;
8485
response: HttpResponse<
8586
FilterKeys<SuccessResponse<ResponseObjectMap<T>>, MediaType>
8687
>;
8788
}
8889
| {
89-
data?: never;
90+
data: never;
9091
error: FilterKeys<ErrorResponse<ResponseObjectMap<T>>, MediaType>;
9192
response: HttpResponse<
9293
FilterKeys<ErrorResponse<ResponseObjectMap<T>>, MediaType>
9394
>;
9495
};
9596

96-
export type ClientMethod<
97+
export type ClientPromiseMethod<
9798
Paths extends Record<string, PathMethods>,
9899
M extends HttpMethod,
99100
> = <
@@ -103,3 +104,14 @@ export type ClientMethod<
103104
url: P,
104105
...init: I
105106
) => Promise<FetchResponse<Paths[P][M]>>;
107+
108+
export type ClientObservableMethod<
109+
Paths extends Record<string, PathMethods>,
110+
M extends HttpMethod,
111+
> = <
112+
P extends PathsWithMethod<Paths, M>,
113+
I extends MaybeOptionalInit<Paths[P], M>,
114+
>(
115+
url: P,
116+
...init: I
117+
) => Observable<FetchResponse<Paths[P][M]>>;

0 commit comments

Comments
 (0)