Skip to content

Commit 21c64fd

Browse files
authored
Release 5.1.0 (#157)
* chore: make exportable ApiConfig interface; chore: change eslint-disable line at first line of generated file * feat: --single-http-client option which allows to send HttpClient instance to Api constructor (issue #155) * feat: onCreateRouteName hook; internal: clearing routeNameDuplicatesMap * docs: update CHANGELOG * chore: refresh tests schemas * fix: nested object properties are generated are optional (issue #156, thanks @Fabiencdp) * bump: up project version to 5.1.0
1 parent 58573bc commit 21c64fd

Some content is hidden

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

81 files changed

+1128
-856
lines changed

CHANGELOG.md

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

3+
# 5.1.0
4+
5+
Fixes:
6+
- Bug with optional nested properties of object schema type (issue #156, thanks @Fabiencdp)
7+
8+
Features:
9+
- `onCreateRouteName(routeNameInfo: RouteNameInfo, rawRouteInfo: RawRouteInfo): RouteNameInfo | void` hook
10+
Which allows to customize route name without customizing `route-name.eta` template
11+
- Improved content kinds for request infos
12+
- `--single-http-client` option which allows to send HttpClient instance to Api constructor and not to create many count of HttpClient instances with `--modular` api (issue #155)
13+
14+
Minor:
15+
- A bit improve type declaration file (index.d.ts) for this tool
16+
- make exportable `ApiConfig` interface
17+
18+
Internal:
19+
- clearing `routeNameDuplicatesMap` before each `parseRoutes()` function call
20+
- Changed templates:
21+
- `http-client.eta`
22+
- `procedure-call.eta`
23+
- `api.eta`
24+
325
# 5.0.0
426

527
Fixes:

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ Options:
5858
--modular generate separated files for http client, data contracts, and routes (default: false)
5959
--disableStrictSSL disabled strict SSL (default: false)
6060
--clean-output clean output folder before generate api. WARNING: May cause data loss (default: false)
61+
--single-http-client Ability to send HttpClient instance to Api constructor (default: false)
6162
--default-response <type> default type for empty response schema (default: "void")
6263
-h, --help display help for command
6364
```

index.d.ts

Lines changed: 57 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,10 @@ interface GenerateApiParams {
8181
* default type for empty response schema (default: "void")
8282
*/
8383
defaultResponseType?: boolean;
84+
/**
85+
* Ability to send HttpClient instance to Api constructor
86+
*/
87+
singleHttpClient?: boolean;
8488
cleanOutput?: boolean;
8589
enumNamesAsValues?: boolean;
8690

@@ -92,6 +96,10 @@ interface GenerateApiParams {
9296
onInit?: <C extends GenerateApiConfiguration["config"]>(configuration: C) => C | void;
9397
/** customize configuration object before sending it to ETA templates */
9498
onPrepareConfig?: <C extends GenerateApiConfiguration>(currentConfiguration: C) => C | void;
99+
onCreateRouteName?: (
100+
routeNameInfo: RouteNameInfo,
101+
rawRouteInfo: RawRouteInfo,
102+
) => RouteNameInfo | void;
95103
onCreateRequestParams?: (
96104
rawType: SchemaComponent["rawTypeData"],
97105
) => SchemaComponent["rawTypeData"] | void;
@@ -102,6 +110,14 @@ interface GenerateApiParams {
102110
extraTemplates?: { name: string; path: string }[];
103111
}
104112

113+
export interface RouteNameRouteInfo {}
114+
115+
export type RouteNameInfo = {
116+
usage: string;
117+
original: string;
118+
duplicate: boolean;
119+
};
120+
105121
export type SchemaTypePrimitiveContent = {
106122
$parsedSchema: boolean;
107123
schemaType: string;
@@ -139,6 +155,13 @@ export interface ParsedSchema<C> {
139155
content: C;
140156
}
141157

158+
export interface PathArgInfo {
159+
name: string;
160+
optional: boolean;
161+
type: string;
162+
description?: string;
163+
}
164+
142165
export interface SchemaComponent {
143166
$ref: string;
144167
typeName: string;
@@ -167,41 +190,50 @@ export interface SchemaComponent {
167190
> | null;
168191
}
169192

193+
export enum RequestContentKind {
194+
JSON = "JSON",
195+
URL_ENCODED = "URL_ENCODED",
196+
FORM_DATA = "FORM_DATA",
197+
IMAGE = "IMAGE",
198+
OTHER = "OTHER",
199+
}
200+
201+
export interface RequestResponseInfo {
202+
contentTypes: string[];
203+
contentKind: RequestContentKind;
204+
type: string;
205+
description: string;
206+
status: string | number;
207+
isSuccess: boolean;
208+
}
209+
210+
export type RawRouteInfo = {
211+
operationId: string;
212+
method: string;
213+
route: string;
214+
moduleName: string;
215+
responsesTypes: RequestResponseInfo[];
216+
description?: string;
217+
tags?: string[];
218+
summary?: string;
219+
responses?: import("swagger-schema-official").Spec["responses"];
220+
produces?: string[];
221+
requestBody?: object;
222+
consumes?: string[];
223+
};
224+
170225
export interface ParsedRoute {
171226
id: string;
172227
jsDocLines: string;
173228
namespace: string;
174229
request: Request;
175230
response: Response;
176-
routeName: {
177-
usage: string;
178-
original: string;
179-
duplicate: boolean;
180-
};
181-
raw: {
182-
method: string;
183-
route: string;
184-
moduleName: string;
185-
responsesTypes: {
186-
type: string;
187-
description: string;
188-
status: number;
189-
isSuccess: boolean;
190-
}[];
191-
};
231+
routeName: RouteNameInfo;
232+
raw: RawRouteInfo;
192233
}
193234

194235
export interface GenerateApiConfiguration {
195236
apiConfig: {
196-
props: {
197-
name: string;
198-
optional: boolean;
199-
type: string;
200-
}[];
201-
generic: {
202-
name: string;
203-
defaultValue: string;
204-
}[];
205237
baseUrl: string;
206238
title: string;
207239
version: string;

index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ program
6262
0,
6363
)
6464
.option("--disableStrictSSL", "disabled strict SSL", false)
65+
.option("--single-http-client", "Ability to send HttpClient instance to Api constructor", false)
6566
.option("--default-response <type>", "default type for empty response schema", TS_KEYWORDS.VOID)
6667
.option(
6768
"--clean-output",
@@ -89,6 +90,7 @@ const {
8990
disableStrictSSL,
9091
cleanOutput,
9192
defaultResponse,
93+
singleHttpClient,
9294
} = program;
9395

9496
generateApi({
@@ -109,5 +111,6 @@ generateApi({
109111
enumNamesAsValues: enumNamesAsValues,
110112
moduleNameIndex: +(moduleNameIndex || 0),
111113
disableStrictSSL: !!disableStrictSSL,
114+
singleHttpClient: !!singleHttpClient,
112115
cleanOutput: !!cleanOutput,
113116
});

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: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "swagger-typescript-api",
3-
"version": "5.0.0",
3+
"version": "5.1.0",
44
"description": "Create typescript api module from swagger schema",
55
"scripts": {
66
"cli:json": "node index.js -r -d -p ./swagger-test-cli.json -n swagger-test-cli.ts --extract-request-params --enum-names-as-values",
@@ -25,6 +25,7 @@
2525
"test:specProperty": "node tests/spec/specProperty/test.js",
2626
"test:--module-name-index": "node tests/spec/moduleNameIndex/test.js",
2727
"test:--modular": "node tests/spec/modular/test.js",
28+
"test:--single-http-client": "node tests/spec/singleHttpClient/test.js",
2829
"test:--extract-request-params": "node tests/spec/extractRequestParams/test.js",
2930
"test:--enum-names-as-values": "node tests/spec/enumNamesAsValues/test.js",
3031
"test:--default-response": "node tests/spec/defaultResponse/test.js",

src/config.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ const config = {
3636
httpClient: "http-client",
3737
outOfModuleApi: "Common",
3838
},
39+
routeNameDuplicatesMap: new Map(),
3940
prettierOptions: constants.PRETTIER_OPTIONS,
4041
hooks: {
4142
onCreateComponent: (schema) => schema,
@@ -44,8 +45,10 @@ const config = {
4445
onInit: (config) => config,
4546
onPrepareConfig: (apiConfig) => apiConfig,
4647
onCreateRequestParams: (rawType) => {},
48+
onCreateRouteName: () => {},
4749
},
4850
defaultResponseType: constants.TS_KEYWORDS.VOID,
51+
singleHttpClient: false,
4952
};
5053

5154
/** needs to use data everywhere in project */

src/filePrefix.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module.exports = {
2-
filePrefix: `/* tslint:disable */
3-
/* eslint-disable */
2+
filePrefix: `/* eslint:disable */
3+
/* tslint-disable */
44
/*
55
* ---------------------------------------------------------------
66
* ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ##

src/index.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ module.exports = {
3737
moduleNameIndex = config.moduleNameIndex,
3838
extractRequestParams = config.extractRequestParams,
3939
defaultResponseType = config.defaultResponseType,
40+
singleHttpClient = config.singleHttpClient,
4041
prettier: prettierOptions = constants.PRETTIER_OPTIONS,
4142
hooks: rawHooks,
4243
extraTemplates,
@@ -61,6 +62,7 @@ module.exports = {
6162
disableStrictSSL,
6263
cleanOutput,
6364
defaultResponseType,
65+
singleHttpClient,
6466
});
6567
(spec ? convertSwaggerObject(spec) : getSwaggerObject(input, url, disableStrictSSL))
6668
.then(({ usageSchema, originalSchema }) => {
@@ -83,6 +85,9 @@ module.exports = {
8385
const componentsMap = createComponentsMap(components);
8486

8587
const parsedSchemas = parseSchemas(components);
88+
89+
config.routeNameDuplicatesMap.clear();
90+
8691
const routes = parseRoutes({
8792
usageSchema,
8893
parsedSchemas,

src/routeNames.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,13 @@ const getRouteName = (routeInfo) => {
3232

3333
const duplicates = routeNameDuplicatesMap.get(duplicateIdentifier);
3434

35-
return {
35+
const routeNameInfo = {
3636
usage: routeName + (duplicates > 1 ? duplicates : ""),
3737
original: routeName,
3838
duplicate: duplicates > 1,
3939
};
40+
41+
return config.hooks.onCreateRouteName(routeNameInfo, routeInfo) || routeNameInfo;
4042
};
4143

4244
module.exports = {

src/routes.js

Lines changed: 20 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ const {
77
TS_KEYWORDS,
88
} = require("./constants");
99
const { formatDescription, classNameCase } = require("./common");
10-
const { config, addToConfig } = require("./config");
10+
const { config } = require("./config");
1111
const { nanoid } = require("nanoid");
1212
const { getRouteName } = require("./routeNames");
1313
const { createComponent } = require("./components");
@@ -336,7 +336,10 @@ const CONTENT_KIND = {
336336
};
337337

338338
const getContentKind = (contentTypes) => {
339-
if (contentTypes.includes("application/json")) {
339+
if (
340+
_.includes(contentTypes, "application/json") ||
341+
_.some(contentTypes, (contentType) => _.endsWith(contentType, "+json"))
342+
) {
340343
return CONTENT_KIND.JSON;
341344
}
342345

@@ -434,9 +437,6 @@ const getResponseBodyInfo = (routeInfo, routeParams, parsedSchemas) => {
434437
const parseRoutes = ({ usageSchema, parsedSchemas, moduleNameIndex, extractRequestParams }) => {
435438
const { paths, security: globalSecurity } = usageSchema;
436439
const pathsEntries = _.entries(paths);
437-
addToConfig({
438-
routeNameDuplicatesMap: new Map(),
439-
});
440440

441441
return pathsEntries.reduce((routes, [rawRoute, routeInfoByMethodsMap]) => {
442442
if (rawRoute.startsWith("x-")) return routes;
@@ -481,11 +481,8 @@ const parseRoutes = ({ usageSchema, parsedSchemas, moduleNameIndex, extractReque
481481
const requestBodyInfo = getRequestBodyInfo(routeInfo, routeParams, parsedSchemas);
482482
const responseBodyInfo = getResponseBodyInfo(routeInfo, routeParams, parsedSchemas);
483483

484-
const queryObjectSchema = convertRouteParamsIntoObject(routeParams.query);
485-
const pathObjectSchema = convertRouteParamsIntoObject(routeParams.path);
486-
const headersObjectSchema = convertRouteParamsIntoObject(routeParams.header);
487-
488-
const routeName = getRouteName({
484+
const rawRouteInfo = {
485+
pathArgs,
489486
operationId,
490487
method,
491488
route: rawRoute,
@@ -494,8 +491,18 @@ const parseRoutes = ({ usageSchema, parsedSchemas, moduleNameIndex, extractReque
494491
description,
495492
tags,
496493
summary,
497-
pathArgs,
498-
});
494+
responses,
495+
produces,
496+
requestBody,
497+
consumes,
498+
...otherInfo,
499+
};
500+
501+
const queryObjectSchema = convertRouteParamsIntoObject(routeParams.query);
502+
const pathObjectSchema = convertRouteParamsIntoObject(routeParams.path);
503+
const headersObjectSchema = convertRouteParamsIntoObject(routeParams.header);
504+
505+
const routeName = getRouteName(rawRouteInfo);
499506

500507
const requestParamsSchema = createRequestParamsSchema({
501508
queryParams: routeParams.query,
@@ -615,21 +622,7 @@ const parseRoutes = ({ usageSchema, parsedSchemas, moduleNameIndex, extractReque
615622
type: responseBodyInfo.success.type,
616623
errorType: responseBodyInfo.error.type,
617624
},
618-
raw: {
619-
operationId,
620-
method,
621-
route: rawRoute,
622-
moduleName,
623-
responsesTypes: responseBodyInfo.responses,
624-
description,
625-
tags,
626-
summary,
627-
responses,
628-
produces,
629-
requestBody,
630-
consumes,
631-
...otherInfo,
632-
},
625+
raw: rawRouteInfo,
633626
};
634627

635628
return config.hooks.onCreateRoute(routeData) || routeData;

0 commit comments

Comments
 (0)