swagger-typescript-api 12.0.4 → 13.0.0

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.
Files changed (75) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +1 -1
  3. package/cli/constants.js +3 -3
  4. package/cli/execute.js +52 -31
  5. package/cli/index.d.ts +1 -2
  6. package/cli/index.js +18 -17
  7. package/cli/operations/display-help.js +51 -29
  8. package/cli/parse-args.js +3 -3
  9. package/cli/process-option.js +28 -20
  10. package/index.d.ts +99 -7
  11. package/index.js +158 -136
  12. package/package.json +35 -30
  13. package/src/code-formatter.js +28 -13
  14. package/src/code-gen-process.js +367 -264
  15. package/src/commands/generate-templates/configuration.js +2 -2
  16. package/src/commands/generate-templates/index.js +1 -2
  17. package/src/commands/generate-templates/templates-gen-process.js +62 -35
  18. package/src/component-type-name-resolver.js +44 -0
  19. package/src/configuration.js +166 -98
  20. package/src/constants.js +28 -22
  21. package/src/index.js +3 -4
  22. package/src/schema-components-map.js +39 -23
  23. package/src/schema-parser/base-schema-parsers/array.js +43 -0
  24. package/src/schema-parser/base-schema-parsers/complex.js +51 -0
  25. package/src/schema-parser/base-schema-parsers/discriminator.js +301 -0
  26. package/src/schema-parser/base-schema-parsers/enum.js +158 -0
  27. package/src/schema-parser/base-schema-parsers/object.js +105 -0
  28. package/src/schema-parser/base-schema-parsers/primitive.js +63 -0
  29. package/src/schema-parser/complex-schema-parsers/all-of.js +26 -0
  30. package/src/schema-parser/complex-schema-parsers/any-of.js +34 -0
  31. package/src/schema-parser/complex-schema-parsers/not.js +9 -0
  32. package/src/schema-parser/complex-schema-parsers/one-of.js +27 -0
  33. package/src/schema-parser/mono-schema-parser.js +48 -0
  34. package/src/schema-parser/schema-formatters.js +58 -44
  35. package/src/schema-parser/schema-parser-fabric.js +131 -0
  36. package/src/schema-parser/schema-parser.js +212 -361
  37. package/src/schema-parser/schema-utils.js +158 -33
  38. package/src/schema-parser/util/enum-key-resolver.js +26 -0
  39. package/src/{schema-parser → schema-routes}/schema-routes.js +472 -203
  40. package/src/schema-routes/util/specific-arg-name-resolver.js +26 -0
  41. package/src/schema-walker.js +93 -0
  42. package/src/swagger-schema-resolver.js +61 -28
  43. package/src/templates-worker.js +240 -0
  44. package/src/translators/javascript.js +83 -0
  45. package/src/translators/translator.js +35 -0
  46. package/src/{type-name.js → type-name-formatter.js} +35 -20
  47. package/src/util/file-system.js +30 -14
  48. package/src/util/id.js +2 -2
  49. package/src/util/internal-case.js +1 -1
  50. package/src/util/logger.js +46 -20
  51. package/src/util/name-resolver.js +50 -58
  52. package/src/util/object-assign.js +7 -3
  53. package/src/util/pascal-case.js +1 -1
  54. package/src/util/request.js +5 -5
  55. package/src/util/sort-by-property.js +17 -0
  56. package/templates/base/data-contract-jsdoc.ejs +37 -37
  57. package/templates/base/data-contracts.ejs +40 -28
  58. package/templates/base/enum-data-contract.ejs +12 -12
  59. package/templates/base/http-client.ejs +2 -2
  60. package/templates/base/http-clients/axios-http-client.ejs +139 -138
  61. package/templates/base/http-clients/fetch-http-client.ejs +224 -224
  62. package/templates/base/interface-data-contract.ejs +10 -10
  63. package/templates/base/object-field-jsdoc.ejs +28 -28
  64. package/templates/base/route-docs.ejs +30 -30
  65. package/templates/base/route-name.ejs +42 -42
  66. package/templates/base/route-type.ejs +22 -21
  67. package/templates/base/type-data-contract.ejs +15 -15
  68. package/templates/default/api.ejs +69 -65
  69. package/templates/default/procedure-call.ejs +100 -100
  70. package/templates/default/route-types.ejs +32 -28
  71. package/templates/modular/api.ejs +28 -28
  72. package/templates/modular/procedure-call.ejs +100 -100
  73. package/templates/modular/route-types.ejs +18 -18
  74. package/src/templates.js +0 -177
  75. package/src/translators/JavaScript.js +0 -60
@@ -1,28 +1,40 @@
1
- <%
2
- const { modelTypes, utils, config } = it;
3
- const { formatDescription, require, _, Ts } = utils;
4
-
5
-
6
- const dataContractTemplates = {
7
- enum: (contract) => {
8
- return `enum ${contract.name} {\r\n${contract.content} \r\n }`;
9
- },
10
- interface: (contract) => {
11
- return `interface ${contract.name} {\r\n${contract.content}}`;
12
- },
13
- type: (contract) => {
14
- return `type ${contract.name} = ${contract.content}`;
15
- },
16
- }
17
- %>
18
-
19
- <% if (config.internalTemplateOptions.addUtilRequiredKeysType) { %>
20
- type <%~ config.Ts.CodeGenKeyword.UtilRequiredKeys %><T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>
21
- <% } %>
22
-
23
- <% modelTypes.forEach((contract) => { %>
24
- <%~ includeFile('@base/data-contract-jsdoc.ejs', { ...it, data: { ...contract, ...contract.typeData } }) %>
25
- export <%~ (dataContractTemplates[contract.typeIdentifier] || dataContractTemplates.type)(contract) %>
26
-
27
-
28
- <% }) %>
1
+ <%
2
+ const { modelTypes, utils, config } = it;
3
+ const { formatDescription, require, _, Ts } = utils;
4
+
5
+
6
+ const buildGenerics = (contract) => {
7
+ if (!contract.genericArgs || !contract.genericArgs.length) return '';
8
+
9
+ return '<' + contract.genericArgs.map(({ name, default: defaultType, extends: extendsType }) => {
10
+ return [
11
+ name,
12
+ extendsType && `extends ${extendsType}`,
13
+ defaultType && `= ${defaultType}`,
14
+ ].join('')
15
+ }).join(',') + '>'
16
+ }
17
+
18
+ const dataContractTemplates = {
19
+ enum: (contract) => {
20
+ return `enum ${contract.name} {\r\n${contract.content} \r\n }`;
21
+ },
22
+ interface: (contract) => {
23
+ return `interface ${contract.name}${buildGenerics(contract)} {\r\n${contract.content}}`;
24
+ },
25
+ type: (contract) => {
26
+ return `type ${contract.name}${buildGenerics(contract)} = ${contract.content}`;
27
+ },
28
+ }
29
+ %>
30
+
31
+ <% if (config.internalTemplateOptions.addUtilRequiredKeysType) { %>
32
+ type <%~ config.Ts.CodeGenKeyword.UtilRequiredKeys %><T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>
33
+ <% } %>
34
+
35
+ <% for (const contract of modelTypes) { %>
36
+ <%~ includeFile('@base/data-contract-jsdoc.ejs', { ...it, data: { ...contract, ...contract.typeData } }) %>
37
+ <%~ contract.internal ? '' : 'export'%> <%~ (dataContractTemplates[contract.typeIdentifier] || dataContractTemplates.type)(contract) %>
38
+
39
+
40
+ <% } %>
@@ -1,12 +1,12 @@
1
- <%
2
- const { contract, utils, config } = it;
3
- const { formatDescription, require, _ } = utils;
4
- const { name, $content } = contract;
5
- %>
6
- <% if (config.generateUnionEnums) { %>
7
- export type <%~ name %> = <%~ _.map($content, ({ value }) => value).join(" | ") %>
8
- <% } else { %>
9
- export enum <%~ name %> {
10
- <%~ _.map($content, ({ key, value }) => `${key} = ${value}`).join(",\n") %>
11
- }
12
- <% } %>
1
+ <%
2
+ const { contract, utils, config } = it;
3
+ const { formatDescription, require, _ } = utils;
4
+ const { name, $content } = contract;
5
+ %>
6
+ <% if (config.generateUnionEnums) { %>
7
+ export type <%~ name %> = <%~ _.map($content, ({ value }) => value).join(" | ") %>
8
+ <% } else { %>
9
+ export enum <%~ name %> {
10
+ <%~ _.map($content, ({ key, value }) => `${key} = ${value}`).join(",\n") %>
11
+ }
12
+ <% } %>
@@ -1,3 +1,3 @@
1
- <% const { config } = it; %>
2
- <% /* https://github.com/acacode/swagger-typescript-api/tree/next/templates/base/http-clients/ */ %>
1
+ <% const { config } = it; %>
2
+ <% /* https://github.com/acacode/swagger-typescript-api/tree/next/templates/base/http-clients/ */ %>
3
3
  <%~ includeFile(`@base/http-clients/${config.httpClientType}-http-client`, it) %>
@@ -1,138 +1,139 @@
1
- <%
2
- const { apiConfig, generateResponses, config } = it;
3
- %>
4
-
5
- import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, ResponseType, HeadersDefaults } from "axios";
6
-
7
- export type QueryParamsType = Record<string | number, any>;
8
-
9
- export interface FullRequestParams extends Omit<AxiosRequestConfig, "data" | "params" | "url" | "responseType"> {
10
- /** set parameter to `true` for call `securityWorker` for this request */
11
- secure?: boolean;
12
- /** request path */
13
- path: string;
14
- /** content type of request body */
15
- type?: ContentType;
16
- /** query params */
17
- query?: QueryParamsType;
18
- /** format of response (i.e. response.json() -> format: "json") */
19
- format?: ResponseType;
20
- /** request body */
21
- body?: unknown;
22
- }
23
-
24
- export type RequestParams = Omit<FullRequestParams, "body" | "method" | "query" | "path">;
25
-
26
- export interface ApiConfig<SecurityDataType = unknown> extends Omit<AxiosRequestConfig, "data" | "cancelToken"> {
27
- securityWorker?: (securityData: SecurityDataType | null) => Promise<AxiosRequestConfig | void> | AxiosRequestConfig | void;
28
- secure?: boolean;
29
- format?: ResponseType;
30
- }
31
-
32
- export enum ContentType {
33
- Json = "application/json",
34
- FormData = "multipart/form-data",
35
- UrlEncoded = "application/x-www-form-urlencoded",
36
- Text = "text/plain",
37
- }
38
-
39
- export class HttpClient<SecurityDataType = unknown> {
40
- public instance: AxiosInstance;
41
- private securityData: SecurityDataType | null = null;
42
- private securityWorker?: ApiConfig<SecurityDataType>["securityWorker"];
43
- private secure?: boolean;
44
- private format?: ResponseType;
45
-
46
- constructor({ securityWorker, secure, format, ...axiosConfig }: ApiConfig<SecurityDataType> = {}) {
47
- this.instance = axios.create({ ...axiosConfig, baseURL: axiosConfig.baseURL || "<%~ apiConfig.baseUrl %>" })
48
- this.secure = secure;
49
- this.format = format;
50
- this.securityWorker = securityWorker;
51
- }
52
-
53
- public setSecurityData = (data: SecurityDataType | null) => {
54
- this.securityData = data
55
- }
56
-
57
- protected mergeRequestParams(params1: AxiosRequestConfig, params2?: AxiosRequestConfig): AxiosRequestConfig {
58
- const method = params1.method || (params2 && params2.method)
59
-
60
- return {
61
- ...this.instance.defaults,
62
- ...params1,
63
- ...(params2 || {}),
64
- headers: {
65
- ...((method && this.instance.defaults.headers[method.toLowerCase() as keyof HeadersDefaults]) || {}),
66
- ...(params1.headers || {}),
67
- ...((params2 && params2.headers) || {}),
68
- },
69
- };
70
- }
71
-
72
- protected stringifyFormItem(formItem: unknown) {
73
- if (typeof formItem === "object" && formItem !== null) {
74
- return JSON.stringify(formItem);
75
- } else {
76
- return `${formItem}`;
77
- }
78
- }
79
-
80
- protected createFormData(input: Record<string, unknown>): FormData {
81
- return Object.keys(input || {}).reduce((formData, key) => {
82
- const property = input[key];
83
- const propertyContent: any[] = (property instanceof Array) ? property : [property]
84
-
85
- for (const formItem of propertyContent) {
86
- const isFileType = formItem instanceof Blob || formItem instanceof File;
87
- formData.append(
88
- key,
89
- isFileType ? formItem : this.stringifyFormItem(formItem)
90
- );
91
- }
92
-
93
- return formData;
94
- }, new FormData());
95
- }
96
-
97
- public request = async <T = any, _E = any>({
98
- secure,
99
- path,
100
- type,
101
- query,
102
- format,
103
- body,
104
- ...params
105
- <% if (config.unwrapResponseData) { %>
106
- }: FullRequestParams): Promise<T> => {
107
- <% } else { %>
108
- }: FullRequestParams): Promise<AxiosResponse<T>> => {
109
- <% } %>
110
- const secureParams = ((typeof secure === 'boolean' ? secure : this.secure) && this.securityWorker && (await this.securityWorker(this.securityData))) || {};
111
- const requestParams = this.mergeRequestParams(params, secureParams);
112
- const responseFormat = (format || this.format) || undefined;
113
-
114
- if (type === ContentType.FormData && body && body !== null && typeof body === "object") {
115
- body = this.createFormData(body as Record<string, unknown>);
116
- }
117
-
118
- if (type === ContentType.Text && body && body !== null && typeof body !== "string") {
119
- body = JSON.stringify(body);
120
- }
121
-
122
- return this.instance.request({
123
- ...requestParams,
124
- headers: {
125
- ...(requestParams.headers || {}),
126
- ...(type && type !== ContentType.FormData ? { "Content-Type": type } : {}),
127
- },
128
- params: query,
129
- responseType: responseFormat,
130
- data: body,
131
- url: path,
132
- <% if (config.unwrapResponseData) { %>
133
- }).then(response => response.data);
134
- <% } else { %>
135
- });
136
- <% } %>
137
- };
138
- }
1
+ <%
2
+ const { apiConfig, generateResponses, config } = it;
3
+ %>
4
+
5
+ import type { AxiosInstance, AxiosRequestConfig, HeadersDefaults, ResponseType, AxiosResponse } from "axios";
6
+ import axios from "axios";
7
+
8
+ export type QueryParamsType = Record<string | number, any>;
9
+
10
+ export interface FullRequestParams extends Omit<AxiosRequestConfig, "data" | "params" | "url" | "responseType"> {
11
+ /** set parameter to `true` for call `securityWorker` for this request */
12
+ secure?: boolean;
13
+ /** request path */
14
+ path: string;
15
+ /** content type of request body */
16
+ type?: ContentType;
17
+ /** query params */
18
+ query?: QueryParamsType;
19
+ /** format of response (i.e. response.json() -> format: "json") */
20
+ format?: ResponseType;
21
+ /** request body */
22
+ body?: unknown;
23
+ }
24
+
25
+ export type RequestParams = Omit<FullRequestParams, "body" | "method" | "query" | "path">;
26
+
27
+ export interface ApiConfig<SecurityDataType = unknown> extends Omit<AxiosRequestConfig, "data" | "cancelToken"> {
28
+ securityWorker?: (securityData: SecurityDataType | null) => Promise<AxiosRequestConfig | void> | AxiosRequestConfig | void;
29
+ secure?: boolean;
30
+ format?: ResponseType;
31
+ }
32
+
33
+ export enum ContentType {
34
+ Json = "application/json",
35
+ FormData = "multipart/form-data",
36
+ UrlEncoded = "application/x-www-form-urlencoded",
37
+ Text = "text/plain",
38
+ }
39
+
40
+ export class HttpClient<SecurityDataType = unknown> {
41
+ public instance: AxiosInstance;
42
+ private securityData: SecurityDataType | null = null;
43
+ private securityWorker?: ApiConfig<SecurityDataType>["securityWorker"];
44
+ private secure?: boolean;
45
+ private format?: ResponseType;
46
+
47
+ constructor({ securityWorker, secure, format, ...axiosConfig }: ApiConfig<SecurityDataType> = {}) {
48
+ this.instance = axios.create({ ...axiosConfig, baseURL: axiosConfig.baseURL || "<%~ apiConfig.baseUrl %>" })
49
+ this.secure = secure;
50
+ this.format = format;
51
+ this.securityWorker = securityWorker;
52
+ }
53
+
54
+ public setSecurityData = (data: SecurityDataType | null) => {
55
+ this.securityData = data
56
+ }
57
+
58
+ protected mergeRequestParams(params1: AxiosRequestConfig, params2?: AxiosRequestConfig): AxiosRequestConfig {
59
+ const method = params1.method || (params2 && params2.method)
60
+
61
+ return {
62
+ ...this.instance.defaults,
63
+ ...params1,
64
+ ...(params2 || {}),
65
+ headers: {
66
+ ...((method && this.instance.defaults.headers[method.toLowerCase() as keyof HeadersDefaults]) || {}),
67
+ ...(params1.headers || {}),
68
+ ...((params2 && params2.headers) || {}),
69
+ },
70
+ };
71
+ }
72
+
73
+ protected stringifyFormItem(formItem: unknown) {
74
+ if (typeof formItem === "object" && formItem !== null) {
75
+ return JSON.stringify(formItem);
76
+ } else {
77
+ return `${formItem}`;
78
+ }
79
+ }
80
+
81
+ protected createFormData(input: Record<string, unknown>): FormData {
82
+ return Object.keys(input || {}).reduce((formData, key) => {
83
+ const property = input[key];
84
+ const propertyContent: any[] = (property instanceof Array) ? property : [property]
85
+
86
+ for (const formItem of propertyContent) {
87
+ const isFileType = formItem instanceof Blob || formItem instanceof File;
88
+ formData.append(
89
+ key,
90
+ isFileType ? formItem : this.stringifyFormItem(formItem)
91
+ );
92
+ }
93
+
94
+ return formData;
95
+ }, new FormData());
96
+ }
97
+
98
+ public request = async <T = any, _E = any>({
99
+ secure,
100
+ path,
101
+ type,
102
+ query,
103
+ format,
104
+ body,
105
+ ...params
106
+ <% if (config.unwrapResponseData) { %>
107
+ }: FullRequestParams): Promise<T> => {
108
+ <% } else { %>
109
+ }: FullRequestParams): Promise<AxiosResponse<T>> => {
110
+ <% } %>
111
+ const secureParams = ((typeof secure === 'boolean' ? secure : this.secure) && this.securityWorker && (await this.securityWorker(this.securityData))) || {};
112
+ const requestParams = this.mergeRequestParams(params, secureParams);
113
+ const responseFormat = (format || this.format) || undefined;
114
+
115
+ if (type === ContentType.FormData && body && body !== null && typeof body === "object") {
116
+ body = this.createFormData(body as Record<string, unknown>);
117
+ }
118
+
119
+ if (type === ContentType.Text && body && body !== null && typeof body !== "string") {
120
+ body = JSON.stringify(body);
121
+ }
122
+
123
+ return this.instance.request({
124
+ ...requestParams,
125
+ headers: {
126
+ ...(requestParams.headers || {}),
127
+ ...(type && type !== ContentType.FormData ? { "Content-Type": type } : {}),
128
+ },
129
+ params: query,
130
+ responseType: responseFormat,
131
+ data: body,
132
+ url: path,
133
+ <% if (config.unwrapResponseData) { %>
134
+ }).then(response => response.data);
135
+ <% } else { %>
136
+ });
137
+ <% } %>
138
+ };
139
+ }