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.
- package/README.md +263 -41
- package/index.d.ts +97 -0
- package/index.js +242 -115
- package/package.json +121 -116
- package/src/code-formatter.js +101 -0
- package/src/code-gen-process.js +456 -0
- package/src/configuration.js +425 -0
- package/src/constants.js +14 -31
- package/src/index.js +20 -271
- package/src/schema-components-map.js +60 -0
- package/src/schema-parser/schema-formatters.js +145 -0
- package/src/schema-parser/schema-parser.js +497 -0
- package/src/schema-parser/schema-routes.js +902 -0
- package/src/swagger-schema-resolver.js +187 -0
- package/src/templates.js +174 -155
- package/src/translators/JavaScript.js +3 -14
- package/src/type-name.js +79 -0
- package/src/util/file-system.js +76 -0
- package/src/{utils → util}/id.js +9 -9
- package/src/util/internal-case.js +5 -0
- package/src/util/logger.js +100 -0
- package/src/{utils/resolveName.js → util/name-resolver.js} +94 -97
- package/src/util/object-assign.js +11 -0
- package/src/util/pascal-case.js +5 -0
- package/src/{utils → util}/random.js +14 -14
- package/templates/base/data-contract-jsdoc.ejs +29 -24
- package/templates/base/data-contracts.ejs +3 -3
- package/templates/base/interface-data-contract.ejs +1 -0
- package/templates/base/route-docs.ejs +3 -4
- package/templates/base/route-type.ejs +2 -2
- package/templates/default/procedure-call.ejs +2 -2
- package/templates/default/route-types.ejs +2 -2
- package/templates/modular/api.ejs +2 -2
- package/templates/modular/procedure-call.ejs +2 -2
- package/templates/modular/route-types.ejs +2 -2
- package/src/apiConfig.js +0 -30
- package/src/common.js +0 -28
- package/src/components.js +0 -91
- package/src/config.js +0 -106
- package/src/filePrefix.js +0 -14
- package/src/files.js +0 -56
- package/src/formatFileContent.js +0 -81
- package/src/logger.js +0 -59
- package/src/modelNames.js +0 -78
- package/src/modelTypes.js +0 -31
- package/src/output.js +0 -165
- package/src/prettierOptions.js +0 -23
- package/src/render/utils/fmtToJSDocLine.js +0 -10
- package/src/render/utils/index.js +0 -31
- package/src/render/utils/templateRequire.js +0 -17
- package/src/routeNames.js +0 -46
- package/src/routes.js +0 -809
- package/src/schema.js +0 -474
- package/src/swagger.js +0 -152
- package/src/typeFormatters.js +0 -121
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
const { Configuration } = require("./configuration.js");
|
|
2
|
+
const _ = require("lodash");
|
|
3
|
+
const converter = require("swagger2openapi");
|
|
4
|
+
const https = require("https");
|
|
5
|
+
const axios = require("axios");
|
|
6
|
+
const yaml = require("js-yaml");
|
|
7
|
+
|
|
8
|
+
class SwaggerSchemaResolver {
|
|
9
|
+
/**
|
|
10
|
+
* @type {Configuration}
|
|
11
|
+
*/
|
|
12
|
+
config;
|
|
13
|
+
/**
|
|
14
|
+
* @type {Logger}
|
|
15
|
+
*/
|
|
16
|
+
logger;
|
|
17
|
+
/**
|
|
18
|
+
* @type {FileSystem}
|
|
19
|
+
*/
|
|
20
|
+
fileSystem;
|
|
21
|
+
|
|
22
|
+
constructor(configuration, logger, fileSystem) {
|
|
23
|
+
this.config = configuration;
|
|
24
|
+
this.logger = logger;
|
|
25
|
+
this.fileSystem = fileSystem;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
*
|
|
30
|
+
* @returns {Promise<{usageSchema: Record<string, *>, originalSchema: Record<string, *>}>}
|
|
31
|
+
*/
|
|
32
|
+
async create() {
|
|
33
|
+
const { spec, patch, input, url, disableStrictSSL, disableProxy, authorizationToken } = this.config;
|
|
34
|
+
|
|
35
|
+
if (this.config.spec) {
|
|
36
|
+
return await this.convertSwaggerObject(spec, { patch });
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const swaggerSchemaFile = await this.fetchSwaggerSchemaFile(
|
|
40
|
+
input,
|
|
41
|
+
url,
|
|
42
|
+
disableStrictSSL,
|
|
43
|
+
disableProxy,
|
|
44
|
+
authorizationToken,
|
|
45
|
+
);
|
|
46
|
+
const swaggerSchemaObject = this.processSwaggerSchemaFile(swaggerSchemaFile);
|
|
47
|
+
return await this.convertSwaggerObject(swaggerSchemaObject, { patch });
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
*
|
|
52
|
+
* @param swaggerSchema {Record<string, any>}
|
|
53
|
+
* @param converterOptions {{ patch?: boolean }}
|
|
54
|
+
* @returns {Promise<{ usageSchema: Record<string, any>, originalSchema: Record<string, any>}>}
|
|
55
|
+
*/
|
|
56
|
+
convertSwaggerObject(swaggerSchema, converterOptions) {
|
|
57
|
+
return new Promise((resolve) => {
|
|
58
|
+
const result = _.cloneDeep(swaggerSchema);
|
|
59
|
+
result.info = _.merge(
|
|
60
|
+
{
|
|
61
|
+
title: "No title",
|
|
62
|
+
version: "",
|
|
63
|
+
},
|
|
64
|
+
result.info,
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
if (!result.openapi) {
|
|
68
|
+
result.paths = _.merge({}, result.paths);
|
|
69
|
+
|
|
70
|
+
converter.convertObj(
|
|
71
|
+
result,
|
|
72
|
+
{
|
|
73
|
+
...converterOptions,
|
|
74
|
+
warnOnly: true,
|
|
75
|
+
refSiblings: "preserve",
|
|
76
|
+
rbname: "requestBodyName",
|
|
77
|
+
},
|
|
78
|
+
(err, options) => {
|
|
79
|
+
const parsedSwaggerSchema = _.get(err, "options.openapi", _.get(options, "openapi"));
|
|
80
|
+
if (!parsedSwaggerSchema && err) {
|
|
81
|
+
throw new Error(err);
|
|
82
|
+
}
|
|
83
|
+
this.config.update({ convertedFromSwagger2: true });
|
|
84
|
+
resolve({
|
|
85
|
+
usageSchema: parsedSwaggerSchema,
|
|
86
|
+
originalSchema: result,
|
|
87
|
+
});
|
|
88
|
+
},
|
|
89
|
+
);
|
|
90
|
+
} else {
|
|
91
|
+
resolve({
|
|
92
|
+
usageSchema: result,
|
|
93
|
+
originalSchema: _.cloneDeep(result),
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
fetchSwaggerSchemaFile(pathToSwagger, urlToSwagger, disableStrictSSL, disableProxy, authorizationToken) {
|
|
100
|
+
return new Promise((resolve, reject) => {
|
|
101
|
+
if (this.fileSystem.pathIsExist(pathToSwagger)) {
|
|
102
|
+
this.logger.log(`try to get swagger by path "${pathToSwagger}"`);
|
|
103
|
+
resolve(this.fileSystem.getFileContent(pathToSwagger));
|
|
104
|
+
} else {
|
|
105
|
+
this.logger.log(`try to get swagger by URL "${urlToSwagger}"`);
|
|
106
|
+
// setup options for Axios
|
|
107
|
+
const axiosOptions = {
|
|
108
|
+
maxContentLength: Infinity,
|
|
109
|
+
maxBodyLength: Infinity,
|
|
110
|
+
};
|
|
111
|
+
//
|
|
112
|
+
if (disableStrictSSL) {
|
|
113
|
+
axiosOptions.httpsAgent = new https.Agent({
|
|
114
|
+
rejectUnauthorized: false,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
//
|
|
118
|
+
if (authorizationToken) {
|
|
119
|
+
axiosOptions.headers = {
|
|
120
|
+
Authorization: authorizationToken,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
//
|
|
124
|
+
if (disableProxy) axiosOptions.proxy = false;
|
|
125
|
+
//
|
|
126
|
+
axios
|
|
127
|
+
.get(urlToSwagger, axiosOptions)
|
|
128
|
+
.then((res) => resolve(res.data))
|
|
129
|
+
.catch((error) => {
|
|
130
|
+
const message = `error while getting swagger by URL ${urlToSwagger}`;
|
|
131
|
+
|
|
132
|
+
this.logger.error(message, "response" in error ? error.response : error);
|
|
133
|
+
|
|
134
|
+
reject(message);
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
processSwaggerSchemaFile(file) {
|
|
141
|
+
if (typeof file !== "string") return file;
|
|
142
|
+
|
|
143
|
+
try {
|
|
144
|
+
return JSON.parse(file);
|
|
145
|
+
} catch (e) {
|
|
146
|
+
return yaml.load(file);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
fixSwaggerSchema({ usageSchema, originalSchema }) {
|
|
151
|
+
const usagePaths = _.get(usageSchema, "paths");
|
|
152
|
+
const originalPaths = _.get(originalSchema, "paths");
|
|
153
|
+
|
|
154
|
+
// walk by routes
|
|
155
|
+
_.each(usagePaths, (usagePathObject, route) => {
|
|
156
|
+
const originalPathObject = _.get(originalPaths, route);
|
|
157
|
+
|
|
158
|
+
// walk by methods
|
|
159
|
+
_.each(usagePathObject, (usageRouteInfo, methodName) => {
|
|
160
|
+
const originalRouteInfo = _.get(originalPathObject, methodName);
|
|
161
|
+
const usageRouteParams = _.get(usageRouteInfo, "parameters", []);
|
|
162
|
+
const originalRouteParams = _.get(originalRouteInfo, "parameters", []);
|
|
163
|
+
|
|
164
|
+
usageRouteInfo.consumes = _.uniq(
|
|
165
|
+
_.compact([...(usageRouteInfo.consumes || []), ...(originalRouteInfo.consumes || [])]),
|
|
166
|
+
);
|
|
167
|
+
usageRouteInfo.produces = _.uniq(
|
|
168
|
+
_.compact([...(usageRouteInfo.produces || []), ...(originalRouteInfo.produces || [])]),
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
_.each(originalRouteParams, (originalRouteParam) => {
|
|
172
|
+
const existUsageParam = _.find(
|
|
173
|
+
usageRouteParams,
|
|
174
|
+
(param) => originalRouteParam.in === param.in && originalRouteParam.name === param.name,
|
|
175
|
+
);
|
|
176
|
+
if (!existUsageParam) {
|
|
177
|
+
usageRouteParams.push(originalRouteParam);
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
module.exports = {
|
|
186
|
+
SwaggerSchemaResolver,
|
|
187
|
+
};
|
package/src/templates.js
CHANGED
|
@@ -1,155 +1,174 @@
|
|
|
1
|
-
const
|
|
2
|
-
const
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
if (
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
1
|
+
const { resolve } = require("path");
|
|
2
|
+
const _ = require("lodash");
|
|
3
|
+
const Eta = require("eta");
|
|
4
|
+
const path = require("path");
|
|
5
|
+
|
|
6
|
+
class Templates {
|
|
7
|
+
/**
|
|
8
|
+
* @type {Configuration}
|
|
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
|
+
getTemplatePaths = ({ templates, modular }) => {
|
|
32
|
+
const baseTemplatesPath = resolve(__dirname, "../templates/base");
|
|
33
|
+
const defaultTemplatesPath = resolve(__dirname, "../templates/default");
|
|
34
|
+
const modularTemplatesPath = resolve(__dirname, "../templates/modular");
|
|
35
|
+
const originalTemplatesPath = modular ? modularTemplatesPath : defaultTemplatesPath;
|
|
36
|
+
const customTemplatesPath = templates ? resolve(process.cwd(), templates) : originalTemplatesPath;
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
/** `templates/base` */
|
|
40
|
+
base: baseTemplatesPath,
|
|
41
|
+
/** `templates/default` */
|
|
42
|
+
default: defaultTemplatesPath,
|
|
43
|
+
/** `templates/modular` */
|
|
44
|
+
modular: modularTemplatesPath,
|
|
45
|
+
/** usage path if `--templates` option is not set */
|
|
46
|
+
original: originalTemplatesPath,
|
|
47
|
+
/** custom path to templates (`--templates`) */
|
|
48
|
+
custom: customTemplatesPath,
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
cropExtension = (path) =>
|
|
53
|
+
this.config.templateExtensions.reduce((path, ext) => (_.endsWith(path, ext) ? path.replace(ext, "") : path), path);
|
|
54
|
+
|
|
55
|
+
getTemplateFullPath = (path, fileName) => {
|
|
56
|
+
const raw = resolve(path, "./", this.cropExtension(fileName));
|
|
57
|
+
const pathVariants = this.config.templateExtensions.map((extension) => `${raw}${extension}`);
|
|
58
|
+
|
|
59
|
+
return pathVariants.find((variant) => !!this.fileSystem.pathIsExist(variant));
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
requireFnFromTemplate = (packageOrPath) => {
|
|
63
|
+
const isPath = _.startsWith(packageOrPath, "./") || _.startsWith(packageOrPath, "../");
|
|
64
|
+
|
|
65
|
+
if (isPath) {
|
|
66
|
+
return require(path.resolve(this.config.templates, packageOrPath));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return require(packageOrPath);
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
getTemplate = ({ fileName, name, path }) => {
|
|
73
|
+
const { templatePaths } = this.config;
|
|
74
|
+
|
|
75
|
+
if (path) {
|
|
76
|
+
return this.fileSystem.getFileContent(path);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (!fileName) return "";
|
|
80
|
+
|
|
81
|
+
const customFullPath = this.getTemplateFullPath(templatePaths.custom, fileName);
|
|
82
|
+
let fileContent = customFullPath && this.fileSystem.getFileContent(customFullPath);
|
|
83
|
+
|
|
84
|
+
if (!fileContent) {
|
|
85
|
+
const baseFullPath = this.getTemplateFullPath(templatePaths.base, fileName);
|
|
86
|
+
|
|
87
|
+
if (baseFullPath) {
|
|
88
|
+
fileContent = this.fileSystem.getFileContent(baseFullPath);
|
|
89
|
+
} else {
|
|
90
|
+
this.logger.warn(
|
|
91
|
+
`${_.lowerCase(name)} template not found in ${customFullPath}`,
|
|
92
|
+
`\nCode generator will use the default template`,
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const originalFullPath = this.getTemplateFullPath(templatePaths.original, fileName);
|
|
97
|
+
|
|
98
|
+
if (originalFullPath) {
|
|
99
|
+
fileContent = this.fileSystem.getFileContent(originalFullPath);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return fileContent;
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
getTemplates = ({ templatePaths }) => {
|
|
107
|
+
this.logger.log(`try to read templates from directory "${templatePaths.custom}"`);
|
|
108
|
+
|
|
109
|
+
return _.reduce(
|
|
110
|
+
this.config.templateInfos,
|
|
111
|
+
(acc, { fileName, name }) => ({
|
|
112
|
+
...acc,
|
|
113
|
+
[name]: this.getTemplate({ fileName, name }),
|
|
114
|
+
}),
|
|
115
|
+
{},
|
|
116
|
+
);
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
getTemplateContent = (path) => {
|
|
120
|
+
const foundTemplatePathKey = _.keys(this.config.templatePaths).find((key) => _.startsWith(path, `@${key}`));
|
|
121
|
+
|
|
122
|
+
const findPathWithExt = (path) => {
|
|
123
|
+
const raw = this.cropExtension(path);
|
|
124
|
+
const pathVariants = this.config.templateExtensions.map((extension) => `${raw}${extension}`);
|
|
125
|
+
return pathVariants.find((variant) => this.fileSystem.pathIsExist(variant));
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
const rawPath = resolve(
|
|
129
|
+
_.replace(path, `@${foundTemplatePathKey}`, this.config.templatePaths[foundTemplatePathKey]),
|
|
130
|
+
);
|
|
131
|
+
const fixedPath = findPathWithExt(rawPath);
|
|
132
|
+
|
|
133
|
+
if (fixedPath) {
|
|
134
|
+
return this.fileSystem.getFileContent(fixedPath);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const customPath = findPathWithExt(resolve(this.config.templatePaths.custom, path));
|
|
138
|
+
|
|
139
|
+
if (customPath) {
|
|
140
|
+
return this.fileSystem.getFileContent(customPath);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const originalPath = findPathWithExt(resolve(this.config.templatePaths.original, path));
|
|
144
|
+
|
|
145
|
+
if (originalPath) {
|
|
146
|
+
return this.fileSystem.getFileContent(originalPath);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return "";
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
renderTemplate = (template, configuration, options) => {
|
|
153
|
+
if (!template) return "";
|
|
154
|
+
|
|
155
|
+
return Eta.render(
|
|
156
|
+
template,
|
|
157
|
+
{
|
|
158
|
+
...this.getRenderTemplateData(),
|
|
159
|
+
...configuration,
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
async: false,
|
|
163
|
+
...(options || {}),
|
|
164
|
+
includeFile: (path, payload, options) => {
|
|
165
|
+
return this.renderTemplate(this.getTemplateContent(path), payload, options);
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
);
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
module.exports = {
|
|
173
|
+
Templates,
|
|
174
|
+
};
|
|
@@ -7,20 +7,9 @@ function translate(fileName, content, options) {
|
|
|
7
7
|
const originalSourceFileGet = host.getSourceFile.bind(host);
|
|
8
8
|
host.getSourceFile = (sourceFileName, languageVersion, onError, shouldCreateNewSourceFile) => {
|
|
9
9
|
if (sourceFileName !== fileName)
|
|
10
|
-
return originalSourceFileGet(
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
onError,
|
|
14
|
-
shouldCreateNewSourceFile,
|
|
15
|
-
);
|
|
16
|
-
|
|
17
|
-
return ts.createSourceFile(
|
|
18
|
-
sourceFileName,
|
|
19
|
-
content,
|
|
20
|
-
languageVersion,
|
|
21
|
-
true,
|
|
22
|
-
ts.ScriptKind.External,
|
|
23
|
-
);
|
|
10
|
+
return originalSourceFileGet(sourceFileName, languageVersion, onError, shouldCreateNewSourceFile);
|
|
11
|
+
|
|
12
|
+
return ts.createSourceFile(sourceFileName, content, languageVersion, true, ts.ScriptKind.External);
|
|
24
13
|
};
|
|
25
14
|
|
|
26
15
|
host.writeFile = (fileName, contents) => {
|
package/src/type-name.js
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
const _ = require("lodash");
|
|
2
|
+
|
|
3
|
+
class TypeName {
|
|
4
|
+
/** @type {Map<string, string>} */
|
|
5
|
+
formattedModelNamesMap = new Map();
|
|
6
|
+
|
|
7
|
+
/** @type {Configuration} */
|
|
8
|
+
config;
|
|
9
|
+
|
|
10
|
+
/** @type {Logger} */
|
|
11
|
+
logger;
|
|
12
|
+
|
|
13
|
+
constructor(config, logger) {
|
|
14
|
+
this.config = config;
|
|
15
|
+
this.logger = logger;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @param name
|
|
20
|
+
* @param options {{ ignorePrefix?: boolean, ignoreSuffix?: boolean }}
|
|
21
|
+
* @return {string}
|
|
22
|
+
*/
|
|
23
|
+
format = (name, options) => {
|
|
24
|
+
const typePrefix = options && options.ignorePrefix ? "" : this.config.typePrefix;
|
|
25
|
+
const typeSuffix = options && options.ignoreSuffix ? "" : this.config.typeSuffix;
|
|
26
|
+
const hashKey = `${typePrefix}_${name}_${typeSuffix}`;
|
|
27
|
+
|
|
28
|
+
if (typeof name !== "string") {
|
|
29
|
+
this.logger.warn("wrong name of the model name", name);
|
|
30
|
+
return name;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (/^([A-Z_]{1,})$/g.test(name)) {
|
|
34
|
+
return _.compact([typePrefix, name, typeSuffix]).join("_");
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (this.formattedModelNamesMap.has(hashKey)) {
|
|
38
|
+
return this.formattedModelNamesMap.get(hashKey);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const fixedModelName = fixModelName(name);
|
|
42
|
+
|
|
43
|
+
const formattedModelName = _.replace(_.startCase(`${typePrefix}_${fixedModelName}_${typeSuffix}`), /\s/g, "");
|
|
44
|
+
const modelName = this.config.hooks.onFormatTypeName(formattedModelName, name) || formattedModelName;
|
|
45
|
+
|
|
46
|
+
this.formattedModelNamesMap.set(hashKey, modelName);
|
|
47
|
+
|
|
48
|
+
return modelName;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
isValidName = isValidName;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const isValidName = (name) => /^([A-Za-z$_]{1,})$/g.test(name);
|
|
55
|
+
|
|
56
|
+
const fixModelName = (name) => {
|
|
57
|
+
if (!isValidName(name)) {
|
|
58
|
+
if (!/^[a-zA-Z_$]/g.test(name)) {
|
|
59
|
+
name = `Type ${name}`;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// specific replaces for TSOA 3.x
|
|
63
|
+
if (name.includes("."))
|
|
64
|
+
name = name
|
|
65
|
+
.replace(/Exclude_keyof[A-Za-z]{1,}/g, (match) => "ExcludeKeys")
|
|
66
|
+
.replace(/%22\~AND\~%22/g, "And")
|
|
67
|
+
.replace(/%22\~OR\~%22/g, "Or")
|
|
68
|
+
.replace(/(\.?%22)|\./g, "_")
|
|
69
|
+
.replace(/__+$/, "");
|
|
70
|
+
|
|
71
|
+
if (name.includes("-")) name = _.startCase(name).replace(/ /g, "");
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return name;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
module.exports = {
|
|
78
|
+
TypeName,
|
|
79
|
+
};
|