swagger-typescript-api 10.0.2 → 11.0.0--alpha

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 (55) hide show
  1. package/README.md +263 -41
  2. package/index.d.ts +97 -0
  3. package/index.js +242 -115
  4. package/package.json +121 -116
  5. package/src/code-formatter.js +101 -0
  6. package/src/code-gen-process.js +456 -0
  7. package/src/configuration.js +425 -0
  8. package/src/constants.js +14 -31
  9. package/src/index.js +20 -271
  10. package/src/schema-components-map.js +60 -0
  11. package/src/schema-parser/schema-formatters.js +145 -0
  12. package/src/schema-parser/schema-parser.js +497 -0
  13. package/src/schema-parser/schema-routes.js +902 -0
  14. package/src/swagger-schema-resolver.js +187 -0
  15. package/src/templates.js +174 -155
  16. package/src/translators/JavaScript.js +3 -14
  17. package/src/type-name.js +79 -0
  18. package/src/util/file-system.js +76 -0
  19. package/src/{utils → util}/id.js +9 -9
  20. package/src/util/internal-case.js +5 -0
  21. package/src/util/logger.js +100 -0
  22. package/src/{utils/resolveName.js → util/name-resolver.js} +94 -97
  23. package/src/util/object-assign.js +11 -0
  24. package/src/util/pascal-case.js +5 -0
  25. package/src/{utils → util}/random.js +14 -14
  26. package/templates/base/data-contract-jsdoc.ejs +29 -24
  27. package/templates/base/data-contracts.ejs +3 -3
  28. package/templates/base/interface-data-contract.ejs +1 -0
  29. package/templates/base/route-docs.ejs +3 -4
  30. package/templates/base/route-type.ejs +2 -2
  31. package/templates/default/procedure-call.ejs +2 -2
  32. package/templates/default/route-types.ejs +2 -2
  33. package/templates/modular/api.ejs +2 -2
  34. package/templates/modular/procedure-call.ejs +2 -2
  35. package/templates/modular/route-types.ejs +2 -2
  36. package/src/apiConfig.js +0 -30
  37. package/src/common.js +0 -28
  38. package/src/components.js +0 -91
  39. package/src/config.js +0 -106
  40. package/src/filePrefix.js +0 -14
  41. package/src/files.js +0 -56
  42. package/src/formatFileContent.js +0 -81
  43. package/src/logger.js +0 -59
  44. package/src/modelNames.js +0 -78
  45. package/src/modelTypes.js +0 -31
  46. package/src/output.js +0 -165
  47. package/src/prettierOptions.js +0 -23
  48. package/src/render/utils/fmtToJSDocLine.js +0 -10
  49. package/src/render/utils/index.js +0 -31
  50. package/src/render/utils/templateRequire.js +0 -17
  51. package/src/routeNames.js +0 -46
  52. package/src/routes.js +0 -809
  53. package/src/schema.js +0 -474
  54. package/src/swagger.js +0 -152
  55. package/src/typeFormatters.js +0 -121
package/src/index.js CHANGED
@@ -1,271 +1,20 @@
1
- #!/usr/bin/env node
2
-
3
- // Copyright (c) 2019-present acacode
4
- // Node module: swagger-typescript-api
5
- // This file is licensed under the MIT License.
6
- // License text available at https://opensource.org/licenses/MIT
7
- // Repository https://github.com/acacode/swagger-typescript-api
8
-
9
- const _ = require("lodash");
10
- const { parseSchemas } = require("./schema");
11
- const { parseRoutes, groupRoutes } = require("./routes");
12
- const { createApiConfig } = require("./apiConfig");
13
- const { prepareModelType } = require("./modelTypes");
14
- const { getSwaggerObject, fixSwaggerScheme, convertSwaggerObject } = require("./swagger");
15
- const { createComponentsMap, filterComponentsMap } = require("./components");
16
- const { createFile, pathIsExist, pathIsDir, createDir, cleanDir } = require("./files");
17
- const { addToConfig, config } = require("./config");
18
- const { getTemplates, getTemplatePaths, renderTemplate, getTemplate } = require("./templates");
19
- const constants = require("./constants");
20
- const { generateOutputFiles } = require("./output");
21
- const formatFileContent = require("./formatFileContent");
22
- const { logger } = require("./logger");
23
- const { ComponentTypeNameResolver } = require("./utils/resolveName");
24
- const { getPrettierOptions } = require("./prettierOptions");
25
-
26
- module.exports = {
27
- constants: constants,
28
- generateApi: ({
29
- input,
30
- output,
31
- url,
32
- spec,
33
- name: fileName,
34
- toJS: translateToJavaScript = config.toJS,
35
- modular,
36
- templates,
37
- generateResponses = config.generateResponses,
38
- defaultResponseAsSuccess = config.defaultResponseAsSuccess,
39
- generateRouteTypes = config.generateRouteTypes,
40
- generateClient = config.generateClient,
41
- httpClientType = config.httpClientType,
42
- generateUnionEnums = config.generateUnionEnums,
43
- addReadonly = config.addReadonly,
44
- moduleNameIndex = config.moduleNameIndex,
45
- moduleNameFirstTag = config.moduleNameFirstTag,
46
- extractRequestParams = config.extractRequestParams,
47
- extractRequestBody = config.extractRequestBody,
48
- extractResponseBody = config.extractResponseBody,
49
- extractResponseError = config.extractResponseError,
50
- defaultResponseType = config.defaultResponseType,
51
- unwrapResponseData = config.unwrapResponseData,
52
- disableThrowOnError = config.disableThrowOnError,
53
- sortTypes = config.sortTypes,
54
- singleHttpClient = config.singleHttpClient,
55
- prettier: prettierOptions = getPrettierOptions(),
56
- hooks: rawHooks,
57
- extraTemplates,
58
- enumNamesAsValues,
59
- disableStrictSSL = config.disableStrictSSL,
60
- disableProxy = config.disableProxy,
61
- cleanOutput,
62
- silent = config.silent,
63
- typePrefix = config.typePrefix,
64
- typeSuffix = config.typeSuffix,
65
- patch = config.patch,
66
- authorizationToken,
67
- apiClassName = config.apiClassName,
68
- debug = config.debug,
69
- }) =>
70
- new Promise((resolve, reject) => {
71
- addToConfig({
72
- defaultResponseAsSuccess,
73
- generateRouteTypes,
74
- generateClient,
75
- httpClientType,
76
- generateResponses,
77
- templates,
78
- generateUnionEnums,
79
- addReadonly,
80
- moduleNameIndex,
81
- moduleNameFirstTag,
82
- prettierOptions,
83
- modular,
84
- extractRequestParams,
85
- extractRequestBody,
86
- extractResponseBody,
87
- extractResponseError,
88
- hooks: _.merge(config.hooks, rawHooks || {}),
89
- enumNamesAsValues,
90
- disableStrictSSL,
91
- disableProxy,
92
- cleanOutput,
93
- defaultResponseType,
94
- unwrapResponseData,
95
- disableThrowOnError,
96
- sortTypes,
97
- singleHttpClient,
98
- constants,
99
- silent,
100
- toJS: translateToJavaScript,
101
- typePrefix,
102
- typeSuffix,
103
- patch,
104
- apiClassName,
105
- debug,
106
- });
107
- (spec
108
- ? convertSwaggerObject(spec, { patch })
109
- : getSwaggerObject(input, url, disableStrictSSL, disableProxy, authorizationToken, { patch })
110
- )
111
- .then(({ usageSchema, originalSchema }) => {
112
- const templatePaths = getTemplatePaths(config);
113
-
114
- addToConfig({ templatePaths });
115
-
116
- const templatesToRender = getTemplates(config);
117
-
118
- logger.event("start generating your typescript api");
119
-
120
- fixSwaggerScheme(usageSchema, originalSchema);
121
-
122
- addToConfig({
123
- swaggerSchema: usageSchema,
124
- originalSchema,
125
- templatesToRender,
126
- });
127
-
128
- const { components } = usageSchema;
129
-
130
- addToConfig(config.hooks.onInit(config) || config);
131
-
132
- const componentsMap = createComponentsMap(components);
133
-
134
- const componentSchemasNames = filterComponentsMap(componentsMap, "schemas").map((c) => c.typeName);
135
-
136
- addToConfig({
137
- componentTypeNameResolver: new ComponentTypeNameResolver(componentSchemasNames),
138
- });
139
-
140
- const parsedSchemas = parseSchemas(components);
141
-
142
- config.routeNameDuplicatesMap.clear();
143
-
144
- const routes = parseRoutes({
145
- usageSchema,
146
- parsedSchemas,
147
- moduleNameIndex,
148
- moduleNameFirstTag,
149
- extractRequestParams,
150
- });
151
-
152
- const hasSecurityRoutes = routes.some((route) => route.security);
153
- const hasQueryRoutes = routes.some((route) => route.hasQuery);
154
- const hasFormDataRoutes = routes.some((route) => route.hasFormDataParams);
155
-
156
- const usageComponentSchemas = filterComponentsMap(componentsMap, "schemas");
157
- const sortByProperty = (propertyName) => (o1, o2) => {
158
- if (o1[propertyName] > o2[propertyName]) {
159
- return 1;
160
- }
161
- if (o1[propertyName] < o2[propertyName]) {
162
- return -1;
163
- }
164
- return 0;
165
- };
166
-
167
- const sortSchemas = (schemas) => {
168
- if (config.sortTypes) {
169
- return schemas.sort(sortByProperty("typeName")).map((schema) => {
170
- if (schema.rawTypeData?.properties) {
171
- return {
172
- ...schema,
173
- rawTypeData: {
174
- ...schema.rawTypeData,
175
- $parsed: schema.rawTypeData["$parsed"] && {
176
- ...schema.rawTypeData["$parsed"],
177
- content: Array.isArray(schema.rawTypeData["$parsed"].content)
178
- ? schema.rawTypeData["$parsed"].content.sort(sortByProperty("name"))
179
- : schema.rawTypeData["$parsed"].content,
180
- },
181
- },
182
- };
183
- }
184
- return schema;
185
- });
186
- }
187
- return schemas;
188
- };
189
-
190
- const rawConfiguration = {
191
- apiConfig: createApiConfig(usageSchema),
192
- config,
193
- modelTypes: _.map(sortSchemas(usageComponentSchemas), prepareModelType),
194
- rawModelTypes: usageComponentSchemas,
195
- hasFormDataRoutes,
196
- hasSecurityRoutes,
197
- hasQueryRoutes,
198
- generateResponses,
199
- routes: groupRoutes(routes),
200
- extraTemplates,
201
- fileName,
202
- translateToJavaScript,
203
- utils: {
204
- ...require("./render/utils"),
205
- ...require("./common"),
206
- },
207
- };
208
-
209
- const configuration = config.hooks.onPrepareConfig(rawConfiguration) || rawConfiguration;
210
-
211
- if (pathIsExist(output)) {
212
- if (cleanOutput) {
213
- cleanDir(output);
214
- }
215
- } else {
216
- createDir(output);
217
- }
218
-
219
- const files = generateOutputFiles({
220
- modular,
221
- templatesToRender,
222
- configuration,
223
- });
224
-
225
- const isDirPath = pathIsDir(output);
226
-
227
- const generatedFiles = files.map((file) => {
228
- if (!isDirPath) return file;
229
-
230
- if (translateToJavaScript) {
231
- createFile({
232
- path: output,
233
- fileName: file.name,
234
- content: file.content,
235
- withPrefix: true,
236
- });
237
- createFile({
238
- path: output,
239
- fileName: file.declaration.name,
240
- content: file.declaration.content,
241
- withPrefix: true,
242
- });
243
- logger.success(`javascript api file`, file.name, `created in ${output}`);
244
- } else {
245
- createFile({
246
- path: output,
247
- fileName: file.name,
248
- content: file.content,
249
- withPrefix: true,
250
- });
251
- logger.success(`typescript api file`, file.name, `created in ${output}`);
252
- }
253
-
254
- return file;
255
- });
256
-
257
- resolve({
258
- files: generatedFiles,
259
- configuration,
260
- getTemplate,
261
- renderTemplate,
262
- createFile,
263
- formatTSContent: formatFileContent,
264
- });
265
- })
266
- .catch((e) => {
267
- reject(e);
268
- throw new Error("Swagger schema parse error!\r\n " + e);
269
- });
270
- }),
271
- };
1
+ #!/usr/bin/env node
2
+
3
+ // Copyright (c) 2019-present acacode
4
+ // Node module: swagger-typescript-api
5
+ // This file is licensed under the MIT License.
6
+ // License text available at https://opensource.org/licenses/MIT
7
+ // Repository https://github.com/acacode/swagger-typescript-api
8
+
9
+ const _ = require("lodash");
10
+ const constants = require("./constants");
11
+ const { CodeGenProcess } = require("./code-gen-process.js");
12
+
13
+ module.exports = {
14
+ constants: constants,
15
+ generateApi: async (config) => {
16
+ const codeGenProcess = new CodeGenProcess(config);
17
+ return await codeGenProcess.start();
18
+ },
19
+ generateTemplates: (config) => {},
20
+ };
@@ -0,0 +1,60 @@
1
+ const _ = require("lodash");
2
+
3
+ class SchemaComponentsMap {
4
+ /**
5
+ * @type {Record<string, SchemaComponent>}
6
+ */
7
+ data = {};
8
+ /**
9
+ * @type {Configuration}
10
+ */
11
+ config;
12
+
13
+ constructor(config, schema) {
14
+ this.config = config;
15
+ this.processSchema(schema);
16
+ }
17
+
18
+ processSchema(schema) {
19
+ this.data = {};
20
+ if (!schema) return;
21
+ _.each(schema.components, (component, componentName) =>
22
+ _.each(component, (rawTypeData, typeName) => this.createComponent(componentName, typeName, rawTypeData)),
23
+ );
24
+ }
25
+
26
+ createComponent(componentName, typeName, rawTypeData) {
27
+ const $ref = `#/components/${componentName}/${typeName}`;
28
+
29
+ const componentSchema = {
30
+ $ref,
31
+ typeName,
32
+ rawTypeData,
33
+ componentName,
34
+ /** result from schema parser */
35
+ typeData: null,
36
+ };
37
+
38
+ const usageComponent = this.config.hooks.onCreateComponent(componentSchema) || componentSchema;
39
+
40
+ this.data[$ref] = usageComponent;
41
+
42
+ return usageComponent;
43
+ }
44
+
45
+ /**
46
+ * @param componentName {string}
47
+ * @returns {SchemaComponent[]}
48
+ */
49
+ filter(componentName) {
50
+ return _.filter(this.data, (v, ref) => _.startsWith(ref, `#/components/${componentName}`));
51
+ }
52
+
53
+ get(ref) {
54
+ return this.data[ref] || null;
55
+ }
56
+ }
57
+
58
+ module.exports = {
59
+ SchemaComponentsMap,
60
+ };
@@ -0,0 +1,145 @@
1
+ const { SCHEMA_TYPES } = require("../constants");
2
+ const _ = require("lodash");
3
+
4
+ class SchemaFormatters {
5
+ /**
6
+ * @type {Configuration}
7
+ */
8
+ config;
9
+ /**
10
+ * @type {Logger}
11
+ */
12
+ logger;
13
+ /**
14
+ * @type {SchemaParser}
15
+ */
16
+ schemaParser;
17
+ /**
18
+ * @type {Templates}
19
+ */
20
+ templates;
21
+
22
+ constructor(config, logger, schemaParser, templates) {
23
+ this.config = config;
24
+ this.logger = logger;
25
+ this.schemaParser = schemaParser;
26
+ this.templates = templates;
27
+ }
28
+
29
+ base = {
30
+ [SCHEMA_TYPES.ENUM]: (parsedSchema) => {
31
+ const isNumberEnum = _.some(parsedSchema.content, (content) => typeof content.key === "number");
32
+ const formatAsUnionType = !!(isNumberEnum || this.config.generateUnionEnums);
33
+
34
+ if (formatAsUnionType) {
35
+ return {
36
+ ...parsedSchema,
37
+ $content: parsedSchema.content,
38
+ content: this.config.Ts.UnionType(_.map(parsedSchema.content, ({ value }) => value)),
39
+ };
40
+ }
41
+
42
+ return {
43
+ ...parsedSchema,
44
+ $content: parsedSchema.content,
45
+ content: this.config.Ts.EnumFieldsWrapper(parsedSchema.content),
46
+ };
47
+ },
48
+ [SCHEMA_TYPES.OBJECT]: (parsedSchema) => {
49
+ if (parsedSchema.nullable) return this.inline[SCHEMA_TYPES.OBJECT](parsedSchema);
50
+ return {
51
+ ...parsedSchema,
52
+ $content: parsedSchema.content,
53
+ content: this.formatObjectContent(parsedSchema.content),
54
+ };
55
+ },
56
+ [SCHEMA_TYPES.PRIMITIVE]: (parsedSchema) => {
57
+ return {
58
+ ...parsedSchema,
59
+ $content: parsedSchema.content,
60
+ };
61
+ },
62
+ };
63
+ inline = {
64
+ [SCHEMA_TYPES.OBJECT]: (parsedSchema) => {
65
+ if (_.isString(parsedSchema.content)) {
66
+ return {
67
+ ...parsedSchema,
68
+ typeIdentifier: this.config.Ts.Keyword.Type,
69
+ content: this.schemaParser.checkAndAddNull(parsedSchema.content),
70
+ };
71
+ }
72
+
73
+ return {
74
+ ...parsedSchema,
75
+ typeIdentifier: this.config.Ts.Keyword.Type,
76
+ content: this.schemaParser.checkAndAddNull(
77
+ parsedSchema,
78
+ parsedSchema.content.length
79
+ ? this.config.Ts.ObjectWrapper(this.formatObjectContent(parsedSchema.content))
80
+ : this.config.Ts.RecordType(Ts.Keyword.String, this.config.Ts.Keyword.Any),
81
+ ),
82
+ };
83
+ },
84
+ [SCHEMA_TYPES.ENUM]: (parsedSchema) => {
85
+ return {
86
+ ...parsedSchema,
87
+ content: parsedSchema.$ref
88
+ ? parsedSchema.typeName
89
+ : this.config.Ts.UnionType(
90
+ _.compact([
91
+ ..._.map(parsedSchema.content, ({ value }) => `${value}`),
92
+ parsedSchema.nullable && this.config.Ts.Keyword.Null,
93
+ ]),
94
+ ),
95
+ };
96
+ },
97
+ };
98
+
99
+ formatDescription = (description, inline) => {
100
+ if (!description) return "";
101
+
102
+ let prettified = description;
103
+
104
+ prettified = _.replace(prettified, /\*\//g, "*/");
105
+
106
+ const hasMultipleLines = _.includes(prettified, "\n");
107
+
108
+ if (!hasMultipleLines) return prettified;
109
+
110
+ if (inline) {
111
+ return _(prettified)
112
+ .split(/\n/g)
113
+ .map((part) => _.trim(part))
114
+ .compact()
115
+ .join(" ")
116
+ .valueOf();
117
+ }
118
+
119
+ return _.replace(prettified, /\n$/g, "");
120
+ };
121
+
122
+ formatObjectContent = (content) => {
123
+ return _.map(content, (part) => {
124
+ const extraSpace = " ";
125
+ const result = `${extraSpace}${part.field},\n`;
126
+
127
+ const renderedJsDoc = this.templates.renderTemplate(this.config.templatesToRender.dataContractJsDoc, {
128
+ data: part,
129
+ });
130
+
131
+ const routeNameFromTemplate = renderedJsDoc
132
+ .split("\n")
133
+ .map((c) => `${extraSpace}${c}`)
134
+ .join("\n");
135
+
136
+ if (routeNameFromTemplate) return `${routeNameFromTemplate}${result}`;
137
+
138
+ return `${result}`;
139
+ }).join("");
140
+ };
141
+ }
142
+
143
+ module.exports = {
144
+ SchemaFormatters,
145
+ };