swagger-typescript-api 10.0.3 → 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 (53) hide show
  1. package/README.md +218 -0
  2. package/index.d.ts +93 -0
  3. package/index.js +230 -103
  4. package/package.json +121 -119
  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 +6 -257
  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 +141 -122
  16. package/src/translators/JavaScript.js +49 -49
  17. package/src/type-name.js +79 -0
  18. package/src/util/file-system.js +76 -0
  19. package/src/{utils → util}/id.js +0 -0
  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} +1 -1
  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 +1 -1
  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 +2 -2
  30. package/templates/base/route-type.ejs +2 -2
  31. package/templates/default/route-types.ejs +2 -2
  32. package/templates/modular/api.ejs +2 -2
  33. package/templates/modular/route-types.ejs +2 -2
  34. package/src/apiConfig.js +0 -30
  35. package/src/common.js +0 -28
  36. package/src/components.js +0 -91
  37. package/src/config.js +0 -108
  38. package/src/filePrefix.js +0 -14
  39. package/src/files.js +0 -56
  40. package/src/formatFileContent.js +0 -81
  41. package/src/logger.js +0 -68
  42. package/src/modelNames.js +0 -74
  43. package/src/modelTypes.js +0 -31
  44. package/src/output.js +0 -165
  45. package/src/prettierOptions.js +0 -23
  46. package/src/render/utils/fmtToJSDocLine.js +0 -10
  47. package/src/render/utils/index.js +0 -31
  48. package/src/render/utils/templateRequire.js +0 -17
  49. package/src/routeNames.js +0 -46
  50. package/src/routes.js +0 -809
  51. package/src/schema.js +0 -474
  52. package/src/swagger.js +0 -152
  53. package/src/typeFormatters.js +0 -121
package/src/index.js CHANGED
@@ -7,265 +7,14 @@
7
7
  // Repository https://github.com/acacode/swagger-typescript-api
8
8
 
9
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
10
  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");
11
+ const { CodeGenProcess } = require("./code-gen-process.js");
25
12
 
26
13
  module.exports = {
27
14
  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
- }),
15
+ generateApi: async (config) => {
16
+ const codeGenProcess = new CodeGenProcess(config);
17
+ return await codeGenProcess.start();
18
+ },
19
+ generateTemplates: (config) => {},
271
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
+ };