Skip to content

Commit 1c7decf

Browse files
authored
Merge pull request #2 from fullystudios/nextjsfetch
Nextjsfetch
2 parents 42a51ec + aec4134 commit 1c7decf

17 files changed

+268
-5
lines changed

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
⚠️ this is just a fork to add some options to `fetch` client. See last few commits on this branch:
2+
3+
https://github.com/justin-calleja/openapi-typescript-codegen/tree/nextjsfetch
4+
15
# OpenAPI Typescript Codegen
26

37
[![NPM][npm-image]][npm-url]
@@ -38,7 +42,7 @@ $ openapi --help
3842
-V, --version output the version number
3943
-i, --input <value> OpenAPI specification, can be a path, url or string content (required)
4044
-o, --output <value> Output directory (required)
41-
-c, --client <value> HTTP client to generate [fetch, xhr, node, axios, angular] (default: "fetch")
45+
-c, --client <value> HTTP client to generate [nextjs_fetch, fetch, xhr, node, axios, angular] (default: "fetch")
4246
--name <value> Custom client class name
4347
--useOptions Use options instead of arguments
4448
--useUnionTypes Use union types instead of enums

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 [nextjs_fetch, fetch, xhr, node, axios, angular]', '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')

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
"version": "0.27.0",
44
"description": "Library that generates Typescript clients based on the OpenAPI specification.",
55
"author": "Ferdi Koomen",
6-
"homepage": "https://github.com/ferdikoomen/openapi-typescript-codegen",
6+
"homepage": "https://github.com/justin-calleja/openapi-typescript-codegen/tree/nextjsfetch",
77
"repository": {
88
"type": "git",
9-
"url": "git+https://github.com/ferdikoomen/openapi-typescript-codegen.git"
9+
"url": "git+http/github.com/ferdikoomen/openapi-typescript-codegen.git"
1010
},
1111
"bugs": {
1212
"url": "https://github.com/ferdikoomen/openapi-typescript-codegen/issues"

src/HttpClient.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
export enum HttpClient {
22
FETCH = 'fetch',
33
XHR = 'xhr',
4+
NEXTJS_FETCH = 'nextjs_fetch',
45
NODE = 'node',
56
AXIOS = 'axios',
67
ANGULAR = 'angular',

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 (nextjs_fetch, fetch, xhr, node or axios)
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: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,23 @@
11
{{>header}}
22

3+
4+
{{#equals @root.httpClient 'nextjs_fetch'}}
5+
export type ApiRequestOptions = {
6+
readonly method: 'GET' | 'PUT' | 'POST' | 'DELETE' | 'OPTIONS' | 'HEAD' | 'PATCH';
7+
readonly url: string;
8+
readonly path?: Record<string, any>;
9+
readonly cookies?: Record<string, any>;
10+
readonly headers?: Record<string, any>;
11+
readonly query?: Record<string, any>;
12+
readonly formData?: Record<string, any>;
13+
readonly body?: any;
14+
readonly mediaType?: string;
15+
readonly responseHeader?: string;
16+
readonly errors?: Record<number, string>;
17+
readonly cache?: RequestInit['cache']
18+
readonly next?: { revalidate: number }
19+
};
20+
{{else}}
321
export type ApiRequestOptions = {
422
readonly method: 'GET' | 'PUT' | 'POST' | 'DELETE' | 'OPTIONS' | 'HEAD' | 'PATCH';
523
readonly url: string;
@@ -13,3 +31,4 @@ export type ApiRequestOptions = {
1331
readonly responseHeader?: string;
1432
readonly errors?: Record<number, string>;
1533
};
34+
{{/equals}}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
export const getHeaders = async (config: OpenAPIConfig, options: ApiRequestOptions): Promise<Headers> => {
2+
const token = await resolve(options, config.TOKEN);
3+
const username = await resolve(options, config.USERNAME);
4+
const password = await resolve(options, config.PASSWORD);
5+
const additionalHeaders = await resolve(options, config.HEADERS);
6+
7+
const headers = Object.entries({
8+
Accept: 'application/json',
9+
...additionalHeaders,
10+
...options.headers,
11+
})
12+
.filter(([_, value]) => isDefined(value))
13+
.reduce((headers, [key, value]) => ({
14+
...headers,
15+
[key]: String(value),
16+
}), {} as Record<string, string>);
17+
18+
if (isStringWithValue(token)) {
19+
headers['Authorization'] = `Bearer ${token}`;
20+
}
21+
22+
if (isStringWithValue(username) && isStringWithValue(password)) {
23+
const credentials = base64(`${username}:${password}`);
24+
headers['Authorization'] = `Basic ${credentials}`;
25+
}
26+
27+
if (options.body) {
28+
if (options.mediaType) {
29+
headers['Content-Type'] = options.mediaType;
30+
} else if (isBlob(options.body)) {
31+
headers['Content-Type'] = options.body.type || 'application/octet-stream';
32+
} else if (isString(options.body)) {
33+
headers['Content-Type'] = 'text/plain';
34+
} else if (!isFormData(options.body)) {
35+
headers['Content-Type'] = 'application/json';
36+
}
37+
}
38+
39+
return new Headers(headers);
40+
};
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
export const getRequestBody = (options: ApiRequestOptions): any => {
2+
if (options.body !== undefined) {
3+
if (options.mediaType?.includes('/json')) {
4+
return JSON.stringify(options.body)
5+
} else if (isString(options.body) || isBlob(options.body) || isFormData(options.body)) {
6+
return options.body;
7+
} else {
8+
return JSON.stringify(options.body);
9+
}
10+
}
11+
return undefined;
12+
};
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
export const getResponseBody = async (response: Response): Promise<any> => {
2+
if (response.status !== 204) {
3+
try {
4+
const contentType = response.headers.get('Content-Type');
5+
if (contentType) {
6+
const jsonTypes = ['application/json', 'application/problem+json']
7+
const isJSON = jsonTypes.some(type => contentType.toLowerCase().startsWith(type));
8+
if (isJSON) {
9+
return await response.json();
10+
} else {
11+
return await response.text();
12+
}
13+
}
14+
} catch (error) {
15+
console.error(error);
16+
}
17+
}
18+
return undefined;
19+
};
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export const getResponseHeader = (response: Response, responseHeader?: string): string | undefined => {
2+
if (responseHeader) {
3+
const content = response.headers.get(responseHeader);
4+
if (isString(content)) {
5+
return content;
6+
}
7+
}
8+
return undefined;
9+
};

0 commit comments

Comments
 (0)