Skip to content

Commit 4b809f3

Browse files
js2mesushruthStynStijnLammens
authored
Release 8.0.0 (#216)
* BREAKING_CHANGES: remove default `json` format of the response type * fix: missing `schema.$ref` in inline enum schemas * Allow passing custom fetch function (#218) * Allow passing custom fetch function * Fixing a mistake * Using ApiConfig instead of second param * fix: tests * chore: refresh schemas * Fix: query param array serialization (#223) * make the query params serialization conform to the default open api specs * uri encode second part Co-authored-by: stijn.lammens <[email protected]> * docs: update CHANGELOG * fix: unused E generic type * chore: refresh generated test schemas * bump: up version to 8.0.0 Co-authored-by: Sushruth Shastry <[email protected]> Co-authored-by: Stijn Lammens <[email protected]> Co-authored-by: stijn.lammens <[email protected]>
1 parent 8329c4b commit 4b809f3

File tree

74 files changed

+1626
-1395
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

74 files changed

+1626
-1395
lines changed

CHANGELOG.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,23 @@
11
# next release
22

3+
# 8.0.0
4+
5+
BREAKING_CHANGES:
6+
- remove default `json` format of the response type (both for `axios` and `fetch` http clients) (issue #213, thanks @po5i)
7+
8+
Features:
9+
- Allow passing custom fetch function (`fetch` http client only)
10+
- Allow to set global response type format through `HttpClient` constructor
11+
Example:
12+
```ts
13+
const httpClient = new HttpClient({ format: 'json' });
14+
// all request responses will been formatted as json
15+
```
16+
Fixes:
17+
- Missing `schema.$ref` in inline enum schemas
18+
- Array query param values are serialized with the (non-default) comma separated style (issue #222, thanks @Styn, PR #223)
19+
- TypeScript error "TS6133: 'E' is declared but its value is never read." (`axios` http client) (issue #220, thanks @pmbednarczyk )
20+
321
# 7.0.1
422

523
Fixes:

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "swagger-typescript-api",
3-
"version": "7.0.1",
3+
"version": "8.0.0",
44
"description": "Generate typescript/javascript api from swagger schema",
55
"scripts": {
66
"cli:json": "node index.js -r -d -p ./swagger-test-cli.json -n swagger-test-cli.ts",
@@ -9,8 +9,8 @@
99
"node:debug": "node --nolazy swagger-test-cli/generate.js",
1010
"contributors": "all-contributors generate",
1111
"cli:help": "node index.js -h",
12-
"test-all": "node ./node_modules/npm-run-all/bin/npm-run-all/index.js generate validate test:* --continue-on-error",
13-
"test-specific": "node ./node_modules/npm-run-all/bin/npm-run-all/index.js test:* --continue-on-error",
12+
"test-all": "node ./node_modules/npm-run-all/bin/npm-run-all/index.js generate validate test:*",
13+
"test-specific": "node ./node_modules/npm-run-all/bin/npm-run-all/index.js generate validate test:*",
1414
"generate": "node tests/generate.js",
1515
"generate:debug": "node --nolazy tests/generate.js",
1616
"validate": "node tests/validate.js",

src/schema.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,8 @@ const attachParsedRef = (originalSchema, parsedSchema) => {
235235

236236
const schemaParsers = {
237237
[SCHEMA_TYPES.ENUM]: (schema, typeName) => {
238+
const refType = getRefType(schema);
239+
const $ref = (refType && refType.$ref) || null;
238240
const enumNamesAsValues = config.enumNamesAsValues;
239241
const keyType = getType(schema);
240242
const enumNames = getEnumNames(schema);
@@ -277,6 +279,8 @@ const schemaParsers = {
277279

278280
return attachParsedRef(schema, {
279281
...(_.isObject(schema) ? schema : {}),
282+
$ref: $ref,
283+
typeName: ($ref && refType.typeName) || null,
280284
$parsedSchema: true,
281285
schemaType: SCHEMA_TYPES.ENUM,
282286
type: SCHEMA_TYPES.ENUM,

src/typeFormatters.js

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,14 @@ const inlineExtraFormatters = {
5757
[SCHEMA_TYPES.ENUM]: (parsedSchema) => {
5858
return {
5959
...parsedSchema,
60-
content: _.uniq(
61-
_.compact([
62-
..._.map(parsedSchema.content, ({ value }) => `${value}`),
63-
parsedSchema.nullable && TS_KEYWORDS.NULL,
64-
]),
65-
).join(" | "),
60+
content: parsedSchema.$ref
61+
? parsedSchema.typeName
62+
: _.uniq(
63+
_.compact([
64+
..._.map(parsedSchema.content, ({ value }) => `${value}`),
65+
parsedSchema.nullable && TS_KEYWORDS.NULL,
66+
]),
67+
).join(" | "),
6668
};
6769
},
6870
};

templates/base/http-clients/axios-http-client.eta

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export type RequestParams = Omit<FullRequestParams, "body" | "method" | "query"
2626
export interface ApiConfig<SecurityDataType = unknown> extends Omit<AxiosRequestConfig, "data" | "cancelToken"> {
2727
securityWorker?: (securityData: SecurityDataType | null) => Promise<AxiosRequestConfig | void> | AxiosRequestConfig | void;
2828
secure?: boolean;
29+
format?: ResponseType;
2930
}
3031

3132
export enum ContentType {
@@ -39,10 +40,12 @@ export class HttpClient<SecurityDataType = unknown> {
3940
private securityData: SecurityDataType | null = null;
4041
private securityWorker?: ApiConfig<SecurityDataType>["securityWorker"];
4142
private secure?: boolean;
43+
private format?: ResponseType;
4244

43-
constructor({ securityWorker, secure, ...axiosConfig }: ApiConfig<SecurityDataType> = {}) {
45+
constructor({ securityWorker, secure, format, ...axiosConfig }: ApiConfig<SecurityDataType> = {}) {
4446
this.instance = axios.create({ ...axiosConfig, baseURL: axiosConfig.baseURL || "<%~ apiConfig.baseUrl %>" })
4547
this.secure = secure;
48+
this.format = format;
4649
this.securityWorker = securityWorker;
4750
}
4851

@@ -63,17 +66,18 @@ export class HttpClient<SecurityDataType = unknown> {
6366
};
6467
}
6568

66-
public request = async <T = any, E = any>({
69+
public request = async <T = any, _E = any>({
6770
secure,
6871
path,
6972
type,
7073
query,
71-
format = "json",
74+
format,
7275
body,
7376
...params
7477
}: FullRequestParams): Promise<AxiosResponse<T>> => {
7578
const secureParams = ((typeof secure === 'boolean' ? secure : this.secure) && this.securityWorker && (await this.securityWorker(this.securityData))) || {};
7679
const requestParams = this.mergeRequestParams(params, secureParams);
80+
const responseFormat = (format && this.format) || void 0;
7781

7882
return this.instance.request({
7983
...requestParams,
@@ -82,7 +86,7 @@ export class HttpClient<SecurityDataType = unknown> {
8286
...(requestParams.headers || {}),
8387
},
8488
params: query,
85-
responseType: format,
89+
responseType: responseFormat,
8690
data: body,
8791
url: path,
8892
});

templates/base/http-clients/fetch-http-client.eta

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ export interface ApiConfig<SecurityDataType = unknown> {
3131
baseUrl?: string;
3232
baseApiParams?: Omit<RequestParams, "baseUrl" | "cancelToken" | "signal">;
3333
securityWorker?: (securityData: SecurityDataType | null) => Promise<RequestParams | void> | RequestParams | void;
34+
customFetch?: (input: RequestInfo, init?: RequestInit) => Promise<Response>
3435
}
3536

3637
export interface HttpResponse<D extends unknown, E extends unknown = unknown> extends Response {
@@ -51,6 +52,7 @@ export class HttpClient<SecurityDataType = unknown> {
5152
private securityData: SecurityDataType | null = null;
5253
private securityWorker?: ApiConfig<SecurityDataType>["securityWorker"];
5354
private abortControllers = new Map<CancelToken, AbortController>();
55+
private customFetch = fetch;
5456

5557
private baseApiParams: RequestParams = {
5658
credentials: 'same-origin',
@@ -67,16 +69,10 @@ export class HttpClient<SecurityDataType = unknown> {
6769
this.securityData = data;
6870
}
6971

70-
private addQueryParam(query: QueryParamsType, key: string) {
72+
private addArrayQueryParam(query: QueryParamsType, key: string) {
7173
const value = query[key];
72-
73-
return (
74-
encodeURIComponent(key) + "=" + encodeURIComponent(
75-
Array.isArray(value) ? value.join(",") :
76-
typeof value === "number" ? value :
77-
`${value}`
78-
)
79-
);
74+
const encodedKey = encodeURIComponent(key);
75+
return `${value.map((val: any) => `${encodedKey}=${encodeURIComponent(typeof val === "number" ? val : `${val}`)}`).join('&')}`;
8076
}
8177

8278
protected toQueryString(rawQuery?: QueryParamsType): string {
@@ -86,7 +82,7 @@ export class HttpClient<SecurityDataType = unknown> {
8682
.map((key) =>
8783
typeof query[key] === "object" && !Array.isArray(query[key])
8884
? this.toQueryString(query[key] as QueryParamsType)
89-
: this.addQueryParam(query, key),
85+
: this.addArrayQueryParam(query, key),
9086
)
9187
.join("&");
9288
}
@@ -118,7 +114,7 @@ export class HttpClient<SecurityDataType = unknown> {
118114
},
119115
};
120116
}
121-
117+
122118
private createAbortSignal = (cancelToken: CancelToken): AbortSignal | undefined => {
123119
if (this.abortControllers.has(cancelToken)) {
124120
const abortController = this.abortControllers.get(cancelToken);
@@ -127,7 +123,7 @@ export class HttpClient<SecurityDataType = unknown> {
127123
}
128124
return void 0;
129125
}
130-
126+
131127
const abortController = new AbortController();
132128
this.abortControllers.set(cancelToken, abortController);
133129
return abortController.signal;
@@ -141,14 +137,14 @@ export class HttpClient<SecurityDataType = unknown> {
141137
this.abortControllers.delete(cancelToken);
142138
}
143139
}
144-
140+
145141
public request = async <T = any, E = any>({
146142
body,
147143
secure,
148144
path,
149145
type,
150146
query,
151-
format = "json",
147+
format,
152148
baseUrl,
153149
cancelToken,
154150
...params
@@ -157,8 +153,9 @@ export class HttpClient<SecurityDataType = unknown> {
157153
const requestParams = this.mergeRequestParams(params, secureParams);
158154
const queryString = query && this.toQueryString(query);
159155
const payloadFormatter = this.contentFormatters[type || ContentType.Json];
156+
const responseFormat = format && requestParams.format;
160157

161-
return fetch(
158+
return this.customFetch(
162159
`${baseUrl || this.baseUrl || ""}${path}${queryString ? `?${queryString}` : ""}`,
163160
{
164161
...requestParams,
@@ -174,7 +171,7 @@ export class HttpClient<SecurityDataType = unknown> {
174171
r.data = (null as unknown) as T;
175172
r.error = (null as unknown) as E;
176173

177-
const data = await response[format]()
174+
const data = !responseFormat ? r : await response[responseFormat]()
178175
.then((data) => {
179176
if (r.ok) {
180177
r.data = data;
@@ -187,7 +184,7 @@ export class HttpClient<SecurityDataType = unknown> {
187184
r.error = e;
188185
return r;
189186
});
190-
187+
191188
if (cancelToken) {
192189
this.abortControllers.delete(cancelToken);
193190
}

tests/generated/v2.0/adafruit.ts

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ export interface ApiConfig<SecurityDataType = unknown> {
192192
baseUrl?: string;
193193
baseApiParams?: Omit<RequestParams, "baseUrl" | "cancelToken" | "signal">;
194194
securityWorker?: (securityData: SecurityDataType | null) => Promise<RequestParams | void> | RequestParams | void;
195+
customFetch?: (input: RequestInfo, init?: RequestInit) => Promise<Response>;
195196
}
196197

197198
export interface HttpResponse<D extends unknown, E extends unknown = unknown> extends Response {
@@ -212,6 +213,7 @@ export class HttpClient<SecurityDataType = unknown> {
212213
private securityData: SecurityDataType | null = null;
213214
private securityWorker?: ApiConfig<SecurityDataType>["securityWorker"];
214215
private abortControllers = new Map<CancelToken, AbortController>();
216+
private customFetch = fetch;
215217

216218
private baseApiParams: RequestParams = {
217219
credentials: "same-origin",
@@ -228,14 +230,12 @@ export class HttpClient<SecurityDataType = unknown> {
228230
this.securityData = data;
229231
};
230232

231-
private addQueryParam(query: QueryParamsType, key: string) {
233+
private addArrayQueryParam(query: QueryParamsType, key: string) {
232234
const value = query[key];
233-
234-
return (
235-
encodeURIComponent(key) +
236-
"=" +
237-
encodeURIComponent(Array.isArray(value) ? value.join(",") : typeof value === "number" ? value : `${value}`)
238-
);
235+
const encodedKey = encodeURIComponent(key);
236+
return `${value
237+
.map((val: any) => `${encodedKey}=${encodeURIComponent(typeof val === "number" ? val : `${val}`)}`)
238+
.join("&")}`;
239239
}
240240

241241
protected toQueryString(rawQuery?: QueryParamsType): string {
@@ -245,7 +245,7 @@ export class HttpClient<SecurityDataType = unknown> {
245245
.map((key) =>
246246
typeof query[key] === "object" && !Array.isArray(query[key])
247247
? this.toQueryString(query[key] as QueryParamsType)
248-
: this.addQueryParam(query, key),
248+
: this.addArrayQueryParam(query, key),
249249
)
250250
.join("&");
251251
}
@@ -308,7 +308,7 @@ export class HttpClient<SecurityDataType = unknown> {
308308
path,
309309
type,
310310
query,
311-
format = "json",
311+
format,
312312
baseUrl,
313313
cancelToken,
314314
...params
@@ -321,8 +321,9 @@ export class HttpClient<SecurityDataType = unknown> {
321321
const requestParams = this.mergeRequestParams(params, secureParams);
322322
const queryString = query && this.toQueryString(query);
323323
const payloadFormatter = this.contentFormatters[type || ContentType.Json];
324+
const responseFormat = format && requestParams.format;
324325

325-
return fetch(`${baseUrl || this.baseUrl || ""}${path}${queryString ? `?${queryString}` : ""}`, {
326+
return this.customFetch(`${baseUrl || this.baseUrl || ""}${path}${queryString ? `?${queryString}` : ""}`, {
326327
...requestParams,
327328
headers: {
328329
...(type && type !== ContentType.FormData ? { "Content-Type": type } : {}),
@@ -335,19 +336,21 @@ export class HttpClient<SecurityDataType = unknown> {
335336
r.data = (null as unknown) as T;
336337
r.error = (null as unknown) as E;
337338

338-
const data = await response[format]()
339-
.then((data) => {
340-
if (r.ok) {
341-
r.data = data;
342-
} else {
343-
r.error = data;
344-
}
345-
return r;
346-
})
347-
.catch((e) => {
348-
r.error = e;
349-
return r;
350-
});
339+
const data = !responseFormat
340+
? r
341+
: await response[responseFormat]()
342+
.then((data) => {
343+
if (r.ok) {
344+
r.data = data;
345+
} else {
346+
r.error = data;
347+
}
348+
return r;
349+
})
350+
.catch((e) => {
351+
r.error = e;
352+
return r;
353+
});
351354

352355
if (cancelToken) {
353356
this.abortControllers.delete(cancelToken);

0 commit comments

Comments
 (0)