Skip to content

Commit 24e8fe3

Browse files
committed
feat: support nextjs customized fetch
1 parent c94d2ab commit 24e8fe3

17 files changed

+154
-13
lines changed

bin/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ const params = program
1212
.version(pkg.version)
1313
.requiredOption('-i, --input <value>', 'OpenAPI specification, can be a path, url or string content (required)')
1414
.requiredOption('-o, --output <value>', 'Output directory (required)')
15-
.option('-c, --client <value>', 'HTTP client to generate [fetch, xhr, node, axios, angular]', 'fetch')
15+
.option('-c, --client <value>', 'HTTP client to generate [fetch, xhr, node, axios, angular, nextjs]', 'fetch')
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')

src/HttpClient.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ export enum HttpClient {
44
NODE = 'node',
55
AXIOS = 'axios',
66
ANGULAR = 'angular',
7+
NEXTJS = 'nextjs',
78
}

src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export type Options = {
3636
* service layer, etc.
3737
* @param input The relative ___location of the OpenAPI spec
3838
* @param output The relative ___location of the output directory
39-
* @param httpClient The selected httpClient (fetch, xhr, node or axios)
39+
* @param httpClient The selected httpClient (fetch, xhr, node, axios or nextjs)
4040
* @param clientName Custom client class name
4141
* @param useOptions Use options or arguments functions
4242
* @param useUnionTypes Use union types instead of enums

src/templates/core/ApiRequestOptions.hbs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{{>header}}
22

3-
export type ApiRequestOptions = {
3+
export type ApiRequestOptions<ClientOptions extends object = {}> = {
44
readonly method: 'GET' | 'PUT' | 'POST' | 'DELETE' | 'OPTIONS' | 'HEAD' | 'PATCH';
55
readonly url: string;
66
readonly path?: Record<string, any>;
@@ -12,4 +12,5 @@ export type ApiRequestOptions = {
1212
readonly mediaType?: string;
1313
readonly responseHeader?: string;
1414
readonly errors?: Record<number, string>;
15+
readonly clientOptions?: ClientOptions;
1516
};

src/templates/core/nextjs/request.hbs

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
{{>header}}
2+
3+
import { ApiError } from './ApiError';
4+
import type { ApiRequestOptions } from './ApiRequestOptions';
5+
import type { ApiResult } from './ApiResult';
6+
import { CancelablePromise } from './CancelablePromise';
7+
import type { OnCancel } from './CancelablePromise';
8+
import type { OpenAPIConfig } from './OpenAPI';
9+
10+
{{>functions/isDefined}}
11+
12+
13+
{{>functions/isString}}
14+
15+
16+
{{>functions/isStringWithValue}}
17+
18+
19+
{{>functions/isBlob}}
20+
21+
22+
{{>functions/isFormData}}
23+
24+
25+
{{>functions/base64}}
26+
27+
28+
{{>functions/getQueryString}}
29+
30+
31+
{{>functions/getUrl}}
32+
33+
34+
{{>functions/getFormData}}
35+
36+
37+
{{>functions/resolve}}
38+
39+
40+
{{>fetch/getHeaders}}
41+
42+
43+
{{>fetch/getRequestBody}}
44+
45+
46+
{{>nextjs/sendRequest}}
47+
48+
49+
{{>fetch/getResponseHeader}}
50+
51+
52+
{{>fetch/getResponseBody}}
53+
54+
55+
{{>functions/catchErrorCodes}}
56+
57+
interface ClientOptions {
58+
cache?: 'force-cache' | 'no-store';
59+
next?: {
60+
revalidate?: false | number;
61+
tags?: Array<string>;
62+
};
63+
}
64+
65+
/**
66+
* Request method
67+
* @param config The OpenAPI configuration object
68+
* @param options The request options from the service
69+
* @returns CancelablePromise<T>
70+
* @throws ApiError
71+
*/
72+
export const request = <T>(config: OpenAPIConfig, options: ApiRequestOptions<ClientOptions>): CancelablePromise<T> => {
73+
return new CancelablePromise(async (resolve, reject, onCancel) => {
74+
try {
75+
const url = getUrl(config, options);
76+
const formData = getFormData(options);
77+
const body = getRequestBody(options);
78+
const headers = await getHeaders(config, options);
79+
80+
if (!onCancel.isCancelled) {
81+
const response = await sendRequest(config, options, url, body, formData, headers, onCancel);
82+
const responseBody = await getResponseBody(response);
83+
const responseHeader = getResponseHeader(response, options.responseHeader);
84+
85+
const result: ApiResult = {
86+
url,
87+
ok: response.ok,
88+
status: response.status,
89+
statusText: response.statusText,
90+
body: responseHeader ?? responseBody,
91+
};
92+
93+
catchErrorCodes(options, result);
94+
95+
resolve(result.body);
96+
}
97+
} catch (error) {
98+
reject(error);
99+
}
100+
});
101+
};
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
export const sendRequest = async (
2+
config: OpenAPIConfig,
3+
options: ApiRequestOptions,
4+
url: string,
5+
body: any,
6+
formData: FormData | undefined,
7+
headers: Headers,
8+
onCancel: OnCancel
9+
): Promise<Response> => {
10+
const controller = new AbortController();
11+
12+
const request: RequestInit = {
13+
headers,
14+
body: body ?? formData,
15+
method: options.method,
16+
signal: controller.signal,
17+
cache: options.cache,
18+
next: options.next,
19+
};
20+
21+
if (config.WITH_CREDENTIALS) {
22+
request.credentials = config.CREDENTIALS;
23+
}
24+
25+
onCancel(() => controller.abort());
26+
27+
return await fetch(url, request);
28+
};

src/templates/core/request.hbs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
{{~#equals @root.httpClient 'axios'}}{{>axios/request}}{{/equals~}}
44
{{~#equals @root.httpClient 'angular'}}{{>angular/request}}{{/equals~}}
55
{{~#equals @root.httpClient 'node'}}{{>node/request}}{{/equals~}}
6+
{{~#equals @root.httpClient 'nextjs'}}{{>nextjs/request}}{{/equals~}}

src/utils/getHttpRequestName.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { HttpClient } from '../HttpClient';
22

33
/**
44
* Generate the HttpRequest filename based on the selected client
5-
* @param httpClient The selected httpClient (fetch, xhr, node or axios)
5+
* @param httpClient The selected httpClient (fetch, xhr, node, axios or nextjs)
66
*/
77
export const getHttpRequestName = (httpClient: HttpClient): string => {
88
switch (httpClient) {

src/utils/registerHandlebarTemplates.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ import functionIsStringWithValue from '../templates/core/functions/isStringWithV
3838
import functionIsSuccess from '../templates/core/functions/isSuccess.hbs';
3939
import functionResolve from '../templates/core/functions/resolve.hbs';
4040
import templateCoreHttpRequest from '../templates/core/HttpRequest.hbs';
41+
import nextjsRequest from '../templates/core/nextjs/request.hbs';
42+
import nextjsSendRequest from '../templates/core/nextjs/sendRequest.hbs';
4143
import nodeGetHeaders from '../templates/core/node/getHeaders.hbs';
4244
import nodeGetRequestBody from '../templates/core/node/getRequestBody.hbs';
4345
import nodeGetResponseBody from '../templates/core/node/getResponseBody.hbs';
@@ -188,6 +190,10 @@ export const registerHandlebarTemplates = (root: {
188190
Handlebars.registerPartial('fetch/sendRequest', Handlebars.template(fetchSendRequest));
189191
Handlebars.registerPartial('fetch/request', Handlebars.template(fetchRequest));
190192

193+
// Specific files for the nextjs client implementation
194+
Handlebars.registerPartial('nextjs/sendRequest', Handlebars.template(nextjsSendRequest));
195+
Handlebars.registerPartial('nextjs/request', Handlebars.template(nextjsRequest));
196+
191197
// Specific files for the xhr client implementation
192198
Handlebars.registerPartial('xhr/getHeaders', Handlebars.template(xhrGetHeaders));
193199
Handlebars.registerPartial('xhr/getRequestBody', Handlebars.template(xhrGetRequestBody));

src/utils/writeClient.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import { writeClientServices } from './writeClientServices';
1919
* @param client Client object with all the models, services, etc.
2020
* @param templates Templates wrapper with all loaded Handlebars templates
2121
* @param output The relative ___location of the output directory
22-
* @param httpClient The selected httpClient (fetch, xhr, node or axios)
22+
* @param httpClient The selected httpClient (fetch, xhr, node, axios or nextjs)
2323
* @param useOptions Use options or arguments functions
2424
* @param useUnionTypes Use union types instead of enums
2525
* @param exportCore Generate core client classes

0 commit comments

Comments
 (0)