Skip to content

Commit 8fb9a1a

Browse files
committed
feat: add ofetch http client
1 parent 2b6db23 commit 8fb9a1a

File tree

16 files changed

+70670
-3
lines changed

16 files changed

+70670
-3
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ Options:
6868
--disableStrictSSL disabled strict SSL (default: false)
6969
--disableProxy disabled proxy (default: false)
7070
--axios generate axios http client (default: false)
71+
--ofetch generate ofetch http client (default: false)
7172
--unwrap-response-data unwrap the data item from the response (default: false)
7273
--disable-throw-on-error Do not throw an error when response.ok is not true (default: false)
7374
--single-http-client Ability to send HttpClient instance to Api constructor (default: false)

index.d.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {MonoSchemaParser} from "./src/schema-parser/mono-schema-parser";
22

3-
type HttpClientType = "axios" | "fetch";
3+
type HttpClientType = "axios" | "fetch" | "ofetch";
44

55
interface GenerateApiParamsBase {
66
/**

index.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,11 @@ const program = cli({
162162
description: 'generate axios http client',
163163
default: codeGenBaseConfig.httpClientType === HTTP_CLIENT.AXIOS,
164164
},
165+
{
166+
flags: 'ofetch',
167+
description: 'generate ofetch http client',
168+
default: codeGenBaseConfig.httpClientType === HTTP_CLIENT.OFETCH,
169+
},
165170
{
166171
flags: '--unwrap-response-data',
167172
description: 'unwrap the data item from the response',
@@ -342,7 +347,6 @@ const main = async () => {
342347
} catch (e) {
343348
console.error(e);
344349
process.exit(1);
345-
return;
346350
}
347351
process.exit(0);
348352
};

package-lock.json

+31-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+3
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,11 @@
4545
"test:jsSingleHttpClientModular": "node tests/spec/jsSingleHttpClientModular/test.js",
4646
"test:--js--axios": "node tests/spec/jsAxios/test.js",
4747
"test:--axios": "node tests/spec/axios/test.js",
48+
"test:--ofetch": "node tests/spec/ofetch/test.js",
4849
"test:--another-array-type": "node tests/spec/another-array-type/test.js",
4950
"test:--object-types": "node tests/spec/object-types/test.js",
5051
"test:--axios--single-http-client": "node tests/spec/axiosSingleHttpClient/test.js",
52+
"test:--ofetch--single-http-client": "node tests/spec/ofetchSingleHttpClient/test.js",
5153
"test:--type-suffix--type-prefix": "node tests/spec/typeSuffixPrefix/test.js",
5254
"test:--dot-path-params": "node tests/spec/dot-path-params/test.js",
5355
"test:--primitive-type-constructs": "node tests/spec/primitive-type-constructs/test.js",
@@ -81,6 +83,7 @@
8183
"@types/prettier": "^2.7.3",
8284
"all-contributors-cli": "^6.26.1",
8385
"axios": "^1.4.0",
86+
"ofetch": "^1.3.4",
8487
"cross-env": "^7.0.3",
8588
"dotenv": "^16.3.1",
8689
"git-diff": "^2.0.6",

src/constants.js

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ const SCHEMA_TYPES = {
2727

2828
const HTTP_CLIENT = {
2929
FETCH: 'fetch',
30+
OFETCH: 'ofetch',
3031
AXIOS: 'axios',
3132
};
3233

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
<%
2+
const { apiConfig, generateResponses, config } = it;
3+
%>
4+
5+
import type { $Fetch, FetchOptions } from 'ofetch'
6+
import { $fetch } from 'ofetch'
7+
8+
export type QueryParamsType = Record<string | number, any>;
9+
export type ResponseFormat = keyof Omit<Body, "body" | "bodyUsed">;
10+
11+
export interface CustomFetchOptions extends FetchOptions {
12+
/** set parameter to `true` for call `securityWorker` for this request */
13+
secure?: boolean
14+
}
15+
16+
export type RequestParams = Omit<CustomFetchOptions, 'body' | 'method'>
17+
18+
export interface ApiConfig<SecurityDataType = unknown> {
19+
baseURL?: string;
20+
basePath?: string;
21+
baseSiteId?: string;
22+
baseApiParams?: Omit<RequestParams, "baseURL" | "cancelToken" | "signal">;
23+
securityWorker?: (securityData: SecurityDataType | null) => Promise<RequestParams | void> | RequestParams | void;
24+
customFetch?: $Fetch;
25+
}
26+
27+
type CancelToken = Symbol | string | number;
28+
29+
export enum ContentType {
30+
Json = "application/json",
31+
FormData = "multipart/form-data",
32+
UrlEncoded = "application/x-www-form-urlencoded",
33+
}
34+
35+
export class HttpClient<SecurityDataType = unknown> {
36+
public baseURL: string = "<%~ apiConfig.baseUrl %>";
37+
private securityData: SecurityDataType | null = null;
38+
private securityWorker?: ApiConfig<SecurityDataType>["securityWorker"];
39+
private abortControllers = new Map<CancelToken, AbortController>();
40+
private customFetch = (url: string, fetchParams: FetchOptions) => $fetch(url, fetchParams)
41+
public basePath: string = "<%~ apiConfig.baseUrl.replace('https://{url}', '') %>";
42+
public baseSiteId: string = 'roller';
43+
44+
private baseApiParams: RequestParams = {
45+
credentials: 'same-origin',
46+
headers: {},
47+
redirect: 'follow',
48+
referrerPolicy: 'no-referrer',
49+
}
50+
51+
constructor(apiConfig: ApiConfig<SecurityDataType> = {}) {
52+
Object.assign(this, apiConfig);
53+
}
54+
55+
public setSecurityData = (data: SecurityDataType | null) => {
56+
this.securityData = data;
57+
}
58+
59+
protected mergeRequestParams(params1: RequestParams, params2?: RequestParams): RequestParams {
60+
return {
61+
...this.baseApiParams,
62+
...params1,
63+
...(params2 || {}),
64+
headers: {
65+
...(this.baseApiParams.headers || {}),
66+
...(params1.headers || {}),
67+
...((params2 && params2.headers) || {}),
68+
},
69+
};
70+
}
71+
72+
protected createAbortSignal = (cancelToken: CancelToken): AbortSignal | undefined => {
73+
if (this.abortControllers.has(cancelToken)) {
74+
const abortController = this.abortControllers.get(cancelToken);
75+
if (abortController) {
76+
return abortController.signal;
77+
}
78+
return void 0;
79+
}
80+
81+
const abortController = new AbortController();
82+
this.abortControllers.set(cancelToken, abortController);
83+
return abortController.signal;
84+
}
85+
86+
public abortRequest = (cancelToken: CancelToken) => {
87+
const abortController = this.abortControllers.get(cancelToken)
88+
89+
if (abortController) {
90+
abortController.abort();
91+
this.abortControllers.delete(cancelToken);
92+
}
93+
}
94+
95+
public request = async <T = any>(url: string, {
96+
body,
97+
secure,
98+
method,
99+
baseURL,
100+
signal,
101+
params,
102+
...options
103+
<% if (config.unwrapResponseData) { %>
104+
}: CustomFetchOptions): Promise<T> => {
105+
<% } else { %>
106+
}: CustomFetchOptions): Promise<T> => {
107+
<% } %>
108+
const secureParams = ((typeof secure === 'boolean' ? secure : this.baseApiParams.secure) && this.securityWorker && await this.securityWorker(this.securityData)) || {};
109+
const requestOptions = this.mergeRequestParams(options, secureParams)
110+
111+
return this.customFetch(
112+
`${baseURL || this.baseURL || ""}${this.basePath ? `${this.basePath}` : ''}${url}`,
113+
{
114+
params,
115+
method,
116+
...requestOptions,
117+
signal,
118+
body,
119+
}
120+
<% if (config.unwrapResponseData) { %>
121+
).then((response: T) => response.data)
122+
<% } else { %>
123+
).then((response: T) => response)
124+
<% } %>
125+
};
126+
}

templates/default/procedure-call.ejs

+7
Original file line numberDiff line numberDiff line change
@@ -88,13 +88,20 @@ const describeReturnType = () => {
8888

8989
*/
9090
<%~ route.routeName.usage %><%~ route.namespace ? ': ' : ' = ' %>(<%~ wrapperArgs %>)<%~ config.toJS ? `: ${describeReturnType()}` : "" %> =>
91+
<% if (config.httpClientType === config.constants.HTTP_CLIENT.OFETCH) { %>
92+
<%~ config.singleHttpClient ? 'this.http.request' : 'this.request' %><<%~ type %>>(`<%~ path %>`, {
93+
<% } %>
94+
<% if (config.httpClientType !== config.constants.HTTP_CLIENT.OFETCH) { %>
9195
<%~ config.singleHttpClient ? 'this.http.request' : 'this.request' %><<%~ type %>, <%~ errorType %>>({
9296
path: `<%~ path %>`,
97+
<% } %>
9398
method: '<%~ _.upperCase(method) %>',
9499
<%~ queryTmpl ? `query: ${queryTmpl},` : '' %>
95100
<%~ bodyTmpl ? `body: ${bodyTmpl},` : '' %>
96101
<%~ securityTmpl ? `secure: ${securityTmpl},` : '' %>
102+
<% if (config.httpClientType !== config.constants.HTTP_CLIENT.OFETCH) { %>
97103
<%~ bodyContentKindTmpl ? `type: ${bodyContentKindTmpl},` : '' %>
98104
<%~ responseFormatTmpl ? `format: ${responseFormatTmpl},` : '' %>
105+
<% } %>
99106
...<%~ _.get(requestConfigParam, "name") %>,
100107
})<%~ route.namespace ? ',' : '' %>

0 commit comments

Comments
 (0)