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/files.js DELETED
@@ -1,56 +0,0 @@
1
- const _ = require("lodash");
2
- const fs = require("fs");
3
- const { resolve } = require("path");
4
- const { filePrefix } = require("./filePrefix");
5
- const makeDir = require("make-dir");
6
-
7
- const getFileContent = (path) => {
8
- return fs.readFileSync(path, { encoding: "UTF-8" });
9
- };
10
-
11
- const pathIsDir = (path) => {
12
- if (!path) return false;
13
-
14
- try {
15
- const stat = fs.statSync(path);
16
- return stat.isDirectory();
17
- } catch (e) {
18
- return false;
19
- }
20
- };
21
-
22
- const removeDir = (path) => {
23
- try {
24
- if (typeof fs.rmSync === "function") {
25
- fs.rmSync(path, { recursive: true });
26
- } else {
27
- fs.rmdirSync(path, { recursive: true });
28
- }
29
- } catch (e) {}
30
- };
31
-
32
- const createDir = (path) => {
33
- try {
34
- makeDir.sync(path);
35
- } catch (e) {}
36
- };
37
-
38
- const cleanDir = (path) => {
39
- removeDir(path);
40
- createDir(path);
41
- };
42
-
43
- const pathIsExist = (path) => path && fs.existsSync(path);
44
-
45
- const createFile = ({ path, fileName, content, withPrefix }) =>
46
- fs.writeFileSync(resolve(__dirname, path, `./${fileName}`), `${withPrefix ? filePrefix : ""}${content}`, _.noop);
47
-
48
- module.exports = {
49
- createFile,
50
- pathIsDir,
51
- cleanDir,
52
- pathIsExist,
53
- createDir,
54
- removeDir,
55
- getFileContent,
56
- };
@@ -1,81 +0,0 @@
1
- const _ = require("lodash");
2
- const prettier = require("prettier");
3
- const { config } = require("./config");
4
- const ts = require("typescript");
5
-
6
- class LanguageServiceHost {
7
- constructor(fileName, content) {
8
- const tsconfig = ts.findConfigFile(fileName, ts.sys.fileExists);
9
-
10
- Object.assign(this, {
11
- fileName,
12
- content,
13
- compilerOptions: tsconfig
14
- ? ts.convertCompilerOptionsFromJson(ts.readConfigFile(tsconfig, ts.sys.readFile).config.compilerOptions).options
15
- : ts.getDefaultCompilerOptions(),
16
- });
17
- }
18
-
19
- getNewLine() {
20
- return "newLine" in ts.sys ? ts.sys.newLine : "\n";
21
- }
22
- getScriptFileNames() {
23
- return [this.fileName];
24
- }
25
- getCompilationSettings() {
26
- return this.compilerOptions;
27
- }
28
- getDefaultLibFileName() {
29
- return ts.getDefaultLibFileName(this.getCompilationSettings());
30
- }
31
- getCurrentDirectory() {
32
- return process.cwd();
33
- }
34
- getScriptVersion() {
35
- return ts.version;
36
- }
37
- getScriptSnapshot() {
38
- return ts.ScriptSnapshot.fromString(this.content);
39
- }
40
- readFile(fileName, encoding) {
41
- if (fileName === this.fileName) {
42
- return this.content;
43
- }
44
-
45
- return ts.sys.readFile(fileName, encoding);
46
- }
47
- fileExists(path) {
48
- return ts.sys.fileExists(path);
49
- }
50
- }
51
-
52
- const removeUnusedImports = (content) => {
53
- const tempFileName = "file.ts";
54
-
55
- const host = new LanguageServiceHost(tempFileName, content);
56
- const languageService = ts.createLanguageService(host);
57
-
58
- const fileTextChanges = languageService.organizeImports(
59
- { type: "file", fileName: tempFileName },
60
- { newLineCharacter: ts.sys.newLine },
61
- )[0];
62
-
63
- if (fileTextChanges && fileTextChanges.textChanges.length) {
64
- return _.reduceRight(
65
- fileTextChanges.textChanges,
66
- (content, { span, newText }) =>
67
- `${content.slice(0, span.start)}${newText}${content.slice(span.start + span.length)}`,
68
- content,
69
- );
70
- }
71
-
72
- return content;
73
- };
74
-
75
- const prettierFormat = (content) => {
76
- return prettier.format(content, config.prettierOptions);
77
- };
78
-
79
- const formatters = [removeUnusedImports, prettierFormat];
80
-
81
- module.exports = (content) => formatters.reduce((fixedContent, formatter) => formatter(fixedContent), content);
package/src/logger.js DELETED
@@ -1,68 +0,0 @@
1
- const _ = require("lodash");
2
- const { config } = require("./config");
3
- const { emojify, emoji } = require("node-emoji");
4
-
5
- let firstLog = true;
6
-
7
- /**
8
- *
9
- * @param {{ type: "warn" | "log" | "error", emojiName: keyof emoji, messages: unknown[] }} payload
10
- * @returns {void}
11
- */
12
- const createLogMessage = ({ type, emojiName, messages }) => {
13
- if (config.silent) return;
14
-
15
- const emoji = emojify(emojiName);
16
-
17
- if (firstLog) {
18
- firstLog = false;
19
- logger.log(
20
- `swagger-typescript-api(${config.version}),${process.env.npm_config_user_agent || `nodejs(${process.version})`}`,
21
- );
22
- }
23
-
24
- console[type](
25
- emoji,
26
- " ",
27
- ..._.map(messages, (message) =>
28
- _.startsWith(message, "\n") ? `\n${emoji} ${message.replace(/\n/, "")}` : message,
29
- ),
30
- );
31
- };
32
-
33
- const logger = {
34
- log: (...messages) =>
35
- createLogMessage({
36
- type: "log",
37
- emojiName: ":sparkles:",
38
- messages,
39
- }),
40
- event: (...messages) =>
41
- createLogMessage({
42
- type: "log",
43
- emojiName: ":comet: ",
44
- messages,
45
- }),
46
- success: (...messages) =>
47
- createLogMessage({
48
- type: "log",
49
- emojiName: ":white_check_mark:",
50
- messages,
51
- }),
52
- warn: (...messages) =>
53
- createLogMessage({
54
- type: "warn",
55
- emojiName: ":warning: ",
56
- messages,
57
- }),
58
- error: (...messages) =>
59
- createLogMessage({
60
- type: "error",
61
- emojiName: ":exclamation:",
62
- messages,
63
- }),
64
- };
65
-
66
- module.exports = {
67
- logger,
68
- };
package/src/modelNames.js DELETED
@@ -1,74 +0,0 @@
1
- const _ = require("lodash");
2
- const { config } = require("./config");
3
- const { logger } = require("./logger");
4
-
5
- const isValidName = (name) => /^([A-Za-z$_]{1,})$/g.test(name);
6
-
7
- const formattedModelNamesMap = new Map();
8
-
9
- const fixModelName = (name) => {
10
- if (!isValidName(name)) {
11
- if (!/^[a-zA-Z_$]/g.test(name)) {
12
- name = `Type ${name}`;
13
- }
14
-
15
- // specific replaces for TSOA 3.x
16
- if (name.includes("."))
17
- name = name
18
- .replace(/Exclude_keyof[A-Za-z]{1,}/g, (match) => "ExcludeKeys")
19
- .replace(/%22\~AND\~%22/g, "And")
20
- .replace(/%22\~OR\~%22/g, "Or")
21
- .replace(/(\.?%22)|\./g, "_")
22
- .replace(/__+$/, "");
23
-
24
- if (name.includes("-")) name = _.startCase(name).replace(/ /g, "");
25
- }
26
-
27
- return name;
28
- };
29
-
30
- /**
31
- *
32
- * @param {string} name
33
- * @param {{ ignorePrefix?: boolean; ignoreSuffix?: boolean }} options
34
- * @returns
35
- */
36
- const formatModelName = (name, options) => {
37
- const typePrefix = options && options.ignorePrefix ? "" : config.typePrefix;
38
- const typeSuffix = options && options.ignoreSuffix ? "" : config.typeSuffix;
39
- const hashKey = `${typePrefix}_${name}_${typeSuffix}`;
40
-
41
- if (typeof name !== "string") {
42
- logger.warn("wrong name of the model name", name);
43
- return name;
44
- }
45
-
46
- if (/^([A-Z_]{1,})$/g.test(name)) {
47
- return _.compact([typePrefix, name, typeSuffix]).join("_");
48
- }
49
-
50
- if (formattedModelNamesMap.has(hashKey)) {
51
- return formattedModelNamesMap.get(hashKey);
52
- }
53
-
54
- const fixedModelName = fixModelName(name);
55
-
56
- const formattedModelName = _.replace(_.startCase(`${typePrefix}_${fixedModelName}_${typeSuffix}`), /\s/g, "");
57
- const modelName = config.hooks.onFormatTypeName(formattedModelName, name) || formattedModelName;
58
-
59
- formattedModelNamesMap.set(hashKey, modelName);
60
-
61
- return modelName;
62
- };
63
-
64
- const formatEnumKey = (key) =>
65
- formatModelName(key, {
66
- ignorePrefix: true,
67
- ignoreSuffix: true,
68
- });
69
-
70
- module.exports = {
71
- formatModelName: formatModelName,
72
- formatEnumKey: formatEnumKey,
73
- isValidName,
74
- };
package/src/modelTypes.js DELETED
@@ -1,31 +0,0 @@
1
- const { formatters } = require("./typeFormatters");
2
- const { formatModelName } = require("./modelNames");
3
- const { config } = require("./config");
4
- const { getTypeData } = require("./components");
5
-
6
- /**
7
- *
8
- * @param {import("./components").TypeInfo} typeInfo
9
- * @returns
10
- */
11
- const prepareModelType = (typeInfo) => {
12
- const rawTypeData = getTypeData(typeInfo);
13
- const typeData = formatters[rawTypeData.type] ? formatters[rawTypeData.type](rawTypeData) : rawTypeData;
14
- let { typeIdentifier, name: originalName, content, description } = typeData;
15
- const name = formatModelName(originalName);
16
-
17
- return {
18
- ...typeData,
19
- typeIdentifier,
20
- name,
21
- description,
22
- $content: rawTypeData.content,
23
- rawContent: rawTypeData.content,
24
- content: content,
25
- typeData,
26
- };
27
- };
28
-
29
- module.exports = {
30
- prepareModelType,
31
- };
package/src/output.js DELETED
@@ -1,165 +0,0 @@
1
- const _ = require("lodash");
2
- const { getFileContent } = require("./files");
3
- const { classNameCase } = require("./render/utils");
4
- const { renderTemplate } = require("./templates");
5
- const { translate: translateToJS } = require("./translators/JavaScript");
6
- const ts = require("typescript");
7
- const formatFileContent = require("./formatFileContent");
8
- const { config } = require("./config");
9
-
10
- const getFileNameWithoutExt = (fileName) => {
11
- const fileNameParts = _.split(fileName, ".");
12
-
13
- if (fileNameParts.length > 1) {
14
- fileNameParts.pop();
15
- }
16
-
17
- return fileNameParts.join(".");
18
- };
19
-
20
- const createFileInfo = (configuration, fileName, content) => {
21
- const fixedFileName = getFileNameWithoutExt(fileName);
22
-
23
- if (configuration.translateToJavaScript) {
24
- const { sourceContent, declarationContent } = translateToJS(`${fixedFileName}${ts.Extension.Ts}`, content);
25
-
26
- if (config.debug) {
27
- console.info("generating output for", `${fixedFileName}${ts.Extension.Js}`);
28
- console.info(sourceContent);
29
- }
30
-
31
- if (config.debug) {
32
- console.info("generating output for", `${fixedFileName}${ts.Extension.Dts}`);
33
- console.info(declarationContent);
34
- }
35
-
36
- return {
37
- name: `${fixedFileName}${ts.Extension.Js}`,
38
- content: formatFileContent(sourceContent),
39
- declaration: {
40
- name: `${fixedFileName}${ts.Extension.Dts}`,
41
- content: formatFileContent(declarationContent),
42
- },
43
- };
44
- }
45
-
46
- if (config.debug) {
47
- console.info("generating output for", `${fixedFileName}${ts.Extension.Ts}`);
48
- console.info(content);
49
- }
50
-
51
- return {
52
- name: `${fixedFileName}${ts.Extension.Ts}`,
53
- content: formatFileContent(content),
54
- declaration: null,
55
- };
56
- };
57
-
58
- const createMultipleFileInfos = (templatesToRender, configuration) => {
59
- const { routes } = configuration;
60
- const { fileNames, generateRouteTypes, generateClient } = configuration.config;
61
- const modularApiFileInfos = [];
62
-
63
- if (routes.$outOfModule) {
64
- if (generateRouteTypes) {
65
- const outOfModuleRouteContent = renderTemplate(templatesToRender.routeTypes, {
66
- ...configuration,
67
- route: configuration.routes.$outOfModule,
68
- });
69
-
70
- modularApiFileInfos.push(createFileInfo(configuration, fileNames.outOfModuleApi, outOfModuleRouteContent));
71
- }
72
- if (generateClient) {
73
- const outOfModuleApiContent = renderTemplate(templatesToRender.api, {
74
- ...configuration,
75
- route: configuration.routes.$outOfModule,
76
- });
77
-
78
- modularApiFileInfos.push(createFileInfo(configuration, fileNames.outOfModuleApi, outOfModuleApiContent));
79
- }
80
- }
81
-
82
- if (routes.combined) {
83
- modularApiFileInfos.push(
84
- ..._.reduce(
85
- routes.combined,
86
- (apiFileInfos, route) => {
87
- if (generateRouteTypes) {
88
- const routeModuleContent = renderTemplate(templatesToRender.routeTypes, {
89
- ...configuration,
90
- route,
91
- });
92
-
93
- apiFileInfos.push(
94
- createFileInfo(configuration, classNameCase(`${route.moduleName}_Route`), routeModuleContent),
95
- );
96
- }
97
-
98
- if (generateClient) {
99
- const apiModuleContent = renderTemplate(templatesToRender.api, {
100
- ...configuration,
101
- route,
102
- });
103
-
104
- apiFileInfos.push(createFileInfo(configuration, classNameCase(route.moduleName), apiModuleContent));
105
- }
106
-
107
- return apiFileInfos;
108
- },
109
- [],
110
- ),
111
- );
112
- }
113
-
114
- return [
115
- createFileInfo(
116
- configuration,
117
- fileNames.dataContracts,
118
- renderTemplate(templatesToRender.dataContracts, configuration),
119
- ),
120
- generateClient &&
121
- createFileInfo(configuration, fileNames.httpClient, renderTemplate(templatesToRender.httpClient, configuration)),
122
- ...modularApiFileInfos,
123
- ];
124
- };
125
-
126
- const createSingleFileInfo = (templatesToRender, configuration) => {
127
- const { generateRouteTypes, generateClient } = configuration.config;
128
-
129
- return [
130
- createFileInfo(
131
- configuration,
132
- configuration.fileName,
133
- _.compact([
134
- renderTemplate(templatesToRender.dataContracts, configuration),
135
- generateRouteTypes && renderTemplate(templatesToRender.routeTypes, configuration),
136
- generateClient && renderTemplate(templatesToRender.httpClient, configuration),
137
- generateClient && renderTemplate(templatesToRender.api, configuration),
138
- ]).join("\n"),
139
- ),
140
- ];
141
- };
142
-
143
- const createExtraFileInfos = (configuration) => {
144
- return _.map(configuration.extraTemplates, (extraTemplate) => {
145
- return createFileInfo(
146
- configuration,
147
- extraTemplate.name,
148
- renderTemplate(getFileContent(extraTemplate.path), configuration),
149
- );
150
- });
151
- };
152
-
153
- module.exports = {
154
- generateOutputFiles: ({ modular, templatesToRender, configuration }) => {
155
- const output = modular
156
- ? createMultipleFileInfos(templatesToRender, configuration)
157
- : createSingleFileInfo(templatesToRender, configuration);
158
-
159
- if (!_.isEmpty(configuration.extraTemplates)) {
160
- output.push(...createExtraFileInfos(configuration));
161
- }
162
-
163
- return output.filter((fileInfo) => !!fileInfo && !!fileInfo.content);
164
- },
165
- };
@@ -1,23 +0,0 @@
1
- const { cosmiconfigSync } = require("cosmiconfig");
2
- const constants = require("./constants");
3
-
4
- /**
5
- * Get prettier options from user's project or return the default one
6
- * @return {import('prettier').Options} Prettier options
7
- */
8
- function getPrettierOptions() {
9
- const prettier = cosmiconfigSync("prettier").search();
10
-
11
- if (prettier) {
12
- return {
13
- ...prettier.config,
14
- parser: "typescript",
15
- };
16
- }
17
-
18
- return constants.PRETTIER_OPTIONS;
19
- }
20
-
21
- module.exports = {
22
- getPrettierOptions,
23
- };
@@ -1,10 +0,0 @@
1
- /**
2
- * Format a line in JSDOC line by adding ' *' at the beginning and \n character at the end
3
- *
4
- * @example 'abc' -> ' * abc\n'
5
- * @param line
6
- * @return {string}
7
- */
8
- module.exports = function fmtToJSDocLine(line, { eol = true }) {
9
- return ` * ${line}${eol ? "\n" : ""}`;
10
- };
@@ -1,31 +0,0 @@
1
- const { classNameCase, formatDescription, internalCase } = require("../../common");
2
- const { getComponentByRef } = require("../../components");
3
- const { formatModelName } = require("../../modelNames");
4
- const {
5
- getInlineParseContent,
6
- getParseContent,
7
- parseSchema,
8
- checkAndAddNull,
9
- isNeedToAddNull,
10
- } = require("../../schema");
11
- const { formatters, inlineExtraFormatters } = require("../../typeFormatters");
12
- const { NameResolver } = require("../../utils/resolveName");
13
-
14
- module.exports = {
15
- formatDescription,
16
- internalCase,
17
- classNameCase,
18
- getInlineParseContent,
19
- getParseContent,
20
- getComponentByRef,
21
- parseSchema,
22
- formatters,
23
- checkAndAddNull,
24
- isNeedToAddNull,
25
- inlineExtraFormatters,
26
- formatModelName,
27
- fmtToJSDocLine: require("./fmtToJSDocLine"),
28
- NameResolver: NameResolver,
29
- _: require("lodash"),
30
- require: require("./templateRequire").templateRequire,
31
- };
@@ -1,17 +0,0 @@
1
- const _ = require("lodash");
2
- const path = require("path");
3
- const { config } = require("../../config");
4
-
5
- const templateRequire = (packageOrPath) => {
6
- const isPath = _.startsWith(packageOrPath, "./") || _.startsWith(packageOrPath, "../");
7
-
8
- if (isPath) {
9
- return require(path.resolve(config.templates, packageOrPath));
10
- }
11
-
12
- return require(packageOrPath);
13
- };
14
-
15
- module.exports = {
16
- templateRequire,
17
- };
package/src/routeNames.js DELETED
@@ -1,46 +0,0 @@
1
- const { config } = require("./config");
2
- const { logger } = require("./logger");
3
- const { renderTemplate } = require("./templates");
4
-
5
- const getRouteName = (routeInfo) => {
6
- const { moduleName } = routeInfo;
7
- const { routeNameDuplicatesMap, templatesToRender } = config;
8
- const routeNameTemplate = templatesToRender.routeName;
9
-
10
- const routeNameFromTemplate = renderTemplate(routeNameTemplate, {
11
- routeInfo: routeInfo,
12
- utils: require("./render/utils"),
13
- config,
14
- });
15
-
16
- const routeName = config.hooks.onFormatRouteName(routeInfo, routeNameFromTemplate) || routeNameFromTemplate;
17
-
18
- const duplicateIdentifier = `${moduleName}|${routeName}`;
19
-
20
- if (routeNameDuplicatesMap.has(duplicateIdentifier)) {
21
- routeNameDuplicatesMap.set(duplicateIdentifier, routeNameDuplicatesMap.get(duplicateIdentifier) + 1);
22
-
23
- logger.warn(
24
- `Module "${moduleName}" already has method "${routeName}()"`,
25
- `\nThis method has been renamed to "${
26
- routeName + routeNameDuplicatesMap.get(duplicateIdentifier)
27
- }()" to solve conflict names.`,
28
- );
29
- } else {
30
- routeNameDuplicatesMap.set(duplicateIdentifier, 1);
31
- }
32
-
33
- const duplicates = routeNameDuplicatesMap.get(duplicateIdentifier);
34
-
35
- const routeNameInfo = {
36
- usage: routeName + (duplicates > 1 ? duplicates : ""),
37
- original: routeName,
38
- duplicate: duplicates > 1,
39
- };
40
-
41
- return config.hooks.onCreateRouteName(routeNameInfo, routeInfo) || routeNameInfo;
42
- };
43
-
44
- module.exports = {
45
- getRouteName,
46
- };