swagger-typescript-api 9.3.0 → 10.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +40 -1
- package/README.md +22 -15
- package/index.d.ts +39 -20
- package/index.js +49 -76
- package/package.json +19 -15
- package/src/config.js +6 -0
- package/src/index.js +24 -14
- package/src/routeNames.js +3 -7
- package/src/routes.js +91 -79
- package/src/schema.js +65 -43
- package/src/swagger.js +11 -4
- package/src/utils/id.js +9 -0
- package/templates/base/data-contracts.eta +2 -1
- package/templates/base/http-clients/axios-http-client.eta +38 -18
- package/templates/base/http-clients/fetch-http-client.eta +7 -7
- package/templates/default/api.eta +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,43 @@
|
|
|
1
|
-
# next release
|
|
1
|
+
# next release
|
|
2
|
+
|
|
3
|
+
# 10.0.1
|
|
4
|
+
|
|
5
|
+
- fix problem linked with [this.name is not a function](https://github.com/acacode/swagger-typescript-api/issues/381)
|
|
6
|
+
- [internal] add cli tests
|
|
7
|
+
- fix problem with not correct working the `--no-client` option
|
|
8
|
+
|
|
9
|
+
# 10.0.0
|
|
10
|
+
|
|
11
|
+
- `--extract-response-body` option - extract response body type to data contract
|
|
12
|
+
- `--extract-response-error` option - extract response error type to data contract
|
|
13
|
+
- `--add-readonly` option - generate readonly properties
|
|
14
|
+
- `authorizationToken` for axios fetch swagger schema request
|
|
15
|
+
- fix: change COMPLEX_NOT_OF to COMPLEX_NOT (internal)
|
|
16
|
+
- feat: improve `@deprecated` jsdoc info
|
|
17
|
+
- feat: improve `required` field in complex data schemas (anyOf, oneOf, allOf etc)
|
|
18
|
+
- feat: abortSignal for fetch http client
|
|
19
|
+
- chore: improve typings in index.d.ts
|
|
20
|
+
- fixed [Request falls if FormData attachment is File instance](https://github.com/acacode/swagger-typescript-api/issues/293)
|
|
21
|
+
- fixed [Response format - global default or override ?](https://github.com/acacode/swagger-typescript-api/issues/251)
|
|
22
|
+
|
|
23
|
+
> Co-authored-by: Sergey S. Volkov <js2me@outlook.com>
|
|
24
|
+
> Co-authored-by: Xavier Cassel <57092100+xcassel@users.noreply.github.com>
|
|
25
|
+
> Co-authored-by: cassel <xavier.cassel35@gmail.com>
|
|
26
|
+
> Co-authored-by: Adrian Wieprzkowicz <Argeento@users.noreply.github.com>
|
|
27
|
+
> Co-authored-by: EvgenBabenko <evgen.babenko@gmail.com>
|
|
28
|
+
> Co-authored-by: RoCat <catoio.romain@gmail.com>
|
|
29
|
+
> Co-authored-by: rcatoio <rcatoio@doubletrade.com>
|
|
30
|
+
> Co-authored-by: 卡色 <cipchk@qq.com>
|
|
31
|
+
> Co-authored-by: 江麻妞 <50100681+jiangmaniu@users.noreply.github.com>
|
|
32
|
+
> Co-authored-by: Kasper Moskwiak <kasper.moskwiak@gmail.com>
|
|
33
|
+
> Co-authored-by: Ben Watkins <ben@outdatedversion.com>
|
|
34
|
+
> Co-authored-by: bonukai <bonukai@protonmail.com>
|
|
35
|
+
> Co-authored-by: baggoedw <92381702+baggoedw@users.noreply.github.com>
|
|
36
|
+
> Co-authored-by: Marcus Dunn <51931484+MarcusDunn@users.noreply.github.com>
|
|
37
|
+
> Co-authored-by: Daniele De Matteo <daniele@kuama.net>
|
|
38
|
+
> Co-authored-by: Daniel Playfair Cal <daniel.playfair.cal@gmail.com>
|
|
39
|
+
> Co-authored-by: Anders Cassidy <anders.cassidy@dailypay.com>
|
|
40
|
+
> Co-authored-by: Daniel Playfair Cal <dcal@atlassian.com>
|
|
2
41
|
|
|
3
42
|
# 9.2.0
|
|
4
43
|
|
package/README.md
CHANGED
|
@@ -19,7 +19,11 @@ Any questions you can ask [**here**](https://github.com/acacode/swagger-typescri
|
|
|
19
19
|
|
|
20
20
|
<br>
|
|
21
21
|
|
|
22
|
-

|
|
22
|
+

|
|
23
|
+
|
|
24
|
+
👀 This project is looking for a code maintainer 👀
|
|
25
|
+
P.S. If you are creating the PR, please check your changes with using command `npm run prepare`
|
|
26
|
+
P.S. If you want to contribute please use branch `next`. All PRs which will have target `master` will be declined
|
|
23
27
|
|
|
24
28
|
## 👀 Examples
|
|
25
29
|
|
|
@@ -33,36 +37,39 @@ Usage: swagger-typescript-api [options]
|
|
|
33
37
|
|
|
34
38
|
Options:
|
|
35
39
|
-v, --version output the current version
|
|
36
|
-
-p, --path <
|
|
37
|
-
-o, --output <
|
|
38
|
-
-n, --name <
|
|
39
|
-
-t, --templates <
|
|
40
|
+
-p, --path <string> path/url to swagger scheme
|
|
41
|
+
-o, --output <string> output path of typescript api file (default: "./")
|
|
42
|
+
-n, --name <string> name of output typescript api file (default: "Api.ts")
|
|
43
|
+
-t, --templates <string> path to folder containing templates
|
|
40
44
|
-d, --default-as-success use "default" response status code as success response too.
|
|
41
|
-
some swagger schemas use "default" response status code
|
|
42
|
-
as success response type by default. (default: false)
|
|
45
|
+
some swagger schemas use "default" response status code as success response type by default. (default: false)
|
|
43
46
|
-r, --responses generate additional information about request responses
|
|
44
47
|
also add typings for bad responses (default: false)
|
|
45
48
|
--union-enums generate all "enum" types as union types (T1 | T2 | TN) (default: false)
|
|
49
|
+
--add-readonly generate readonly properties (default: false)
|
|
46
50
|
--route-types generate type definitions for API routes (default: false)
|
|
47
51
|
--no-client do not generate an API class
|
|
48
52
|
--enum-names-as-values use values in 'x-enumNames' as enum values (not only as keys) (default: false)
|
|
49
|
-
--
|
|
50
|
-
--extract-request-
|
|
51
|
-
|
|
52
|
-
--extract-
|
|
53
|
-
--module-name-index <number> determines which path index should be used for routes separation (default: 0)
|
|
54
|
-
(example: GET:/fruites/getFruit -> index:0 -> moduleName -> fruites)
|
|
55
|
-
--module-name-first-tag splits routes based on the first tag
|
|
53
|
+
--extract-request-params extract request params to data contract (Also combine path params and query params into one object) (default: false)
|
|
54
|
+
--extract-request-body extract request body type to data contract (default: false)
|
|
55
|
+
--extract-response-body extract response body type to data contract (default: false)
|
|
56
|
+
--extract-response-error extract response error type to data contract (default: false)
|
|
56
57
|
--modular generate separated files for http client, data contracts, and routes (default: false)
|
|
58
|
+
--js generate js api module with declaration file (default: false)
|
|
59
|
+
--module-name-index <number> determines which path index should be used for routes separation (example: GET:/fruites/getFruit -> index:0 -> moduleName -> fruites) (default: 0)
|
|
60
|
+
--module-name-first-tag splits routes based on the first tag (default: false)
|
|
57
61
|
--disableStrictSSL disabled strict SSL (default: false)
|
|
58
62
|
--disableProxy disabled proxy (default: false)
|
|
59
|
-
--clean-output clean output folder before generate api. WARNING: May cause data loss (default: false)
|
|
60
63
|
--axios generate axios http client (default: false)
|
|
64
|
+
--unwrap-response-data unwrap the data item from the response (default: false)
|
|
65
|
+
--disable-throw-on-error Do not throw an error when response.ok is not true (default: false)
|
|
61
66
|
--single-http-client Ability to send HttpClient instance to Api constructor (default: false)
|
|
62
67
|
--silent Output only errors to console (default: false)
|
|
63
68
|
--default-response <type> default type for empty response schema (default: "void")
|
|
64
69
|
--type-prefix <string> data contract name prefix (default: "")
|
|
65
70
|
--type-suffix <string> data contract name suffix (default: "")
|
|
71
|
+
--clean-output clean output folder before generate api. WARNING: May cause data loss (default: false)
|
|
72
|
+
--api-class-name <string> name of the api class
|
|
66
73
|
--patch fix up small errors in the swagger source definition (default: false)
|
|
67
74
|
-h, --help display help for command
|
|
68
75
|
```
|
package/index.d.ts
CHANGED
|
@@ -1,19 +1,4 @@
|
|
|
1
|
-
interface
|
|
2
|
-
/**
|
|
3
|
-
* path to swagger schema
|
|
4
|
-
*/
|
|
5
|
-
input: string;
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* url to swagger schema
|
|
9
|
-
*/
|
|
10
|
-
url: string;
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* swagger schema JSON
|
|
14
|
-
*/
|
|
15
|
-
spec: import("swagger-schema-official").Spec;
|
|
16
|
-
|
|
1
|
+
interface GenerateApiParamsBase {
|
|
17
2
|
/**
|
|
18
3
|
* default 'api.ts'
|
|
19
4
|
*/
|
|
@@ -25,7 +10,7 @@ interface GenerateApiParams {
|
|
|
25
10
|
output?: string;
|
|
26
11
|
|
|
27
12
|
/**
|
|
28
|
-
* path to folder containing templates (default: ./
|
|
13
|
+
* path to folder containing templates (default: ./src/templates)
|
|
29
14
|
*/
|
|
30
15
|
templates?: string;
|
|
31
16
|
|
|
@@ -92,6 +77,14 @@ interface GenerateApiParams {
|
|
|
92
77
|
* extract request body type to data contract
|
|
93
78
|
*/
|
|
94
79
|
extractRequestBody?: boolean;
|
|
80
|
+
/**
|
|
81
|
+
* extract response body type to data contract
|
|
82
|
+
*/
|
|
83
|
+
extractResponseBody?: boolean;
|
|
84
|
+
/**
|
|
85
|
+
* extract response error type to data contract
|
|
86
|
+
*/
|
|
87
|
+
extractResponseError?: boolean;
|
|
95
88
|
/**
|
|
96
89
|
* prettier configuration
|
|
97
90
|
*/
|
|
@@ -121,8 +114,35 @@ interface GenerateApiParams {
|
|
|
121
114
|
* fix up small errors in the swagger source definition
|
|
122
115
|
*/
|
|
123
116
|
patch?: boolean;
|
|
117
|
+
/**
|
|
118
|
+
* authorization token
|
|
119
|
+
*/
|
|
120
|
+
authorizationToken?: string;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
interface GenerateApiParamsFromPath extends GenerateApiParamsBase {
|
|
124
|
+
/**
|
|
125
|
+
* path to swagger schema
|
|
126
|
+
*/
|
|
127
|
+
input: string;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
interface GenerateApiParamsFromUrl extends GenerateApiParamsBase {
|
|
131
|
+
/**
|
|
132
|
+
* url to swagger schema
|
|
133
|
+
*/
|
|
134
|
+
url: string;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
interface GenerateApiParamsFromSpecLiteral extends GenerateApiParamsBase {
|
|
138
|
+
/**
|
|
139
|
+
* swagger schema JSON
|
|
140
|
+
*/
|
|
141
|
+
spec: import("swagger-schema-official").Spec;
|
|
124
142
|
}
|
|
125
143
|
|
|
144
|
+
export type GenerateApiParams = GenerateApiParamsFromPath | GenerateApiParamsFromUrl | GenerateApiParamsFromSpecLiteral;
|
|
145
|
+
|
|
126
146
|
export interface Hooks {
|
|
127
147
|
/** calls after parse schema component */
|
|
128
148
|
onCreateComponent: (component: SchemaComponent) => SchemaComponent | void;
|
|
@@ -323,6 +343,7 @@ export interface GenerateApiConfiguration {
|
|
|
323
343
|
routeName: string;
|
|
324
344
|
};
|
|
325
345
|
routeNameDuplicatesMap: Map<string, string>;
|
|
346
|
+
apiClassName: string
|
|
326
347
|
};
|
|
327
348
|
modelTypes: ModelType[];
|
|
328
349
|
rawModelTypes: SchemaComponent[];
|
|
@@ -371,6 +392,4 @@ export interface GenerateApiOutput {
|
|
|
371
392
|
formatTSContent: (content: string) => string;
|
|
372
393
|
}
|
|
373
394
|
|
|
374
|
-
export declare function generateApi(params:
|
|
375
|
-
export declare function generateApi(params: Omit<GenerateApiParams, "input" | "spec">): Promise<GenerateApiOutput>;
|
|
376
|
-
export declare function generateApi(params: Omit<GenerateApiParams, "input" | "url">): Promise<GenerateApiOutput>;
|
|
395
|
+
export declare function generateApi(params: GenerateApiParams): Promise<GenerateApiOutput>;
|
package/index.js
CHANGED
|
@@ -14,17 +14,14 @@ const { TS_KEYWORDS, HTTP_CLIENT } = require("./src/constants");
|
|
|
14
14
|
|
|
15
15
|
const program = new Command(packageName);
|
|
16
16
|
|
|
17
|
-
program
|
|
18
|
-
|
|
19
|
-
program
|
|
17
|
+
const options = program
|
|
18
|
+
.alias("sta")
|
|
20
19
|
.version(version, "-v, --version", "output the current version")
|
|
21
|
-
.description("Generate api via swagger scheme.\nSupports OA 3.0, 2.0, JSON, yaml.")
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
.
|
|
25
|
-
.option("-
|
|
26
|
-
.option("-n, --name <name>", "name of output typescript api file", "Api.ts")
|
|
27
|
-
.option("-t, --templates <path>", "path to folder containing templates")
|
|
20
|
+
.description("Generate api via swagger scheme.\nSupports OA 3.0, 2.0, JSON, yaml.")
|
|
21
|
+
.requiredOption("-p, --path <string>", "path/url to swagger scheme")
|
|
22
|
+
.option("-o, --output <string>", "output path of typescript api file", "./")
|
|
23
|
+
.option("-n, --name <string>", "name of output typescript api file", "Api.ts")
|
|
24
|
+
.option("-t, --templates <string>", "path to folder containing templates")
|
|
28
25
|
.option(
|
|
29
26
|
"-d, --default-as-success",
|
|
30
27
|
'use "default" response status code as success response too.\n' +
|
|
@@ -37,8 +34,9 @@ program
|
|
|
37
34
|
false,
|
|
38
35
|
)
|
|
39
36
|
.option("--union-enums", 'generate all "enum" types as union types (T1 | T2 | TN)', false)
|
|
37
|
+
.option("--add-readonly", "generate readonly properties", false)
|
|
40
38
|
.option("--route-types", "generate type definitions for API routes", false)
|
|
41
|
-
.option("--no-client", "do not generate an API class",
|
|
39
|
+
.option("--no-client", "do not generate an API class", true)
|
|
42
40
|
.option("--enum-names-as-values", "use values in 'x-enumNames' as enum values (not only as keys)", false)
|
|
43
41
|
.option(
|
|
44
42
|
"--extract-request-params",
|
|
@@ -46,6 +44,8 @@ program
|
|
|
46
44
|
false,
|
|
47
45
|
)
|
|
48
46
|
.option("--extract-request-body", "extract request body type to data contract", false)
|
|
47
|
+
.option("--extract-response-body", "extract response body type to data contract", false)
|
|
48
|
+
.option("--extract-response-error", "extract response error type to data contract", false)
|
|
49
49
|
.option("--modular", "generate separated files for http client, data contracts, and routes", false)
|
|
50
50
|
.option("--js", "generate js api module with declaration file", false)
|
|
51
51
|
.option(
|
|
@@ -65,73 +65,46 @@ program
|
|
|
65
65
|
.option("--type-prefix <string>", "data contract name prefix", "")
|
|
66
66
|
.option("--type-suffix <string>", "data contract name suffix", "")
|
|
67
67
|
.option("--clean-output", "clean output folder before generate api. WARNING: May cause data loss", false)
|
|
68
|
-
.option("--
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
const {
|
|
73
|
-
path,
|
|
74
|
-
output,
|
|
75
|
-
name,
|
|
76
|
-
templates,
|
|
77
|
-
unionEnums,
|
|
78
|
-
routeTypes,
|
|
79
|
-
client,
|
|
80
|
-
defaultAsSuccess,
|
|
81
|
-
responses,
|
|
82
|
-
modular,
|
|
83
|
-
js,
|
|
84
|
-
moduleNameIndex,
|
|
85
|
-
moduleNameFirstTag,
|
|
86
|
-
extractRequestParams,
|
|
87
|
-
extractRequestBody,
|
|
88
|
-
enumNamesAsValues,
|
|
89
|
-
disableStrictSSL,
|
|
90
|
-
disableProxy,
|
|
91
|
-
cleanOutput,
|
|
92
|
-
defaultResponse,
|
|
93
|
-
unwrapResponseData,
|
|
94
|
-
disableThrowOnError,
|
|
95
|
-
sortTypes,
|
|
96
|
-
singleHttpClient,
|
|
97
|
-
axios,
|
|
98
|
-
silent,
|
|
99
|
-
typePrefix,
|
|
100
|
-
typeSuffix,
|
|
101
|
-
patch,
|
|
102
|
-
} = program;
|
|
68
|
+
.option("--api-class-name <string>", "name of the api class")
|
|
69
|
+
.option("--patch", "fix up small errors in the swagger source definition", false)
|
|
70
|
+
.parse(process.argv)
|
|
71
|
+
.opts();
|
|
103
72
|
|
|
104
73
|
generateApi({
|
|
105
|
-
name,
|
|
106
|
-
url: path,
|
|
107
|
-
generateRouteTypes: routeTypes,
|
|
108
|
-
generateClient: !!(axios || client),
|
|
109
|
-
httpClientType: axios ? HTTP_CLIENT.AXIOS : HTTP_CLIENT.FETCH,
|
|
110
|
-
defaultResponseAsSuccess: defaultAsSuccess,
|
|
111
|
-
defaultResponseType: defaultResponse,
|
|
112
|
-
unwrapResponseData: unwrapResponseData,
|
|
113
|
-
disableThrowOnError: disableThrowOnError,
|
|
114
|
-
sortTypes: sortTypes,
|
|
115
|
-
generateUnionEnums: unionEnums,
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
74
|
+
name: options.name,
|
|
75
|
+
url: options.path,
|
|
76
|
+
generateRouteTypes: options.routeTypes,
|
|
77
|
+
generateClient: !!(options.axios || options.client),
|
|
78
|
+
httpClientType: options.axios ? HTTP_CLIENT.AXIOS : HTTP_CLIENT.FETCH,
|
|
79
|
+
defaultResponseAsSuccess: options.defaultAsSuccess,
|
|
80
|
+
defaultResponseType: options.defaultResponse,
|
|
81
|
+
unwrapResponseData: options.unwrapResponseData,
|
|
82
|
+
disableThrowOnError: options.disableThrowOnError,
|
|
83
|
+
sortTypes: options.sortTypes,
|
|
84
|
+
generateUnionEnums: options.unionEnums,
|
|
85
|
+
addReadonly: options.addReadonly,
|
|
86
|
+
generateResponses: options.responses,
|
|
87
|
+
extractRequestParams: !!options.extractRequestParams,
|
|
88
|
+
extractRequestBody: !!options.extractRequestBody,
|
|
89
|
+
extractResponseBody: !!options.extractResponseBody,
|
|
90
|
+
extractResponseError: !!options.extractResponseError,
|
|
91
|
+
input: resolve(process.cwd(), options.path),
|
|
92
|
+
output: resolve(process.cwd(), options.output || "."),
|
|
93
|
+
templates: options.templates,
|
|
94
|
+
modular: !!options.modular,
|
|
95
|
+
toJS: !!options.js,
|
|
96
|
+
enumNamesAsValues: options.enumNamesAsValues,
|
|
97
|
+
moduleNameIndex: +(options.moduleNameIndex || 0),
|
|
98
|
+
moduleNameFirstTag: options.moduleNameFirstTag,
|
|
99
|
+
disableStrictSSL: !!options.disableStrictSSL,
|
|
100
|
+
disableProxy: !!options.disableProxy,
|
|
101
|
+
singleHttpClient: !!options.singleHttpClient,
|
|
102
|
+
cleanOutput: !!options.cleanOutput,
|
|
103
|
+
silent: !!options.silent,
|
|
104
|
+
typePrefix: options.typePrefix,
|
|
105
|
+
typeSuffix: options.typeSuffix,
|
|
106
|
+
patch: !!options.patch,
|
|
107
|
+
apiClassName: options.apiClassName,
|
|
135
108
|
}).catch((err) => {
|
|
136
109
|
// NOTE collect all errors on top level and shows to users in any case
|
|
137
110
|
console.error(err);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "swagger-typescript-api",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "10.0.1",
|
|
4
4
|
"description": "Generate typescript/javascript api from swagger schema",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"cli:json": "node index.js -r -d -p ./swagger-test-cli.json -n swagger-test-cli.ts",
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"test:--default-as-success": "node tests/spec/defaultAsSuccess/test.js",
|
|
24
24
|
"test:--templates": "node tests/spec/templates/test.js",
|
|
25
25
|
"test:--union-enums": "node tests/spec/unionEnums/test.js",
|
|
26
|
+
"test:--add-readonly": "node tests/spec/readonly/test.js",
|
|
26
27
|
"test:--responses": "node tests/spec/responses/test.js",
|
|
27
28
|
"test:specProperty": "node tests/spec/specProperty/test.js",
|
|
28
29
|
"test:--module-name-index": "node tests/spec/moduleNameIndex/test.js",
|
|
@@ -31,6 +32,8 @@
|
|
|
31
32
|
"test:--single-http-client": "node tests/spec/singleHttpClient/test.js",
|
|
32
33
|
"test:--extract-request-params": "node tests/spec/extractRequestParams/test.js",
|
|
33
34
|
"test:--extract-request-body": "node tests/spec/extractRequestBody/test.js",
|
|
35
|
+
"test:--extract-response-body": "node tests/spec/extractResponseBody/test.js",
|
|
36
|
+
"test:--extract-response-error": "node tests/spec/extractResponseError/test.js",
|
|
34
37
|
"test:--enum-names-as-values": "node tests/spec/enumNamesAsValues/test.js",
|
|
35
38
|
"test:--default-response": "node tests/spec/defaultResponse/test.js",
|
|
36
39
|
"test:--js": "node tests/spec/js/test.js",
|
|
@@ -38,6 +41,7 @@
|
|
|
38
41
|
"test:--axios": "node tests/spec/axios/test.js",
|
|
39
42
|
"test:--axios--single-http-client": "node tests/spec/axiosSingleHttpClient/test.js",
|
|
40
43
|
"test:--type-suffix--type-prefix": "node tests/spec/typeSuffixPrefix/test.js",
|
|
44
|
+
"test:--cli": "node index.js -p tests/spec/cli/schema.json -o tests/spec/cli -n schema.ts --extract-response-body --extract-response-error --type-prefix Prefix --api-class-name MySuperApi --no-client",
|
|
41
45
|
"test:partialBaseTemplate": "node tests/spec/partialBaseTemplate/test.js",
|
|
42
46
|
"test:partialDefaultTemplate": "node tests/spec/partialDefaultTemplate/test.js",
|
|
43
47
|
"test:--patch": "node tests/spec/patch/test.js"
|
|
@@ -48,28 +52,28 @@
|
|
|
48
52
|
"main": "src/index.js",
|
|
49
53
|
"devDependencies": {
|
|
50
54
|
"@types/axios": "^0.14.0",
|
|
51
|
-
"@types/lodash": "^4.14.
|
|
55
|
+
"@types/lodash": "^4.14.182",
|
|
52
56
|
"@types/node": "^15.0.2",
|
|
53
|
-
"@types/prettier": "^2.
|
|
54
|
-
"all-contributors-cli": "^6.
|
|
55
|
-
"axios": "^0.21.4",
|
|
57
|
+
"@types/prettier": "^2.7.0",
|
|
58
|
+
"all-contributors-cli": "^6.20.0",
|
|
56
59
|
"husky": "^4.3.6",
|
|
57
60
|
"pretty-quick": "^3.1.0"
|
|
58
61
|
},
|
|
59
62
|
"dependencies": {
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
"
|
|
63
|
+
"axios": "^0.27.2",
|
|
64
|
+
"@types/swagger-schema-official": "2.0.22",
|
|
65
|
+
"commander": "^9.4.0",
|
|
66
|
+
"cosmiconfig": "^7.0.1",
|
|
67
|
+
"eta": "^1.12.3",
|
|
68
|
+
"js-yaml": "^4.1.0",
|
|
65
69
|
"lodash": "^4.17.21",
|
|
66
70
|
"make-dir": "^3.1.0",
|
|
67
|
-
"nanoid": "^3.
|
|
68
|
-
"node-emoji": "^1.
|
|
69
|
-
"prettier": "^2.
|
|
71
|
+
"nanoid": "^3.3.4",
|
|
72
|
+
"node-emoji": "^1.11.0",
|
|
73
|
+
"prettier": "^2.7.1",
|
|
70
74
|
"swagger-schema-official": "2.0.0-bab6bed",
|
|
71
|
-
"swagger2openapi": "^7.0.
|
|
72
|
-
"typescript": "^4.
|
|
75
|
+
"swagger2openapi": "^7.0.8",
|
|
76
|
+
"typescript": "^4.7.4"
|
|
73
77
|
},
|
|
74
78
|
"bin": {
|
|
75
79
|
"swagger-typescript-api": "index.js",
|
package/src/config.js
CHANGED
|
@@ -14,6 +14,8 @@ const config = {
|
|
|
14
14
|
generateClient: true,
|
|
15
15
|
/** CLI flag */
|
|
16
16
|
generateUnionEnums: false,
|
|
17
|
+
/** CLI flag */
|
|
18
|
+
addReadonly: false,
|
|
17
19
|
enumNamesAsValues: false,
|
|
18
20
|
/** parsed swagger schema from getSwaggerObject() */
|
|
19
21
|
|
|
@@ -36,6 +38,8 @@ const config = {
|
|
|
36
38
|
disableProxy: false,
|
|
37
39
|
extractRequestParams: false,
|
|
38
40
|
extractRequestBody: false,
|
|
41
|
+
extractResponseBody: false,
|
|
42
|
+
extractResponseError: false,
|
|
39
43
|
fileNames: {
|
|
40
44
|
dataContracts: "data-contracts",
|
|
41
45
|
routeTypes: "route-types",
|
|
@@ -87,6 +91,8 @@ const config = {
|
|
|
87
91
|
typeSuffix: "",
|
|
88
92
|
patch: false,
|
|
89
93
|
componentTypeNameResolver: new NameResolver([]),
|
|
94
|
+
/** name of the main exported class */
|
|
95
|
+
apiClassName: "Api",
|
|
90
96
|
};
|
|
91
97
|
|
|
92
98
|
/** needs to use data everywhere in project */
|
package/src/index.js
CHANGED
|
@@ -40,10 +40,13 @@ module.exports = {
|
|
|
40
40
|
generateClient = config.generateClient,
|
|
41
41
|
httpClientType = config.httpClientType,
|
|
42
42
|
generateUnionEnums = config.generateUnionEnums,
|
|
43
|
+
addReadonly = config.addReadonly,
|
|
43
44
|
moduleNameIndex = config.moduleNameIndex,
|
|
44
45
|
moduleNameFirstTag = config.moduleNameFirstTag,
|
|
45
46
|
extractRequestParams = config.extractRequestParams,
|
|
46
47
|
extractRequestBody = config.extractRequestBody,
|
|
48
|
+
extractResponseBody = config.extractResponseBody,
|
|
49
|
+
extractResponseError = config.extractResponseError,
|
|
47
50
|
defaultResponseType = config.defaultResponseType,
|
|
48
51
|
unwrapResponseData = config.unwrapResponseData,
|
|
49
52
|
disableThrowOnError = config.disableThrowOnError,
|
|
@@ -60,6 +63,8 @@ module.exports = {
|
|
|
60
63
|
typePrefix = config.typePrefix,
|
|
61
64
|
typeSuffix = config.typeSuffix,
|
|
62
65
|
patch = config.patch,
|
|
66
|
+
authorizationToken,
|
|
67
|
+
apiClassName = config.apiClassName,
|
|
63
68
|
}) =>
|
|
64
69
|
new Promise((resolve, reject) => {
|
|
65
70
|
addToConfig({
|
|
@@ -70,12 +75,15 @@ module.exports = {
|
|
|
70
75
|
generateResponses,
|
|
71
76
|
templates,
|
|
72
77
|
generateUnionEnums,
|
|
78
|
+
addReadonly,
|
|
73
79
|
moduleNameIndex,
|
|
74
80
|
moduleNameFirstTag,
|
|
75
81
|
prettierOptions,
|
|
76
82
|
modular,
|
|
77
83
|
extractRequestParams,
|
|
78
84
|
extractRequestBody,
|
|
85
|
+
extractResponseBody,
|
|
86
|
+
extractResponseError,
|
|
79
87
|
hooks: _.merge(config.hooks, rawHooks || {}),
|
|
80
88
|
enumNamesAsValues,
|
|
81
89
|
disableStrictSSL,
|
|
@@ -92,10 +100,11 @@ module.exports = {
|
|
|
92
100
|
typePrefix,
|
|
93
101
|
typeSuffix,
|
|
94
102
|
patch,
|
|
103
|
+
apiClassName,
|
|
95
104
|
});
|
|
96
105
|
(spec
|
|
97
106
|
? convertSwaggerObject(spec, { patch })
|
|
98
|
-
: getSwaggerObject(input, url, disableStrictSSL, disableProxy, { patch })
|
|
107
|
+
: getSwaggerObject(input, url, disableStrictSSL, disableProxy, authorizationToken, { patch })
|
|
99
108
|
)
|
|
100
109
|
.then(({ usageSchema, originalSchema }) => {
|
|
101
110
|
const templatePaths = getTemplatePaths(config);
|
|
@@ -120,9 +129,7 @@ module.exports = {
|
|
|
120
129
|
|
|
121
130
|
const componentsMap = createComponentsMap(components);
|
|
122
131
|
|
|
123
|
-
const componentSchemasNames = filterComponentsMap(componentsMap, "schemas").map(
|
|
124
|
-
(c) => c.typeName,
|
|
125
|
-
);
|
|
132
|
+
const componentSchemasNames = filterComponentsMap(componentsMap, "schemas").map((c) => c.typeName);
|
|
126
133
|
|
|
127
134
|
addToConfig({
|
|
128
135
|
componentTypeNameResolver: new ComponentTypeNameResolver(componentSchemasNames),
|
|
@@ -146,29 +153,32 @@ module.exports = {
|
|
|
146
153
|
|
|
147
154
|
const usageComponentSchemas = filterComponentsMap(componentsMap, "schemas");
|
|
148
155
|
const sortByProperty = (o1, o2, propertyName) => {
|
|
149
|
-
if(o1[propertyName] > o2[propertyName]) {
|
|
156
|
+
if (o1[propertyName] > o2[propertyName]) {
|
|
150
157
|
return 1;
|
|
151
158
|
}
|
|
152
|
-
if(o1[propertyName] < o2[propertyName]) {
|
|
159
|
+
if (o1[propertyName] < o2[propertyName]) {
|
|
153
160
|
return -1;
|
|
154
161
|
}
|
|
155
162
|
return 0;
|
|
156
|
-
}
|
|
157
|
-
const sortByTypeName = (o1, o2) => sortByProperty(o1, o2,
|
|
163
|
+
};
|
|
164
|
+
const sortByTypeName = (o1, o2) => sortByProperty(o1, o2, "typeName");
|
|
158
165
|
|
|
159
|
-
const sortByName = (o1, o2) => sortByProperty(o1, o2,
|
|
166
|
+
const sortByName = (o1, o2) => sortByProperty(o1, o2, "name");
|
|
160
167
|
|
|
161
168
|
const sortSchemas = (schemas) => {
|
|
162
|
-
if(config.sortTypes) {
|
|
169
|
+
if (config.sortTypes) {
|
|
163
170
|
return schemas.sort(sortByTypeName).map((schema) => {
|
|
164
|
-
if(schema.rawTypeData?.properties) {
|
|
171
|
+
if (schema.rawTypeData?.properties) {
|
|
165
172
|
return {
|
|
166
173
|
...schema,
|
|
167
174
|
rawTypeData: {
|
|
168
175
|
...schema.rawTypeData,
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
176
|
+
$parsed: {
|
|
177
|
+
...schema.rawTypeData["$parsed"],
|
|
178
|
+
content: schema.rawTypeData["$parsed"].content.sort(sortByName),
|
|
179
|
+
},
|
|
180
|
+
},
|
|
181
|
+
};
|
|
172
182
|
}
|
|
173
183
|
return schema;
|
|
174
184
|
});
|
package/src/routeNames.js
CHANGED
|
@@ -13,19 +13,15 @@ const getRouteName = (routeInfo) => {
|
|
|
13
13
|
config,
|
|
14
14
|
});
|
|
15
15
|
|
|
16
|
-
const routeName =
|
|
17
|
-
config.hooks.onFormatRouteName(routeInfo, routeNameFromTemplate) || routeNameFromTemplate;
|
|
16
|
+
const routeName = config.hooks.onFormatRouteName(routeInfo, routeNameFromTemplate) || routeNameFromTemplate;
|
|
18
17
|
|
|
19
18
|
const duplicateIdentifier = `${moduleName}|${routeName}`;
|
|
20
19
|
|
|
21
20
|
if (routeNameDuplicatesMap.has(duplicateIdentifier)) {
|
|
22
|
-
routeNameDuplicatesMap.set(
|
|
23
|
-
duplicateIdentifier,
|
|
24
|
-
routeNameDuplicatesMap.get(duplicateIdentifier) + 1,
|
|
25
|
-
);
|
|
21
|
+
routeNameDuplicatesMap.set(duplicateIdentifier, routeNameDuplicatesMap.get(duplicateIdentifier) + 1);
|
|
26
22
|
|
|
27
23
|
logger.warn(
|
|
28
|
-
`Module "${moduleName}" already
|
|
24
|
+
`Module "${moduleName}" already has method "${routeName}()"`,
|
|
29
25
|
`\nThis method has been renamed to "${
|
|
30
26
|
routeName + routeNameDuplicatesMap.get(duplicateIdentifier)
|
|
31
27
|
}()" to solve conflict names.`,
|
package/src/routes.js
CHANGED
|
@@ -1,12 +1,5 @@
|
|
|
1
1
|
const _ = require("lodash");
|
|
2
|
-
const {
|
|
3
|
-
types,
|
|
4
|
-
parseSchema,
|
|
5
|
-
getType,
|
|
6
|
-
getRefType,
|
|
7
|
-
getInlineParseContent,
|
|
8
|
-
checkAndAddNull,
|
|
9
|
-
} = require("./schema");
|
|
2
|
+
const { types, parseSchema, getType, getRefType, getInlineParseContent, checkAndAddNull } = require("./schema");
|
|
10
3
|
const { formatModelName } = require("./modelNames");
|
|
11
4
|
const {
|
|
12
5
|
DEFAULT_BODY_ARG_NAME,
|
|
@@ -19,7 +12,7 @@ const {
|
|
|
19
12
|
} = require("./constants");
|
|
20
13
|
const { formatDescription, classNameCase } = require("./common");
|
|
21
14
|
const { config } = require("./config");
|
|
22
|
-
const {
|
|
15
|
+
const { generateId } = require("./utils/id");
|
|
23
16
|
const { getRouteName } = require("./routeNames");
|
|
24
17
|
const { createComponent } = require("./components");
|
|
25
18
|
const { logger } = require("./logger");
|
|
@@ -47,26 +40,15 @@ const getSchemaFromRequestType = (requestInfo) => {
|
|
|
47
40
|
return null;
|
|
48
41
|
};
|
|
49
42
|
|
|
50
|
-
const getTypeFromRequestInfo = ({
|
|
51
|
-
requestInfo,
|
|
52
|
-
parsedSchemas,
|
|
53
|
-
operationId,
|
|
54
|
-
defaultType,
|
|
55
|
-
typeName,
|
|
56
|
-
}) => {
|
|
43
|
+
const getTypeFromRequestInfo = ({ requestInfo, parsedSchemas, operationId, defaultType, typeName }) => {
|
|
57
44
|
// TODO: make more flexible pick schema without content type
|
|
58
45
|
const schema = getSchemaFromRequestType(requestInfo);
|
|
59
46
|
const refTypeInfo = getRefType(requestInfo);
|
|
60
47
|
|
|
61
48
|
if (schema) {
|
|
62
49
|
const content = getInlineParseContent(schema, typeName);
|
|
63
|
-
const foundedSchemaByName = _.find(
|
|
64
|
-
|
|
65
|
-
(parsedSchema) => formatModelName(parsedSchema.name) === content,
|
|
66
|
-
);
|
|
67
|
-
const foundSchemaByContent = _.find(parsedSchemas, (parsedSchema) =>
|
|
68
|
-
_.isEqual(parsedSchema.content, content),
|
|
69
|
-
);
|
|
50
|
+
const foundedSchemaByName = _.find(parsedSchemas, (parsedSchema) => formatModelName(parsedSchema.name) === content);
|
|
51
|
+
const foundSchemaByContent = _.find(parsedSchemas, (parsedSchema) => _.isEqual(parsedSchema.content, content));
|
|
70
52
|
|
|
71
53
|
const foundSchema = foundedSchemaByName || foundSchemaByContent;
|
|
72
54
|
|
|
@@ -88,10 +70,7 @@ const getTypeFromRequestInfo = ({
|
|
|
88
70
|
return formatModelName(refTypeInfo.typeName);
|
|
89
71
|
case "responses":
|
|
90
72
|
case "requestBodies":
|
|
91
|
-
return getInlineParseContent(
|
|
92
|
-
getSchemaFromRequestType(refTypeInfo.rawTypeData),
|
|
93
|
-
refTypeInfo.typeName || null,
|
|
94
|
-
);
|
|
73
|
+
return getInlineParseContent(getSchemaFromRequestType(refTypeInfo.rawTypeData), refTypeInfo.typeName || null);
|
|
95
74
|
default:
|
|
96
75
|
return getInlineParseContent(refTypeInfo.rawTypeData, refTypeInfo.typeName || null);
|
|
97
76
|
}
|
|
@@ -344,9 +323,7 @@ const createRequestParamsSchema = ({
|
|
|
344
323
|
if (fixedSchema) return fixedSchema;
|
|
345
324
|
|
|
346
325
|
if (extractRequestParams) {
|
|
347
|
-
const typeName = config.componentTypeNameResolver.resolve([
|
|
348
|
-
classNameCase(`${routeName.usage} Params`),
|
|
349
|
-
]);
|
|
326
|
+
const typeName = config.componentTypeNameResolver.resolve([classNameCase(`${routeName.usage} Params`)]);
|
|
350
327
|
|
|
351
328
|
return createComponent("schemas", typeName, { ...schema });
|
|
352
329
|
}
|
|
@@ -358,9 +335,7 @@ const getContentTypes = (requestInfo, extraContentTypes) =>
|
|
|
358
335
|
_.uniq(
|
|
359
336
|
_.compact([
|
|
360
337
|
...(extraContentTypes || []),
|
|
361
|
-
..._.flatten(
|
|
362
|
-
_.map(requestInfo, (requestInfoData) => requestInfoData && _.keys(requestInfoData.content)),
|
|
363
|
-
),
|
|
338
|
+
..._.flatten(_.map(requestInfo, (requestInfoData) => requestInfoData && _.keys(requestInfoData.content))),
|
|
364
339
|
]),
|
|
365
340
|
);
|
|
366
341
|
|
|
@@ -400,10 +375,7 @@ const getRequestBodyInfo = (routeInfo, routeParams, parsedSchemas, routeName) =>
|
|
|
400
375
|
let schema = null;
|
|
401
376
|
let type = null;
|
|
402
377
|
|
|
403
|
-
const contentTypes = getContentTypes(
|
|
404
|
-
[requestBody],
|
|
405
|
-
[...(consumes || []), routeInfo["x-contentType"]],
|
|
406
|
-
);
|
|
378
|
+
const contentTypes = getContentTypes([requestBody], [...(consumes || []), routeInfo["x-contentType"]]);
|
|
407
379
|
let contentKind = getContentKind(contentTypes);
|
|
408
380
|
|
|
409
381
|
let typeName = null;
|
|
@@ -454,8 +426,7 @@ const getRequestBodyInfo = (routeInfo, routeParams, parsedSchemas, routeName) =>
|
|
|
454
426
|
contentKind,
|
|
455
427
|
schema,
|
|
456
428
|
type,
|
|
457
|
-
required:
|
|
458
|
-
requestBody && (typeof requestBody.required === "undefined" || !!requestBody.required),
|
|
429
|
+
required: requestBody && (typeof requestBody.required === "undefined" || !!requestBody.required),
|
|
459
430
|
};
|
|
460
431
|
};
|
|
461
432
|
|
|
@@ -472,9 +443,7 @@ const getResponseBodyInfo = (routeInfo, routeParams, parsedSchemas) => {
|
|
|
472
443
|
});
|
|
473
444
|
|
|
474
445
|
const successResponse = responseInfos.find((response) => response.isSuccess);
|
|
475
|
-
const errorResponses = responseInfos.filter(
|
|
476
|
-
(response) => !response.isSuccess && response.type !== TS_KEYWORDS.ANY,
|
|
477
|
-
);
|
|
446
|
+
const errorResponses = responseInfos.filter((response) => !response.isSuccess && response.type !== TS_KEYWORDS.ANY);
|
|
478
447
|
|
|
479
448
|
const handleResponseHeaders = (src) => {
|
|
480
449
|
if (!src) {
|
|
@@ -507,24 +476,16 @@ const getResponseBodyInfo = (routeInfo, routeParams, parsedSchemas) => {
|
|
|
507
476
|
responseInfos
|
|
508
477
|
.map(
|
|
509
478
|
(response) => `{
|
|
510
|
-
data: ${response.type}, status: ${response.status}, statusCode: ${
|
|
511
|
-
response.
|
|
512
|
-
},
|
|
513
|
-
response.headers,
|
|
514
|
-
)} config: {} }`,
|
|
479
|
+
data: ${response.type}, status: ${response.status}, statusCode: ${response.status}, statusText: "${
|
|
480
|
+
response.description
|
|
481
|
+
}", ${handleResponseHeaders(response.headers)} config: {} }`,
|
|
515
482
|
)
|
|
516
483
|
.join(" | ") || TS_KEYWORDS.ANY,
|
|
517
484
|
},
|
|
518
485
|
};
|
|
519
486
|
};
|
|
520
487
|
|
|
521
|
-
const parseRoutes = ({
|
|
522
|
-
usageSchema,
|
|
523
|
-
parsedSchemas,
|
|
524
|
-
moduleNameIndex,
|
|
525
|
-
moduleNameFirstTag,
|
|
526
|
-
extractRequestParams,
|
|
527
|
-
}) => {
|
|
488
|
+
const parseRoutes = ({ usageSchema, parsedSchemas, moduleNameIndex, moduleNameFirstTag, extractRequestParams }) => {
|
|
528
489
|
const { paths, security: globalSecurity } = usageSchema;
|
|
529
490
|
const pathsEntries = _.entries(paths);
|
|
530
491
|
|
|
@@ -553,16 +514,13 @@ const parseRoutes = ({
|
|
|
553
514
|
} = routeInfo;
|
|
554
515
|
const { route, pathParams } = parseRoute(rawRoute);
|
|
555
516
|
|
|
556
|
-
const routeId =
|
|
517
|
+
const routeId = generateId();
|
|
557
518
|
const firstTag = tags && tags.length > 0 ? tags[0] : null;
|
|
558
519
|
const moduleName =
|
|
559
520
|
moduleNameFirstTag && firstTag
|
|
560
521
|
? _.camelCase(firstTag)
|
|
561
522
|
: _.camelCase(_.compact(_.split(route, "/"))[moduleNameIndex]);
|
|
562
|
-
const hasSecurity = !!(
|
|
563
|
-
(globalSecurity && globalSecurity.length) ||
|
|
564
|
-
(security && security.length)
|
|
565
|
-
);
|
|
523
|
+
const hasSecurity = !!((globalSecurity && globalSecurity.length) || (security && security.length));
|
|
566
524
|
|
|
567
525
|
const routeParams = getRouteParams(routeInfo, pathParams);
|
|
568
526
|
|
|
@@ -599,12 +557,7 @@ const parseRoutes = ({
|
|
|
599
557
|
|
|
600
558
|
const routeName = getRouteName(rawRouteInfo);
|
|
601
559
|
|
|
602
|
-
const requestBodyInfo = getRequestBodyInfo(
|
|
603
|
-
routeInfo,
|
|
604
|
-
routeParams,
|
|
605
|
-
parsedSchemas,
|
|
606
|
-
routeName,
|
|
607
|
-
);
|
|
560
|
+
const requestBodyInfo = getRequestBodyInfo(routeInfo, routeParams, parsedSchemas, routeName);
|
|
608
561
|
|
|
609
562
|
const requestParamsSchema = createRequestParamsSchema({
|
|
610
563
|
queryParams: routeParams.query,
|
|
@@ -614,13 +567,12 @@ const parseRoutes = ({
|
|
|
614
567
|
routeName,
|
|
615
568
|
});
|
|
616
569
|
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
570
|
+
extractResponseBodyIfItNeeded(routeInfo, responseBodyInfo, routeParams, rawRouteInfo, routeName);
|
|
571
|
+
extractResponseErrorIfItNeeded(routeInfo, responseBodyInfo, routeParams, rawRouteInfo, routeName);
|
|
572
|
+
|
|
573
|
+
const queryType = routeParams.query.length ? getInlineParseContent(queryObjectSchema) : null;
|
|
620
574
|
const pathType = routeParams.path.length ? getInlineParseContent(pathObjectSchema) : null;
|
|
621
|
-
const headersType = routeParams.header.length
|
|
622
|
-
? getInlineParseContent(headersObjectSchema)
|
|
623
|
-
: null;
|
|
575
|
+
const headersType = routeParams.header.length ? getInlineParseContent(headersObjectSchema) : null;
|
|
624
576
|
|
|
625
577
|
const nameResolver = new SpecificArgNameResolver(pathArgsNames);
|
|
626
578
|
|
|
@@ -634,10 +586,7 @@ const parseRoutes = ({
|
|
|
634
586
|
: void 0,
|
|
635
587
|
body: requestBodyInfo.type
|
|
636
588
|
? {
|
|
637
|
-
name: nameResolver.resolve([
|
|
638
|
-
requestBodyInfo.paramName,
|
|
639
|
-
...RESERVED_BODY_ARG_NAMES,
|
|
640
|
-
]),
|
|
589
|
+
name: nameResolver.resolve([requestBodyInfo.paramName, ...RESERVED_BODY_ARG_NAMES]),
|
|
641
590
|
optional: !requestBodyInfo.required,
|
|
642
591
|
type: requestBodyInfo.type,
|
|
643
592
|
}
|
|
@@ -764,10 +713,7 @@ const groupRoutes = (routes) => {
|
|
|
764
713
|
if (
|
|
765
714
|
packRoutes.length > 1 &&
|
|
766
715
|
usageName !== originalName &&
|
|
767
|
-
!_.some(
|
|
768
|
-
packRoutes,
|
|
769
|
-
({ routeName, id }) => id !== route.id && originalName === routeName.original,
|
|
770
|
-
)
|
|
716
|
+
!_.some(packRoutes, ({ routeName, id }) => id !== route.id && originalName === routeName.original)
|
|
771
717
|
) {
|
|
772
718
|
return {
|
|
773
719
|
...route,
|
|
@@ -788,6 +734,72 @@ const groupRoutes = (routes) => {
|
|
|
788
734
|
);
|
|
789
735
|
};
|
|
790
736
|
|
|
737
|
+
const extractResponseBodyIfItNeeded = (routeInfo, responseBodyInfo, routeParams, rawRouteInfo, routeName) => {
|
|
738
|
+
if (
|
|
739
|
+
config.extractResponseBody &&
|
|
740
|
+
responseBodyInfo.responses.length &&
|
|
741
|
+
responseBodyInfo.success &&
|
|
742
|
+
responseBodyInfo.success.schema
|
|
743
|
+
) {
|
|
744
|
+
const typeName = config.componentTypeNameResolver.resolve([
|
|
745
|
+
classNameCase(`${routeName.usage} Data`),
|
|
746
|
+
classNameCase(`${routeName.usage} Result`),
|
|
747
|
+
classNameCase(`${routeName.usage} Output`),
|
|
748
|
+
]);
|
|
749
|
+
|
|
750
|
+
const idx = responseBodyInfo.responses.indexOf(responseBodyInfo.success.schema);
|
|
751
|
+
|
|
752
|
+
let successResponse = responseBodyInfo.success;
|
|
753
|
+
|
|
754
|
+
if (successResponse.schema && !successResponse.schema.$ref) {
|
|
755
|
+
const schema = getSchemaFromRequestType(successResponse.schema);
|
|
756
|
+
successResponse.schema = createComponent("schemas", typeName, { ...schema });
|
|
757
|
+
successResponse.type = getInlineParseContent(successResponse.schema);
|
|
758
|
+
|
|
759
|
+
if (idx > -1) {
|
|
760
|
+
responseBodyInfo.responses[idx] = successResponse.schema;
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
};
|
|
765
|
+
|
|
766
|
+
const extractResponseErrorIfItNeeded = (routeInfo, responseBodyInfo, routeParams, rawRouteInfo, routeName) => {
|
|
767
|
+
if (
|
|
768
|
+
config.extractResponseError &&
|
|
769
|
+
responseBodyInfo.responses.length &&
|
|
770
|
+
responseBodyInfo.error.schemas &&
|
|
771
|
+
responseBodyInfo.error.schemas.length
|
|
772
|
+
) {
|
|
773
|
+
const typeName = config.componentTypeNameResolver.resolve([
|
|
774
|
+
classNameCase(`${routeName.usage} Error`),
|
|
775
|
+
classNameCase(`${routeName.usage} Fail`),
|
|
776
|
+
classNameCase(`${routeName.usage} Fails`),
|
|
777
|
+
classNameCase(`${routeName.usage} ErrorData`),
|
|
778
|
+
classNameCase(`${routeName.usage} HttpError`),
|
|
779
|
+
classNameCase(`${routeName.usage} BadResponse`),
|
|
780
|
+
]);
|
|
781
|
+
|
|
782
|
+
const errorSchemas = responseBodyInfo.error.schemas.map(getSchemaFromRequestType).filter(Boolean);
|
|
783
|
+
|
|
784
|
+
if (!errorSchemas.length) return;
|
|
785
|
+
|
|
786
|
+
const schema = parseSchema({
|
|
787
|
+
oneOf: errorSchemas,
|
|
788
|
+
title: errorSchemas
|
|
789
|
+
.map((schema) => schema.title)
|
|
790
|
+
.filter(Boolean)
|
|
791
|
+
.join(" "),
|
|
792
|
+
description: errorSchemas
|
|
793
|
+
.map((schema) => schema.description)
|
|
794
|
+
.filter(Boolean)
|
|
795
|
+
.join("\n"),
|
|
796
|
+
});
|
|
797
|
+
const component = createComponent("schemas", typeName, { ...schema });
|
|
798
|
+
responseBodyInfo.error.schemas = [component];
|
|
799
|
+
responseBodyInfo.error.type = formatModelName(component.typeName);
|
|
800
|
+
}
|
|
801
|
+
};
|
|
802
|
+
|
|
791
803
|
module.exports = {
|
|
792
804
|
parseRoutes,
|
|
793
805
|
groupRoutes,
|
package/src/schema.js
CHANGED
|
@@ -63,12 +63,7 @@ const getTypeAlias = (rawSchema) => {
|
|
|
63
63
|
};
|
|
64
64
|
|
|
65
65
|
const getEnumNames = (schema) => {
|
|
66
|
-
return
|
|
67
|
-
schema["x-enumNames"] ||
|
|
68
|
-
schema["xEnumNames"] ||
|
|
69
|
-
schema["x-enumnames"] ||
|
|
70
|
-
schema["x-enum-varnames"]
|
|
71
|
-
);
|
|
66
|
+
return schema["x-enumNames"] || schema["xEnumNames"] || schema["x-enumnames"] || schema["x-enum-varnames"];
|
|
72
67
|
};
|
|
73
68
|
|
|
74
69
|
const getInternalSchemaType = (schema) => {
|
|
@@ -137,6 +132,7 @@ const getObjectTypeContent = (schema) => {
|
|
|
137
132
|
const nullable = !!(rawTypeData.nullable || property.nullable);
|
|
138
133
|
const fieldName = isValidName(name) ? name : `"${name}"`;
|
|
139
134
|
const fieldValue = getInlineParseContent(property);
|
|
135
|
+
const readOnly = property.readOnly;
|
|
140
136
|
|
|
141
137
|
return {
|
|
142
138
|
$$raw: property,
|
|
@@ -147,20 +143,25 @@ const getObjectTypeContent = (schema) => {
|
|
|
147
143
|
rawTypeData.description ||
|
|
148
144
|
_.compact(_.map(rawTypeData[getComplexType(rawTypeData)], "description"))[0] ||
|
|
149
145
|
"",
|
|
146
|
+
!_.isUndefined(property.deprecated) && `@deprecated`,
|
|
150
147
|
!_.isUndefined(property.format) && `@format ${property.format}`,
|
|
151
148
|
!_.isUndefined(property.minimum) && `@min ${property.minimum}`,
|
|
152
149
|
!_.isUndefined(property.maximum) && `@max ${property.maximum}`,
|
|
153
150
|
!_.isUndefined(property.pattern) && `@pattern ${property.pattern}`,
|
|
154
151
|
!_.isUndefined(property.example) &&
|
|
155
|
-
`@example ${
|
|
156
|
-
_.isObject(property.example) ? JSON.stringify(property.example) : property.example
|
|
157
|
-
}`,
|
|
152
|
+
`@example ${_.isObject(property.example) ? JSON.stringify(property.example) : property.example}`,
|
|
158
153
|
]).join("\n"),
|
|
159
154
|
isRequired: required,
|
|
160
155
|
isNullable: nullable,
|
|
161
156
|
name: fieldName,
|
|
162
157
|
value: fieldValue,
|
|
163
|
-
field: _.compact([
|
|
158
|
+
field: _.compact([
|
|
159
|
+
readOnly && config.addReadonly && "readonly ",
|
|
160
|
+
fieldName,
|
|
161
|
+
!required && "?",
|
|
162
|
+
": ",
|
|
163
|
+
fieldValue,
|
|
164
|
+
]).join(""),
|
|
164
165
|
};
|
|
165
166
|
});
|
|
166
167
|
|
|
@@ -179,39 +180,73 @@ const getObjectTypeContent = (schema) => {
|
|
|
179
180
|
const complexTypeGetter = (schema) => getInlineParseContent(schema);
|
|
180
181
|
const filterContents = (contents, types) => _.filter(contents, (type) => !_.includes(types, type));
|
|
181
182
|
|
|
183
|
+
const makeAddRequiredToChildSchema = (parentSchema) => (childSchema) => {
|
|
184
|
+
let required = childSchema.required || [];
|
|
185
|
+
let properties = childSchema.properties || {};
|
|
186
|
+
|
|
187
|
+
// Inherit all the required fields from the parent schema that are defined
|
|
188
|
+
// either on the parent schema or on the child schema
|
|
189
|
+
// TODO: any that are defined at grandparents or higher are ignored
|
|
190
|
+
required = required.concat(
|
|
191
|
+
(parentSchema.required || []).filter(
|
|
192
|
+
(key) =>
|
|
193
|
+
!required.includes(key) && (_.keys(properties).includes(key) || _.keys(parentSchema.properties).includes(key)),
|
|
194
|
+
),
|
|
195
|
+
);
|
|
196
|
+
|
|
197
|
+
// Identify properties that are required in the child schema, but
|
|
198
|
+
// defined only in the parent schema (TODO: this only works one level deep)
|
|
199
|
+
const parentPropertiesRequiredByChild = required.filter(
|
|
200
|
+
(key) => !_.keys(childSchema.properties).includes(key) && _.keys(parentSchema.properties).includes(key),
|
|
201
|
+
);
|
|
202
|
+
|
|
203
|
+
// Add such properties to the child so that they can be overriden and made required
|
|
204
|
+
properties = {
|
|
205
|
+
...properties,
|
|
206
|
+
...parentPropertiesRequiredByChild.reduce(
|
|
207
|
+
(additionalProperties, key) => ({
|
|
208
|
+
...additionalProperties,
|
|
209
|
+
[key]: (parentSchema.properties || {})[key],
|
|
210
|
+
}),
|
|
211
|
+
{},
|
|
212
|
+
),
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
return _.merge(
|
|
216
|
+
{
|
|
217
|
+
required: required,
|
|
218
|
+
properties: properties,
|
|
219
|
+
},
|
|
220
|
+
childSchema,
|
|
221
|
+
);
|
|
222
|
+
};
|
|
223
|
+
|
|
182
224
|
const complexSchemaParsers = {
|
|
183
225
|
[SCHEMA_TYPES.COMPLEX_ONE_OF]: (schema) => {
|
|
184
226
|
// T1 | T2
|
|
185
|
-
const combined = _.map(schema.oneOf, complexTypeGetter);
|
|
227
|
+
const combined = _.map(_.map(schema.oneOf, makeAddRequiredToChildSchema(schema)), complexTypeGetter);
|
|
186
228
|
|
|
187
229
|
return checkAndAddNull(schema, filterContents(combined, [TS_KEYWORDS.ANY]).join(" | "));
|
|
188
230
|
},
|
|
189
231
|
[SCHEMA_TYPES.COMPLEX_ALL_OF]: (schema) => {
|
|
190
232
|
// T1 & T2
|
|
191
|
-
const combined = _.map(schema.allOf, complexTypeGetter);
|
|
233
|
+
const combined = _.map(_.map(schema.allOf, makeAddRequiredToChildSchema(schema)), complexTypeGetter);
|
|
192
234
|
return checkAndAddNull(
|
|
193
235
|
schema,
|
|
194
|
-
filterContents(combined, [...JS_EMPTY_TYPES, ...JS_PRIMITIVE_TYPES, TS_KEYWORDS.ANY]).join(
|
|
195
|
-
" & ",
|
|
196
|
-
),
|
|
236
|
+
filterContents(combined, [...JS_EMPTY_TYPES, ...JS_PRIMITIVE_TYPES, TS_KEYWORDS.ANY]).join(" & "),
|
|
197
237
|
);
|
|
198
238
|
},
|
|
199
239
|
[SCHEMA_TYPES.COMPLEX_ANY_OF]: (schema) => {
|
|
200
240
|
// T1 | T2 | (T1 & T2)
|
|
201
|
-
const combined = _.map(schema.anyOf, complexTypeGetter);
|
|
202
|
-
const nonEmptyTypesCombined = filterContents(combined, [
|
|
203
|
-
...JS_EMPTY_TYPES,
|
|
204
|
-
...JS_PRIMITIVE_TYPES,
|
|
205
|
-
TS_KEYWORDS.ANY,
|
|
206
|
-
]);
|
|
241
|
+
const combined = _.map(_.map(schema.anyOf, makeAddRequiredToChildSchema(schema)), complexTypeGetter);
|
|
242
|
+
const nonEmptyTypesCombined = filterContents(combined, [...JS_EMPTY_TYPES, ...JS_PRIMITIVE_TYPES, TS_KEYWORDS.ANY]);
|
|
207
243
|
return checkAndAddNull(
|
|
208
244
|
schema,
|
|
209
|
-
`${combined.join(" | ")}` +
|
|
210
|
-
(nonEmptyTypesCombined.length > 1 ? ` | (${nonEmptyTypesCombined.join(" & ")})` : ""),
|
|
245
|
+
`${combined.join(" | ")}` + (nonEmptyTypesCombined.length > 1 ? ` | (${nonEmptyTypesCombined.join(" & ")})` : ""),
|
|
211
246
|
);
|
|
212
247
|
},
|
|
213
248
|
// TODO
|
|
214
|
-
[SCHEMA_TYPES.
|
|
249
|
+
[SCHEMA_TYPES.COMPLEX_NOT]: (schema) => {
|
|
215
250
|
// TODO
|
|
216
251
|
return TS_KEYWORDS.ANY;
|
|
217
252
|
},
|
|
@@ -228,8 +263,7 @@ const getComplexType = (schema) => {
|
|
|
228
263
|
};
|
|
229
264
|
|
|
230
265
|
const attachParsedRef = (originalSchema, parsedSchema) => {
|
|
231
|
-
const parsedSchemaAfterHook =
|
|
232
|
-
config.hooks.onParseSchema(originalSchema, parsedSchema) || parsedSchema;
|
|
266
|
+
const parsedSchemaAfterHook = config.hooks.onParseSchema(originalSchema, parsedSchema) || parsedSchema;
|
|
233
267
|
|
|
234
268
|
if (originalSchema) {
|
|
235
269
|
originalSchema.$parsed = parsedSchemaAfterHook;
|
|
@@ -264,12 +298,7 @@ const schemaParsers = {
|
|
|
264
298
|
return {
|
|
265
299
|
key: formattedKey,
|
|
266
300
|
type: keyType,
|
|
267
|
-
value:
|
|
268
|
-
enumValue === null
|
|
269
|
-
? enumValue
|
|
270
|
-
: isIntegerOrBooleanEnum
|
|
271
|
-
? `${enumValue}`
|
|
272
|
-
: `"${enumValue}"`,
|
|
301
|
+
value: enumValue === null ? enumValue : isIntegerOrBooleanEnum ? `${enumValue}` : `"${enumValue}"`,
|
|
273
302
|
};
|
|
274
303
|
});
|
|
275
304
|
} else {
|
|
@@ -291,9 +320,7 @@ const schemaParsers = {
|
|
|
291
320
|
type: SCHEMA_TYPES.ENUM,
|
|
292
321
|
keyType: keyType,
|
|
293
322
|
typeIdentifier:
|
|
294
|
-
config.generateUnionEnums || (!enumNames && isIntegerOrBooleanEnum)
|
|
295
|
-
? TS_KEYWORDS.TYPE
|
|
296
|
-
: TS_KEYWORDS.ENUM,
|
|
323
|
+
config.generateUnionEnums || (!enumNames && isIntegerOrBooleanEnum) ? TS_KEYWORDS.TYPE : TS_KEYWORDS.ENUM,
|
|
297
324
|
name: typeName,
|
|
298
325
|
description: formatDescription(schema.description),
|
|
299
326
|
content,
|
|
@@ -332,8 +359,7 @@ const schemaParsers = {
|
|
|
332
359
|
content:
|
|
333
360
|
_.compact([
|
|
334
361
|
complexSchemaContent && `(${complexSchemaContent})`,
|
|
335
|
-
getInternalSchemaType(simpleSchema) === TS_KEYWORDS.OBJECT &&
|
|
336
|
-
getInlineParseContent(simpleSchema),
|
|
362
|
+
getInternalSchemaType(simpleSchema) === TS_KEYWORDS.OBJECT && getInlineParseContent(simpleSchema),
|
|
337
363
|
]).join(" & ") || TS_KEYWORDS.ANY,
|
|
338
364
|
});
|
|
339
365
|
},
|
|
@@ -401,10 +427,7 @@ const parseSchema = (rawSchema, typeName, formattersMap) => {
|
|
|
401
427
|
parsedSchema = schemaParsers[schemaType](fixedRawSchema, typeName);
|
|
402
428
|
}
|
|
403
429
|
|
|
404
|
-
return (
|
|
405
|
-
(formattersMap && formattersMap[schemaType] && formattersMap[schemaType](parsedSchema)) ||
|
|
406
|
-
parsedSchema
|
|
407
|
-
);
|
|
430
|
+
return (formattersMap && formattersMap[schemaType] && formattersMap[schemaType](parsedSchema)) || parsedSchema;
|
|
408
431
|
};
|
|
409
432
|
|
|
410
433
|
const parseSchemas = (components) =>
|
|
@@ -413,8 +436,7 @@ const parseSchemas = (components) =>
|
|
|
413
436
|
const getInlineParseContent = (rawTypeData, typeName = null) =>
|
|
414
437
|
parseSchema(rawTypeData, typeName, inlineExtraFormatters).content;
|
|
415
438
|
|
|
416
|
-
const getParseContent = (rawTypeData, typeName = null) =>
|
|
417
|
-
parseSchema(rawTypeData, typeName).content;
|
|
439
|
+
const getParseContent = (rawTypeData, typeName = null) => parseSchema(rawTypeData, typeName).content;
|
|
418
440
|
|
|
419
441
|
module.exports = {
|
|
420
442
|
types,
|
package/src/swagger.js
CHANGED
|
@@ -17,7 +17,7 @@ const parseSwaggerFile = (file) => {
|
|
|
17
17
|
}
|
|
18
18
|
};
|
|
19
19
|
|
|
20
|
-
const getSwaggerFile = (pathToSwagger, urlToSwagger, disableStrictSSL, disableProxy) =>
|
|
20
|
+
const getSwaggerFile = (pathToSwagger, urlToSwagger, disableStrictSSL, disableProxy, authorizationToken) =>
|
|
21
21
|
new Promise((resolve, reject) => {
|
|
22
22
|
if (pathIsExist(pathToSwagger)) {
|
|
23
23
|
logger.log(`try to get swagger by path "${pathToSwagger}"`);
|
|
@@ -33,15 +33,21 @@ const getSwaggerFile = (pathToSwagger, urlToSwagger, disableStrictSSL, disablePr
|
|
|
33
33
|
});
|
|
34
34
|
}
|
|
35
35
|
//
|
|
36
|
+
if (authorizationToken) {
|
|
37
|
+
axiosOptions.headers = {
|
|
38
|
+
Authorization: authorizationToken,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
//
|
|
36
42
|
if (disableProxy) axiosOptions.proxy = false;
|
|
37
43
|
//
|
|
38
44
|
axios
|
|
39
45
|
.get(urlToSwagger, axiosOptions)
|
|
40
46
|
.then((res) => resolve(res.data))
|
|
41
|
-
.catch(() => {
|
|
47
|
+
.catch((error) => {
|
|
42
48
|
const message = `error while getting swagger by URL ${urlToSwagger}`;
|
|
43
49
|
|
|
44
|
-
logger.error(message);
|
|
50
|
+
logger.error(message, "response" in error ? error.response : error);
|
|
45
51
|
|
|
46
52
|
reject(message);
|
|
47
53
|
});
|
|
@@ -53,9 +59,10 @@ const getSwaggerObject = (
|
|
|
53
59
|
urlToSwagger,
|
|
54
60
|
disableStrictSSL,
|
|
55
61
|
disableProxy,
|
|
62
|
+
authorizationToken,
|
|
56
63
|
converterOptions,
|
|
57
64
|
) =>
|
|
58
|
-
getSwaggerFile(pathToSwagger, urlToSwagger, disableStrictSSL, disableProxy).then((file) =>
|
|
65
|
+
getSwaggerFile(pathToSwagger, urlToSwagger, disableStrictSSL, disableProxy, authorizationToken).then((file) =>
|
|
59
66
|
convertSwaggerObject(parseSwaggerFile(file), converterOptions),
|
|
60
67
|
);
|
|
61
68
|
|
package/src/utils/id.js
ADDED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<%
|
|
2
2
|
const { modelTypes, utils } = it;
|
|
3
3
|
const { formatDescription, require, _ } = utils;
|
|
4
|
-
|
|
4
|
+
|
|
5
5
|
|
|
6
6
|
const dataContractTemplates = {
|
|
7
7
|
enum: (contract) => {
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
|
|
21
21
|
return _.compact([
|
|
22
22
|
contract.description && formatDescription(contract.description),
|
|
23
|
+
contract.typeData.deprecated === true && '@deprecated',
|
|
23
24
|
!_.isUndefined(contract.typeData.format) && `@format ${contract.typeData.format}`,
|
|
24
25
|
!_.isUndefined(contract.typeData.minimum) && `@min ${contract.typeData.minimum}`,
|
|
25
26
|
!_.isUndefined(contract.typeData.maximum) && `@max ${contract.typeData.maximum}`,
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
const { apiConfig, generateResponses, config } = it;
|
|
3
3
|
%>
|
|
4
4
|
|
|
5
|
-
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, ResponseType } from "axios";
|
|
5
|
+
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, ResponseType, HeadersDefaults } from "axios";
|
|
6
6
|
|
|
7
7
|
export type QueryParamsType = Record<string | number, any>;
|
|
8
8
|
|
|
@@ -53,20 +53,44 @@ export class HttpClient<SecurityDataType = unknown> {
|
|
|
53
53
|
this.securityData = data
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
56
|
+
protected mergeRequestParams(params1: AxiosRequestConfig, params2?: AxiosRequestConfig): AxiosRequestConfig {
|
|
57
|
+
const method = params1.method || (params2 && params2.method)
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
...this.instance.defaults,
|
|
61
|
+
...params1,
|
|
62
|
+
...(params2 || {}),
|
|
63
|
+
headers: {
|
|
64
|
+
...((method && this.instance.defaults.headers[method.toLowerCase() as keyof HeadersDefaults]) || {}),
|
|
65
|
+
...(params1.headers || {}),
|
|
66
|
+
...((params2 && params2.headers) || {}),
|
|
67
|
+
},
|
|
68
|
+
};
|
|
67
69
|
}
|
|
68
70
|
|
|
69
|
-
|
|
71
|
+
protected stringifyFormItem(formItem: unknown) {
|
|
72
|
+
if (typeof formItem === "object" && formItem !== null) {
|
|
73
|
+
return JSON.stringify(formItem);
|
|
74
|
+
} else {
|
|
75
|
+
return `${formItem}`;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
protected createFormData(input: Record<string, unknown>): FormData {
|
|
80
|
+
return Object.keys(input || {}).reduce((formData, key) => {
|
|
81
|
+
const property = input[key];
|
|
82
|
+
const propertyContent: Iterable<any> = (property instanceof Array) ? property : [property]
|
|
83
|
+
|
|
84
|
+
for (const formItem of propertyContent) {
|
|
85
|
+
const isFileType = formItem instanceof Blob || formItem instanceof File;
|
|
86
|
+
formData.append(
|
|
87
|
+
key,
|
|
88
|
+
isFileType ? formItem : this.stringifyFormItem(formItem)
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return formData;
|
|
93
|
+
}, new FormData());
|
|
70
94
|
return Object.keys(input || {}).reduce((formData, key) => {
|
|
71
95
|
const property = input[key];
|
|
72
96
|
formData.append(
|
|
@@ -96,13 +120,9 @@ export class HttpClient<SecurityDataType = unknown> {
|
|
|
96
120
|
<% } %>
|
|
97
121
|
const secureParams = ((typeof secure === 'boolean' ? secure : this.secure) && this.securityWorker && (await this.securityWorker(this.securityData))) || {};
|
|
98
122
|
const requestParams = this.mergeRequestParams(params, secureParams);
|
|
99
|
-
const responseFormat = (format
|
|
123
|
+
const responseFormat = (format || this.format) || undefined;
|
|
100
124
|
|
|
101
125
|
if (type === ContentType.FormData && body && body !== null && typeof body === "object") {
|
|
102
|
-
requestParams.headers.common = { Accept: "*/*" };
|
|
103
|
-
requestParams.headers.post = {};
|
|
104
|
-
requestParams.headers.put = {};
|
|
105
|
-
|
|
106
126
|
body = this.createFormData(body as Record<string, unknown>);
|
|
107
127
|
}
|
|
108
128
|
|
|
@@ -68,17 +68,17 @@ export class HttpClient<SecurityDataType = unknown> {
|
|
|
68
68
|
public setSecurityData = (data: SecurityDataType | null) => {
|
|
69
69
|
this.securityData = data;
|
|
70
70
|
}
|
|
71
|
-
|
|
72
|
-
|
|
71
|
+
|
|
72
|
+
protected encodeQueryParam(key: string, value: any) {
|
|
73
73
|
const encodedKey = encodeURIComponent(key);
|
|
74
74
|
return `${encodedKey}=${encodeURIComponent(typeof value === "number" ? value : `${value}`)}`;
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
|
|
77
|
+
protected addQueryParam(query: QueryParamsType, key: string) {
|
|
78
78
|
return this.encodeQueryParam(key, query[key]);
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
|
|
81
|
+
protected addArrayQueryParam(query: QueryParamsType, key: string) {
|
|
82
82
|
const value = query[key];
|
|
83
83
|
return value.map((v: any) => this.encodeQueryParam(key, v)).join("&");
|
|
84
84
|
}
|
|
@@ -118,7 +118,7 @@ export class HttpClient<SecurityDataType = unknown> {
|
|
|
118
118
|
[ContentType.UrlEncoded]: (input: any) => this.toQueryString(input),
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
-
|
|
121
|
+
protected mergeRequestParams(params1: RequestParams, params2?: RequestParams): RequestParams {
|
|
122
122
|
return {
|
|
123
123
|
...this.baseApiParams,
|
|
124
124
|
...params1,
|
|
@@ -131,7 +131,7 @@ export class HttpClient<SecurityDataType = unknown> {
|
|
|
131
131
|
};
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
-
|
|
134
|
+
protected createAbortSignal = (cancelToken: CancelToken): AbortSignal | undefined => {
|
|
135
135
|
if (this.abortControllers.has(cancelToken)) {
|
|
136
136
|
const abortController = this.abortControllers.get(cancelToken);
|
|
137
137
|
if (abortController) {
|
|
@@ -183,7 +183,7 @@ export class HttpClient<SecurityDataType = unknown> {
|
|
|
183
183
|
...(type && type !== ContentType.FormData ? { "Content-Type": type } : {}),
|
|
184
184
|
...(requestParams.headers || {}),
|
|
185
185
|
},
|
|
186
|
-
signal: cancelToken ? this.createAbortSignal(cancelToken) :
|
|
186
|
+
signal: cancelToken ? this.createAbortSignal(cancelToken) : requestParams.signal,
|
|
187
187
|
body: typeof body === "undefined" || body === null ? null : payloadFormatter(body),
|
|
188
188
|
}
|
|
189
189
|
).then(async (response) => {
|
|
@@ -36,7 +36,7 @@ const descriptionLines = _.compact([
|
|
|
36
36
|
<% }) %>
|
|
37
37
|
*/
|
|
38
38
|
<% } %>
|
|
39
|
-
export class
|
|
39
|
+
export class <%~ config.apiClassName %><SecurityDataType extends unknown><% if (!config.singleHttpClient) { %> extends HttpClient<SecurityDataType> <% } %> {
|
|
40
40
|
|
|
41
41
|
<% if(config.singleHttpClient) { %>
|
|
42
42
|
http: HttpClient<SecurityDataType>;
|