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
@@ -0,0 +1,26 @@
1
+ const { NameResolver } = require('../../util/name-resolver');
2
+
3
+ class SpecificArgNameResolver extends NameResolver {
4
+ counter = 1;
5
+ /**
6
+ * @param {CodeGenConfig} config;
7
+ * @param {Logger} logger;
8
+ * @param {string[]} reservedNames
9
+ */
10
+ constructor(config, logger, reservedNames) {
11
+ super(config, logger, reservedNames, (variants) => {
12
+ const generatedVariant =
13
+ (variants[0] && `${variants[0]}${this.counter++}`) ||
14
+ `${this.config.specificArgNameResolverName}${this.counter++}`;
15
+ this.logger.debug(
16
+ 'generated fallback type name for specific arg - ',
17
+ generatedVariant,
18
+ );
19
+ return generatedVariant;
20
+ });
21
+ }
22
+ }
23
+
24
+ module.exports = {
25
+ SpecificArgNameResolver,
26
+ };
@@ -0,0 +1,93 @@
1
+ const _ = require('lodash');
2
+
3
+ // TODO: WIP
4
+ // this class will be needed to walk by schema everywhere
5
+ class SchemaWalker {
6
+ /** @type {Logger} */
7
+ logger;
8
+ /** @type {CodeGenConfig} */
9
+ config;
10
+ /** @type {SwaggerSchemaResolver} */
11
+ swaggerSchemaResolver;
12
+ /** @type {Map<string, Record<string, any>>} */
13
+ schemas = new Map();
14
+ /** @type {Map<string, Record<string, any>>} */
15
+ caches = new Map();
16
+
17
+ constructor({ config, logger }) {
18
+ this.logger = logger;
19
+ this.config = config;
20
+ }
21
+
22
+ /**
23
+ * @param name {string}
24
+ * @param schema {Record<string, any>}
25
+ */
26
+ addSchema = (name, schema) => {
27
+ this.schemas.set(name, _.cloneDeep(schema));
28
+ };
29
+
30
+ /**
31
+ * @param ref {string}
32
+ * @returns {any}
33
+ */
34
+ findByRef = (ref) => {
35
+ this.logger.debug('try to resolve ref by path', ref);
36
+
37
+ if (this.caches.has(ref)) {
38
+ return this.caches.get(ref);
39
+ }
40
+
41
+ const schemas = Array.from(this.schemas.values());
42
+ if (this._isLocalRef(ref)) {
43
+ for (const schema of schemas) {
44
+ const refData = this._getRefDataFromSchema(schema, ref);
45
+ if (refData) {
46
+ return refData;
47
+ }
48
+ }
49
+ } else if (this._isRemoteRef(ref)) {
50
+ this.logger.debug('remote refs not supported', ref);
51
+ return null;
52
+ } else {
53
+ const [address, path] = path.split('#');
54
+ let swaggerSchemaObject;
55
+
56
+ if (this.schemas.has(address)) {
57
+ swaggerSchemaObject = this.schemas.get(address);
58
+ } else {
59
+ const pathToSchema = path.resolve(process.cwd(), address);
60
+ const swaggerSchemaFile =
61
+ this.swaggerSchemaResolver.getSwaggerSchemaByPath(pathToSchema);
62
+ swaggerSchemaObject =
63
+ this.swaggerSchemaResolver.processSwaggerSchemaFile(
64
+ swaggerSchemaFile,
65
+ );
66
+ this.schemas.set(address, swaggerSchemaObject);
67
+ }
68
+
69
+ return this._getRefDataFromSchema(swaggerSchemaObject, path);
70
+ }
71
+ };
72
+
73
+ _isLocalRef = (ref) => {
74
+ return ref.startsWith('#');
75
+ };
76
+
77
+ _isRemoteRef = (ref) => {
78
+ return ref.startsWith('http://') || ref.startsWith('https://');
79
+ };
80
+
81
+ _getRefDataFromSchema = (schema, ref) => {
82
+ const path = ref.replace('#', '').split('/');
83
+ const refData = _.get(schema, path);
84
+ if (refData) {
85
+ this.caches.set(ref, refData);
86
+ }
87
+ return refData;
88
+ };
89
+ }
90
+
91
+ module.exports = {
92
+ SchemaWalker,
93
+ };
@@ -1,7 +1,7 @@
1
- const _ = require("lodash");
2
- const converter = require("swagger2openapi");
3
- const yaml = require("js-yaml");
4
- const { Request } = require("./util/request");
1
+ const _ = require('lodash');
2
+ const converter = require('swagger2openapi');
3
+ const yaml = require('js-yaml');
4
+ const { Request } = require('./util/request');
5
5
 
6
6
  class SwaggerSchemaResolver {
7
7
  /**
@@ -21,7 +21,7 @@ class SwaggerSchemaResolver {
21
21
  */
22
22
  request;
23
23
 
24
- constructor(config, logger, fileSystem) {
24
+ constructor({ config, logger, fileSystem }) {
25
25
  this.config = config;
26
26
  this.logger = logger;
27
27
  this.fileSystem = fileSystem;
@@ -33,7 +33,15 @@ class SwaggerSchemaResolver {
33
33
  * @returns {Promise<{usageSchema: Record<string, *>, originalSchema: Record<string, *>}>}
34
34
  */
35
35
  async create() {
36
- const { spec, patch, input, url, disableStrictSSL, disableProxy, authorizationToken } = this.config;
36
+ const {
37
+ spec,
38
+ patch,
39
+ input,
40
+ url,
41
+ disableStrictSSL,
42
+ disableProxy,
43
+ authorizationToken,
44
+ } = this.config;
37
45
 
38
46
  if (this.config.spec) {
39
47
  return await this.convertSwaggerObject(spec, { patch });
@@ -46,7 +54,8 @@ class SwaggerSchemaResolver {
46
54
  disableProxy,
47
55
  authorizationToken,
48
56
  );
49
- const swaggerSchemaObject = this.processSwaggerSchemaFile(swaggerSchemaFile);
57
+ const swaggerSchemaObject =
58
+ this.processSwaggerSchemaFile(swaggerSchemaFile);
50
59
  return await this.convertSwaggerObject(swaggerSchemaObject, { patch });
51
60
  }
52
61
 
@@ -61,8 +70,8 @@ class SwaggerSchemaResolver {
61
70
  const result = _.cloneDeep(swaggerSchema);
62
71
  result.info = _.merge(
63
72
  {
64
- title: "No title",
65
- version: "",
73
+ title: 'No title',
74
+ version: '',
66
75
  },
67
76
  result.info,
68
77
  );
@@ -75,11 +84,15 @@ class SwaggerSchemaResolver {
75
84
  {
76
85
  ...converterOptions,
77
86
  warnOnly: true,
78
- refSiblings: "preserve",
79
- rbname: "requestBodyName",
87
+ refSiblings: 'preserve',
88
+ rbname: 'requestBodyName',
80
89
  },
81
90
  (err, options) => {
82
- const parsedSwaggerSchema = _.get(err, "options.openapi", _.get(options, "openapi"));
91
+ const parsedSwaggerSchema = _.get(
92
+ err,
93
+ 'options.openapi',
94
+ _.get(options, 'openapi'),
95
+ );
83
96
  if (!parsedSwaggerSchema && err) {
84
97
  throw new Error(err);
85
98
  }
@@ -99,10 +112,20 @@ class SwaggerSchemaResolver {
99
112
  });
100
113
  }
101
114
 
102
- async fetchSwaggerSchemaFile(pathToSwagger, urlToSwagger, disableStrictSSL, disableProxy, authToken) {
115
+ getSwaggerSchemaByPath = (pathToSwagger) => {
116
+ this.logger.log(`try to get swagger by path "${pathToSwagger}"`);
117
+ return this.fileSystem.getFileContent(pathToSwagger);
118
+ };
119
+
120
+ async fetchSwaggerSchemaFile(
121
+ pathToSwagger,
122
+ urlToSwagger,
123
+ disableStrictSSL,
124
+ disableProxy,
125
+ authToken,
126
+ ) {
103
127
  if (this.fileSystem.pathIsExist(pathToSwagger)) {
104
- this.logger.log(`try to get swagger by path "${pathToSwagger}"`);
105
- return this.fileSystem.getFileContent(pathToSwagger);
128
+ return this.getSwaggerSchemaByPath(pathToSwagger);
106
129
  } else {
107
130
  this.logger.log(`try to get swagger by URL "${urlToSwagger}"`);
108
131
  return await this.request.download({
@@ -115,7 +138,7 @@ class SwaggerSchemaResolver {
115
138
  }
116
139
 
117
140
  processSwaggerSchemaFile(file) {
118
- if (typeof file !== "string") return file;
141
+ if (typeof file !== 'string') return file;
119
142
 
120
143
  try {
121
144
  return JSON.parse(file);
@@ -125,8 +148,8 @@ class SwaggerSchemaResolver {
125
148
  }
126
149
 
127
150
  fixSwaggerSchema({ usageSchema, originalSchema }) {
128
- const usagePaths = _.get(usageSchema, "paths");
129
- const originalPaths = _.get(originalSchema, "paths");
151
+ const usagePaths = _.get(usageSchema, 'paths');
152
+ const originalPaths = _.get(originalSchema, 'paths');
130
153
 
131
154
  // walk by routes
132
155
  _.each(usagePaths, (usagePathObject, route) => {
@@ -135,20 +158,30 @@ class SwaggerSchemaResolver {
135
158
  // walk by methods
136
159
  _.each(usagePathObject, (usageRouteInfo, methodName) => {
137
160
  const originalRouteInfo = _.get(originalPathObject, methodName);
138
- const usageRouteParams = _.get(usageRouteInfo, "parameters", []);
139
- const originalRouteParams = _.get(originalRouteInfo, "parameters", []);
140
-
141
- usageRouteInfo.consumes = _.uniq(
142
- _.compact([...(usageRouteInfo.consumes || []), ...(originalRouteInfo.consumes || [])]),
143
- );
144
- usageRouteInfo.produces = _.uniq(
145
- _.compact([...(usageRouteInfo.produces || []), ...(originalRouteInfo.produces || [])]),
146
- );
161
+ const usageRouteParams = _.get(usageRouteInfo, 'parameters', []);
162
+ const originalRouteParams = _.get(originalRouteInfo, 'parameters', []);
163
+
164
+ if (typeof usageRouteInfo === 'object') {
165
+ usageRouteInfo.consumes = _.uniq(
166
+ _.compact([
167
+ ...(usageRouteInfo.consumes || []),
168
+ ...(originalRouteInfo.consumes || []),
169
+ ]),
170
+ );
171
+ usageRouteInfo.produces = _.uniq(
172
+ _.compact([
173
+ ...(usageRouteInfo.produces || []),
174
+ ...(originalRouteInfo.produces || []),
175
+ ]),
176
+ );
177
+ }
147
178
 
148
179
  _.each(originalRouteParams, (originalRouteParam) => {
149
180
  const existUsageParam = _.find(
150
181
  usageRouteParams,
151
- (param) => originalRouteParam.in === param.in && originalRouteParam.name === param.name,
182
+ (param) =>
183
+ originalRouteParam.in === param.in &&
184
+ originalRouteParam.name === param.name,
152
185
  );
153
186
  if (!existUsageParam) {
154
187
  usageRouteParams.push(originalRouteParam);
@@ -0,0 +1,240 @@
1
+ const { resolve } = require('path');
2
+ const _ = require('lodash');
3
+ const Eta = require('eta');
4
+ const path = require('path');
5
+
6
+ class TemplatesWorker {
7
+ /**
8
+ * @type {CodeGenConfig}
9
+ */
10
+ config;
11
+
12
+ /**
13
+ * @type {Logger}
14
+ */
15
+ logger;
16
+
17
+ /**
18
+ * @type {FileSystem}
19
+ */
20
+ fileSystem;
21
+
22
+ getRenderTemplateData;
23
+
24
+ constructor({ config, logger, fileSystem, getRenderTemplateData }) {
25
+ this.config = config;
26
+ this.logger = logger;
27
+ this.fileSystem = fileSystem;
28
+ this.getRenderTemplateData = getRenderTemplateData;
29
+ }
30
+
31
+ /**
32
+ *
33
+ * @param config {CodeGenConfig}
34
+ * @returns {CodeGenConfig.templatePaths}
35
+ */
36
+ getTemplatePaths = (config) => {
37
+ const baseTemplatesPath = resolve(__dirname, '../templates/base');
38
+ const defaultTemplatesPath = resolve(__dirname, '../templates/default');
39
+ const modularTemplatesPath = resolve(__dirname, '../templates/modular');
40
+ const originalTemplatesPath = config.modular
41
+ ? modularTemplatesPath
42
+ : defaultTemplatesPath;
43
+ const customTemplatesPath =
44
+ (config.templates && resolve(process.cwd(), config.templates)) || null;
45
+
46
+ return {
47
+ /** `templates/base` */
48
+ base: baseTemplatesPath,
49
+ /** `templates/default` */
50
+ default: defaultTemplatesPath,
51
+ /** `templates/modular` */
52
+ modular: modularTemplatesPath,
53
+ /** usage path if `--templates` option is not set */
54
+ original: originalTemplatesPath,
55
+ /** custom path to templates (`--templates`) */
56
+ custom: customTemplatesPath,
57
+ };
58
+ };
59
+
60
+ cropExtension = (path) =>
61
+ this.config.templateExtensions.reduce(
62
+ (path, ext) => (_.endsWith(path, ext) ? path.replace(ext, '') : path),
63
+ path,
64
+ );
65
+
66
+ getTemplateFullPath = (path, fileName) => {
67
+ const raw = resolve(path, './', this.cropExtension(fileName));
68
+ const pathVariants = this.config.templateExtensions.map(
69
+ (extension) => `${raw}${extension}`,
70
+ );
71
+
72
+ return pathVariants.find(
73
+ (variant) => !!this.fileSystem.pathIsExist(variant),
74
+ );
75
+ };
76
+
77
+ requireFnFromTemplate = (packageOrPath) => {
78
+ const isPath =
79
+ _.startsWith(packageOrPath, './') || _.startsWith(packageOrPath, '../');
80
+
81
+ if (isPath) {
82
+ return require(path.resolve(
83
+ this.config.templatePaths.custom || this.config.templatePaths.original,
84
+ packageOrPath,
85
+ ));
86
+ }
87
+
88
+ return require(packageOrPath);
89
+ };
90
+
91
+ getTemplate = ({ fileName, name, path }) => {
92
+ const { templatePaths } = this.config;
93
+
94
+ if (path) {
95
+ return this.fileSystem.getFileContent(path);
96
+ }
97
+
98
+ if (!fileName) return '';
99
+
100
+ const customFullPath =
101
+ templatePaths.custom &&
102
+ this.getTemplateFullPath(templatePaths.custom, fileName);
103
+ let fileContent =
104
+ customFullPath && this.fileSystem.getFileContent(customFullPath);
105
+
106
+ if (fileContent) {
107
+ this.logger.log(
108
+ `"${_.lowerCase(name)}" template found in "${templatePaths.custom}"`,
109
+ );
110
+ return fileContent;
111
+ }
112
+
113
+ const baseFullPath = this.getTemplateFullPath(templatePaths.base, fileName);
114
+
115
+ if (baseFullPath) {
116
+ fileContent = this.fileSystem.getFileContent(baseFullPath);
117
+ } else {
118
+ if (templatePaths.custom) {
119
+ this.logger.warn(
120
+ `"${_.lowerCase(name)}" template not found in "${
121
+ templatePaths.custom
122
+ }"`,
123
+ `\nCode generator will use the default template`,
124
+ );
125
+ } else {
126
+ this.logger.log(
127
+ `Code generator will use the default template for "${_.lowerCase(
128
+ name,
129
+ )}"`,
130
+ );
131
+ }
132
+ }
133
+
134
+ const originalFullPath = this.getTemplateFullPath(
135
+ templatePaths.original,
136
+ fileName,
137
+ );
138
+
139
+ if (originalFullPath) {
140
+ fileContent = this.fileSystem.getFileContent(originalFullPath);
141
+ }
142
+
143
+ return fileContent;
144
+ };
145
+
146
+ getTemplates = ({ templatePaths }) => {
147
+ if (templatePaths.custom) {
148
+ this.logger.log(
149
+ `try to read templates from directory "${templatePaths.custom}"`,
150
+ );
151
+ }
152
+
153
+ return _.reduce(
154
+ this.config.templateInfos,
155
+ (acc, { fileName, name }) => ({
156
+ ...acc,
157
+ [name]: this.getTemplate({ fileName, name }),
158
+ }),
159
+ {},
160
+ );
161
+ };
162
+
163
+ findTemplateWithExt = (path) => {
164
+ const raw = this.cropExtension(path);
165
+ const pathVariants = this.config.templateExtensions.map(
166
+ (extension) => `${raw}${extension}`,
167
+ );
168
+ return pathVariants.find((variant) => this.fileSystem.pathIsExist(variant));
169
+ };
170
+
171
+ getTemplateContent = (path) => {
172
+ const foundTemplatePathKey = _.keys(this.config.templatePaths).find((key) =>
173
+ _.startsWith(path, `@${key}`),
174
+ );
175
+
176
+ const rawPath = resolve(
177
+ _.replace(
178
+ path,
179
+ `@${foundTemplatePathKey}`,
180
+ this.config.templatePaths[foundTemplatePathKey],
181
+ ),
182
+ );
183
+ const fixedPath = this.findTemplateWithExt(rawPath);
184
+
185
+ if (fixedPath) {
186
+ return this.fileSystem.getFileContent(fixedPath);
187
+ }
188
+
189
+ const customPath =
190
+ this.config.templatePaths.custom &&
191
+ this.findTemplateWithExt(resolve(this.config.templatePaths.custom, path));
192
+
193
+ if (customPath) {
194
+ return this.fileSystem.getFileContent(customPath);
195
+ }
196
+
197
+ const originalPath = this.findTemplateWithExt(
198
+ resolve(this.config.templatePaths.original, path),
199
+ );
200
+
201
+ if (originalPath) {
202
+ return this.fileSystem.getFileContent(originalPath);
203
+ }
204
+
205
+ return '';
206
+ };
207
+
208
+ /**
209
+ * @param template
210
+ * @param configuration
211
+ * @param options
212
+ * @returns {Promise<string|string|void>}
213
+ */
214
+ renderTemplate = (template, configuration, options) => {
215
+ if (!template) return '';
216
+
217
+ return Eta.render(
218
+ template,
219
+ {
220
+ ...this.getRenderTemplateData(),
221
+ ...configuration,
222
+ },
223
+ {
224
+ async: false,
225
+ ...(options || {}),
226
+ includeFile: (path, configuration, options) => {
227
+ return this.renderTemplate(
228
+ this.getTemplateContent(path),
229
+ configuration,
230
+ options,
231
+ );
232
+ },
233
+ },
234
+ );
235
+ };
236
+ }
237
+
238
+ module.exports = {
239
+ TemplatesWorker,
240
+ };
@@ -0,0 +1,83 @@
1
+ const ts = require('typescript');
2
+ const { Translator } = require('./translator');
3
+
4
+ class JavascriptTranslator extends Translator {
5
+ /**
6
+ * @param {TranslatorIO} input
7
+ * @returns {Record<string, string>}
8
+ */
9
+ compileTSCode = (input) => {
10
+ const fileNameFull = `${input.fileName}${input.fileExtension}`;
11
+ const output = {};
12
+ const host = ts.createCompilerHost(this.config.compilerTsConfig, true);
13
+ const fileNames = [fileNameFull];
14
+ const originalSourceFileGet = host.getSourceFile.bind(host);
15
+ host.getSourceFile = (
16
+ sourceFileName,
17
+ languageVersion,
18
+ onError,
19
+ shouldCreateNewSourceFile,
20
+ ) => {
21
+ if (sourceFileName !== fileNameFull)
22
+ return originalSourceFileGet(
23
+ sourceFileName,
24
+ languageVersion,
25
+ onError,
26
+ shouldCreateNewSourceFile,
27
+ );
28
+
29
+ return ts.createSourceFile(
30
+ sourceFileName,
31
+ input.fileContent,
32
+ languageVersion,
33
+ true,
34
+ ts.ScriptKind.TS,
35
+ );
36
+ };
37
+
38
+ host.writeFile = (fileName, contents) => {
39
+ output[fileName] = contents;
40
+ };
41
+
42
+ ts.createProgram(fileNames, this.config.compilerTsConfig, host).emit();
43
+
44
+ return output;
45
+ };
46
+
47
+ translate = async (input) => {
48
+ const compiled = this.compileTSCode(input);
49
+
50
+ const jsFileName = `${input.fileName}${ts.Extension.Js}`;
51
+ const dtsFileName = `${input.fileName}${ts.Extension.Dts}`;
52
+ const sourceContent = compiled[jsFileName];
53
+ const tsImportRows = input.fileContent
54
+ .split('\n')
55
+ .filter((line) => line.startsWith('import '));
56
+ const declarationContent = compiled[dtsFileName]
57
+ .split('\n')
58
+ .map((line) => {
59
+ if (line.startsWith('import ')) {
60
+ return tsImportRows.shift();
61
+ }
62
+ return line;
63
+ })
64
+ .join('\n');
65
+
66
+ return [
67
+ {
68
+ fileName: input.fileName,
69
+ fileExtension: ts.Extension.Js,
70
+ fileContent: await this.codeFormatter.formatCode(sourceContent),
71
+ },
72
+ {
73
+ fileName: input.fileName,
74
+ fileExtension: ts.Extension.Dts,
75
+ fileContent: await this.codeFormatter.formatCode(declarationContent),
76
+ },
77
+ ];
78
+ };
79
+ }
80
+
81
+ module.exports = {
82
+ JavascriptTranslator,
83
+ };
@@ -0,0 +1,35 @@
1
+ /**
2
+ * @typedef {{ fileName: string, fileExtension: string, fileContent: string }} TranslatorIO
3
+ */
4
+
5
+ class Translator {
6
+ /** @type {Logger} */
7
+ logger;
8
+ /** @type {CodeGenConfig} */
9
+ config;
10
+ /** @type {CodeFormatter} */
11
+ codeFormatter;
12
+
13
+ /**
14
+ * @param codeGenProcess
15
+ */
16
+ constructor(codeGenProcess) {
17
+ this.logger = codeGenProcess.logger;
18
+ this.config = codeGenProcess.config;
19
+ this.codeFormatter = codeGenProcess.codeFormatter;
20
+ }
21
+
22
+ /**
23
+ *
24
+ * @param input {TranslatorIO}
25
+ * @return {Promise<TranslatorIO[]>}
26
+ */
27
+ // eslint-disable-next-line no-unused-vars
28
+ translate(input) {
29
+ throw new Error('not implemented');
30
+ }
31
+ }
32
+
33
+ module.exports = {
34
+ Translator,
35
+ };