Skip to content

Commit d7761c7

Browse files
option to expose response headers and body
1 parent 6f5d0e4 commit d7761c7

14 files changed

+120
-3
lines changed

bin/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ const params = program
1616
.option('--name <value>', 'Custom client class name')
1717
.option('--useOptions', 'Use options instead of arguments')
1818
.option('--useUnionTypes', 'Use union types instead of enums')
19+
.option('--exposeHeadersAndBody', 'Return response headers and body (default is body only')
1920
.option('--exportCore <value>', 'Write core files to disk', true)
2021
.option('--exportServices <value>', 'Write services to disk', true)
2122
.option('--exportModels <value>', 'Write models to disk', true)
@@ -36,6 +37,7 @@ if (OpenAPI) {
3637
clientName: params.name,
3738
useOptions: params.useOptions,
3839
useUnionTypes: params.useUnionTypes,
40+
exposeHeadersAndBody: params.exposeHeadersAndBody,
3941
exportCore: JSON.parse(params.exportCore) === true,
4042
exportServices: JSON.parse(params.exportServices) === true,
4143
exportModels: JSON.parse(params.exportModels) === true,

src/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export type Options = {
1919
clientName?: string;
2020
useOptions?: boolean;
2121
useUnionTypes?: boolean;
22+
exposeHeadersAndBody?: boolean;
2223
exportCore?: boolean;
2324
exportServices?: boolean;
2425
exportModels?: boolean;
@@ -39,6 +40,7 @@ export type Options = {
3940
* @param clientName Custom client class name
4041
* @param useOptions Use options or arguments functions
4142
* @param useUnionTypes Use union types instead of enums
43+
* @param exposeHeadersAndBody Return response headers and body (default is body only)
4244
* @param exportCore Generate core client classes
4345
* @param exportServices Generate services
4446
* @param exportModels Generate models
@@ -55,6 +57,7 @@ export const generate = async ({
5557
clientName,
5658
useOptions = false,
5759
useUnionTypes = false,
60+
exposeHeadersAndBody = false,
5861
exportCore = true,
5962
exportServices = true,
6063
exportModels = true,
@@ -84,6 +87,7 @@ export const generate = async ({
8487
httpClient,
8588
useOptions,
8689
useUnionTypes,
90+
exposeHeadersAndBody,
8791
exportCore,
8892
exportServices,
8993
exportModels,
@@ -107,6 +111,7 @@ export const generate = async ({
107111
httpClient,
108112
useOptions,
109113
useUnionTypes,
114+
exposeHeadersAndBody,
110115
exportCore,
111116
exportServices,
112117
exportModels,

src/templates/core/BaseHttpRequest.hbs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,11 @@ export class BaseHttpRequest {
2828
throw new Error('Not Implemented');
2929
}
3030
{{else}}
31+
{{#if @root.exposeHeadersAndBody}}
32+
public request<T>(options: ApiRequestOptions): CancelablePromise<{ headers: Record<string, string>; body: T; }> {
33+
{{else}}
3134
public request<T>(options: ApiRequestOptions): CancelablePromise<T> {
35+
{{/if}}
3236
throw new Error('Not Implemented');
3337
}
3438
{{/equals}}

src/templates/core/HttpRequest.hbs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,18 @@ export class {{httpRequest}} extends BaseHttpRequest {
5151
/**
5252
* Request method
5353
* @param options The request options from the service
54+
{{#if @root.exposeHeadersAndBody}}
55+
* @returns CancelablePromise<{ headers: Record<string, string>; body: T; }>
56+
{{else}}
5457
* @returns CancelablePromise<T>
58+
{{/if}}
5559
* @throws ApiError
5660
*/
61+
{{#if @root.exposeHeadersAndBody}}
62+
public override request<T>(options: ApiRequestOptions): CancelablePromise<{ headers: Record<string, string>; body: T; }> {
63+
{{else}}
5764
public override request<T>(options: ApiRequestOptions): CancelablePromise<T> {
65+
{{/if}}
5866
return __request(this.config, options);
5967
}
6068
{{/equals}}

src/templates/core/fetch/request.hbs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,21 @@ import type { OpenAPIConfig } from './OpenAPI';
5959
* Request method
6060
* @param config The OpenAPI configuration object
6161
* @param options The request options from the service
62+
{{#if @root.exposeHeadersAndBody}}
63+
* @returns CancelablePromise<{ headers: Record<string, string>; body: T; }>
64+
{{else}}
6265
* @returns CancelablePromise<T>
66+
{{/if}}
6367
* @throws ApiError
6468
*/
69+
{{#if @root.exposeHeadersAndBody}}
70+
export const request = <T>(config: OpenAPIConfig, options: ApiRequestOptions): CancelablePromise<{
71+
headers: Record<string, string>;
72+
body: T;
73+
}> => {
74+
{{else}}
6575
export const request = <T>(config: OpenAPIConfig, options: ApiRequestOptions): CancelablePromise<T> => {
76+
{{/if}}
6677
return new CancelablePromise(async (resolve, reject, onCancel) => {
6778
try {
6879
const url = getUrl(config, options);
@@ -73,19 +84,34 @@ export const request = <T>(config: OpenAPIConfig, options: ApiRequestOptions): C
7384
if (!onCancel.isCancelled) {
7485
const response = await sendRequest(config, options, url, body, formData, headers, onCancel);
7586
const responseBody = await getResponseBody(response);
87+
{{#if @root.exposeHeadersAndBody}}
88+
const responseHeaders: Record<string, string> = {};
89+
for (const header of Array.from(response.headers.keys())) {
90+
responseHeaders[header] = response.headers.get(header) ?? '';
91+
}
92+
{{else}}
7693
const responseHeader = getResponseHeader(response, options.responseHeader);
94+
{{/if}}
7795

7896
const result: ApiResult = {
7997
url,
8098
ok: response.ok,
8199
status: response.status,
82100
statusText: response.statusText,
101+
{{#if @root.exposeHeadersAndBody}}
102+
body: responseBody,
103+
{{else}}
83104
body: responseHeader ?? responseBody,
105+
{{/if}}
84106
};
85107

86108
catchErrorCodes(options, result);
87109

110+
{{#if @root.exposeHeadersAndBody}}
111+
resolve({ headers: responseHeaders, body: result.body });
112+
{{else}}
88113
resolve(result.body);
114+
{{/if}}
89115
}
90116
} catch (error) {
91117
reject(error);

src/templates/core/node/request.hbs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,21 @@ import type { OpenAPIConfig } from './OpenAPI';
6363
* Request method
6464
* @param config The OpenAPI configuration object
6565
* @param options The request options from the service
66+
{{#if @root.exposeHeadersAndBody}}
67+
* @returns CancelablePromise<{ headers: Record<string, string>; body: T; }>
68+
{{else}}
6669
* @returns CancelablePromise<T>
70+
{{/if}}
6771
* @throws ApiError
6872
*/
73+
{{#if @root.exposeHeadersAndBody}}
74+
export const request = <T>(config: OpenAPIConfig, options: ApiRequestOptions): CancelablePromise<{
75+
headers: Record<string, string>;
76+
body: T;
77+
}> => {
78+
{{else}}
6979
export const request = <T>(config: OpenAPIConfig, options: ApiRequestOptions): CancelablePromise<T> => {
80+
{{/if}}
7081
return new CancelablePromise(async (resolve, reject, onCancel) => {
7182
try {
7283
const url = getUrl(config, options);
@@ -77,19 +88,34 @@ export const request = <T>(config: OpenAPIConfig, options: ApiRequestOptions): C
7788
if (!onCancel.isCancelled) {
7889
const response = await sendRequest(options, url, body, formData, headers, onCancel);
7990
const responseBody = await getResponseBody(response);
91+
{{#if @root.exposeHeadersAndBody}}
92+
const responseHeaders: Record<string, string> = {};
93+
for (const header of Array.from(response.headers.keys())) {
94+
responseHeaders[header] = response.headers.get(header) ?? '';
95+
}
96+
{{else}}
8097
const responseHeader = getResponseHeader(response, options.responseHeader);
98+
{{/if}}
8199

82100
const result: ApiResult = {
83101
url,
84102
ok: response.ok,
85103
status: response.status,
86104
statusText: response.statusText,
105+
{{#if @root.exposeHeadersAndBody}}
106+
body: responseBody,
107+
{{else}}
87108
body: responseHeader ?? responseBody,
109+
{{/if}}
88110
};
89111

90112
catchErrorCodes(options, result);
91113

114+
{{#if @root.exposeHeadersAndBody}}
115+
resolve({ headers: responseHeaders, body: result.body });
116+
{{else}}
92117
resolve(result.body);
118+
{{/if}}
93119
}
94120
} catch (error) {
95121
reject(error);

src/templates/core/xhr/request.hbs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,21 @@ import type { OpenAPIConfig } from './OpenAPI';
6262
* Request method
6363
* @param config The OpenAPI configuration object
6464
* @param options The request options from the service
65+
{{#if @root.exposeHeadersAndBody}}
66+
* @returns CancelablePromise<{ headers: Record<string, string>; body: T; }>
67+
{{else}}
6568
* @returns CancelablePromise<T>
69+
{{/if}}
6670
* @throws ApiError
6771
*/
72+
{{#if @root.exposeHeadersAndBody}}
73+
export const request = <T>(config: OpenAPIConfig, options: ApiRequestOptions): CancelablePromise<{
74+
headers: Record<string, string>;
75+
body: T;
76+
}> => {
77+
{{else}}
6878
export const request = <T>(config: OpenAPIConfig, options: ApiRequestOptions): CancelablePromise<T> => {
79+
{{/if}}
6980
return new CancelablePromise(async (resolve, reject, onCancel) => {
7081
try {
7182
const url = getUrl(config, options);
@@ -76,19 +87,36 @@ export const request = <T>(config: OpenAPIConfig, options: ApiRequestOptions): C
7687
if (!onCancel.isCancelled) {
7788
const response = await sendRequest(config, options, url, body, formData, headers, onCancel);
7889
const responseBody = getResponseBody(response);
90+
{{#if @root.exposeHeadersAndBody}}
91+
const responseHeaders: Record<string, string> = {};
92+
const allResponseHeaders = response.getAllResponseHeaders() ?? '';
93+
allResponseHeaders.split(/[\r\n]+/).forEach(line => {
94+
const nv = line.split(': ', 2);
95+
responseHeaders[nv[0]] = nv[1];
96+
});
97+
{{else}}
7998
const responseHeader = getResponseHeader(response, options.responseHeader);
99+
{{/if}}
80100

81101
const result: ApiResult = {
82102
url,
83103
ok: isSuccess(response.status),
84104
status: response.status,
85105
statusText: response.statusText,
106+
{{#if @root.exposeHeadersAndBody}}
107+
body: responseBody,
108+
{{else}}
86109
body: responseHeader ?? responseBody,
110+
{{/if}}
87111
};
88112

89113
catchErrorCodes(options, result);
90114

115+
{{#if @root.exposeHeadersAndBody}}
116+
resolve({ headers: responseHeaders, body: result.body });
117+
{{else}}
91118
resolve(result.body);
119+
{{/if}}
92120
}
93121
} catch (error) {
94122
reject(error);

src/templates/exportService.hbs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,15 +73,23 @@ export class {{{name}}}{{{@root.postfix}}} {
7373
public {{{name}}}({{>parameters}}): Observable<{{>result}}> {
7474
return this.httpRequest.request({
7575
{{else}}
76+
{{#if @root.exposeHeadersAndBody}}
77+
public {{{name}}}({{>parameters}}): CancelablePromise<{ headers: Record<string, string>; body: {{>result}}; }> {
78+
{{else}}
7679
public {{{name}}}({{>parameters}}): CancelablePromise<{{>result}}> {
80+
{{/if}}
7781
return this.httpRequest.request({
7882
{{/equals}}
7983
{{else}}
8084
{{#equals @root.httpClient 'angular'}}
8185
public {{{name}}}({{>parameters}}): Observable<{{>result}}> {
8286
return __request(OpenAPI, this.http, {
8387
{{else}}
88+
{{#if @root.exposeHeadersAndBody}}
89+
public static {{{name}}}({{>parameters}}): CancelablePromise<{ headers: Record<string, string>; body: {{>result}}; }> {
90+
{{else}}
8491
public static {{{name}}}({{>parameters}}): CancelablePromise<{{>result}}> {
92+
{{/if}}
8593
return __request(OpenAPI, {
8694
{{/equals}}
8795
{{/if}}

src/utils/writeClient.spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ describe('writeClient', () => {
4343
HttpClient.FETCH,
4444
false,
4545
false,
46+
false,
4647
true,
4748
true,
4849
true,

src/utils/writeClient.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import { writeClientServices } from './writeClientServices';
2222
* @param httpClient The selected httpClient (fetch, xhr, node or axios)
2323
* @param useOptions Use options or arguments functions
2424
* @param useUnionTypes Use union types instead of enums
25+
* @param exposeHeadersAndBody Return response headers and body (default is body only)
2526
* @param exportCore Generate core client classes
2627
* @param exportServices Generate services
2728
* @param exportModels Generate models
@@ -39,6 +40,7 @@ export const writeClient = async (
3940
httpClient: HttpClient,
4041
useOptions: boolean,
4142
useUnionTypes: boolean,
43+
exposeHeadersAndBody: boolean,
4244
exportCore: boolean,
4345
exportServices: boolean,
4446
exportModels: boolean,
@@ -61,7 +63,7 @@ export const writeClient = async (
6163
if (exportCore) {
6264
await rmdir(outputPathCore);
6365
await mkdir(outputPathCore);
64-
await writeClientCore(client, templates, outputPathCore, httpClient, indent, clientName, request);
66+
await writeClientCore(client, templates, outputPathCore, httpClient, exposeHeadersAndBody, indent, clientName, request);
6567
}
6668

6769
if (exportServices) {
@@ -74,6 +76,7 @@ export const writeClient = async (
7476
httpClient,
7577
useUnionTypes,
7678
useOptions,
79+
exposeHeadersAndBody,
7780
indent,
7881
postfix,
7982
clientName

0 commit comments

Comments
 (0)