swagger-typescript-api 11.1.3 → 12.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.
- package/README.md +23 -5
- package/cli/index.js +0 -0
- package/index.d.ts +66 -3
- package/index.js +6 -1
- package/package.json +5 -2
- package/src/code-gen-process.js +12 -14
- package/src/configuration.js +27 -4
- package/src/index.js +0 -0
- package/src/schema-parser/schema-formatters.js +26 -19
- package/src/schema-parser/schema-parser.js +131 -204
- package/src/schema-parser/schema-routes.js +47 -38
- package/src/schema-parser/schema-utils.js +165 -0
- package/src/templates.js +2 -2
- package/src/type-name.js +49 -30
- package/src/util/logger.js +19 -1
- package/src/util/name-resolver.js +50 -31
- package/templates/base/enum-data-contract.ejs +1 -4
- package/CHANGELOG.md +0 -1121
|
@@ -28,6 +28,10 @@ class SchemaRoutes {
|
|
|
28
28
|
* @type {SchemaParser}
|
|
29
29
|
*/
|
|
30
30
|
schemaParser;
|
|
31
|
+
/**
|
|
32
|
+
* @type {SchemaUtils}
|
|
33
|
+
*/
|
|
34
|
+
schemaUtils;
|
|
31
35
|
/**
|
|
32
36
|
* @type {TypeName}
|
|
33
37
|
*/
|
|
@@ -55,14 +59,15 @@ class SchemaRoutes {
|
|
|
55
59
|
constructor(config, schemaParser, schemaComponentMap, logger, templates, typeName) {
|
|
56
60
|
this.config = config;
|
|
57
61
|
this.schemaParser = schemaParser;
|
|
62
|
+
this.schemaUtils = this.schemaParser.schemaUtils;
|
|
58
63
|
this.typeName = typeName;
|
|
59
64
|
this.schemaComponentMap = schemaComponentMap;
|
|
60
65
|
this.logger = logger;
|
|
61
66
|
this.templates = templates;
|
|
62
67
|
|
|
63
68
|
this.FORM_DATA_TYPES = _.uniq([
|
|
64
|
-
this.schemaParser.
|
|
65
|
-
this.schemaParser.
|
|
69
|
+
this.schemaParser.getSchemaType({ type: "string", format: "file" }),
|
|
70
|
+
this.schemaParser.getSchemaType({ type: "string", format: "binary" }),
|
|
66
71
|
]);
|
|
67
72
|
}
|
|
68
73
|
|
|
@@ -87,7 +92,9 @@ class SchemaRoutes {
|
|
|
87
92
|
);
|
|
88
93
|
};
|
|
89
94
|
|
|
90
|
-
parseRouteName = (
|
|
95
|
+
parseRouteName = (originalRouteName) => {
|
|
96
|
+
const routeName = this.config.hooks.onPreBuildRoutePath(originalRouteName) || originalRouteName;
|
|
97
|
+
|
|
91
98
|
const pathParamMatches = (routeName || "").match(
|
|
92
99
|
/({(([a-zA-Z]-?_?\.?){1,})([0-9]{1,})?})|(:(([a-zA-Z]-?_?\.?){1,})([0-9]{1,})?:?)/g,
|
|
93
100
|
);
|
|
@@ -123,8 +130,9 @@ class SchemaRoutes {
|
|
|
123
130
|
|
|
124
131
|
let fixedRoute = _.reduce(
|
|
125
132
|
pathParams,
|
|
126
|
-
(fixedRoute, pathParam) => {
|
|
127
|
-
|
|
133
|
+
(fixedRoute, pathParam, i, arr) => {
|
|
134
|
+
const insertion = this.config.hooks.onInsertPathParam(pathParam.name, i, arr, fixedRoute) || pathParam.name;
|
|
135
|
+
return _.replace(fixedRoute, pathParam.$match, `\${${insertion}}`);
|
|
128
136
|
},
|
|
129
137
|
routeName || "",
|
|
130
138
|
);
|
|
@@ -161,12 +169,14 @@ class SchemaRoutes {
|
|
|
161
169
|
});
|
|
162
170
|
}
|
|
163
171
|
|
|
164
|
-
|
|
165
|
-
originalRoute:
|
|
172
|
+
const result = {
|
|
173
|
+
originalRoute: originalRouteName || "",
|
|
166
174
|
route: fixedRoute,
|
|
167
175
|
pathParams,
|
|
168
176
|
queryParams,
|
|
169
177
|
};
|
|
178
|
+
|
|
179
|
+
return this.config.hooks.onBuildRoutePath(result) || result;
|
|
170
180
|
};
|
|
171
181
|
|
|
172
182
|
getRouteParams = (routeInfo, pathParamsFromRouteName, queryParamsFromRouteName) => {
|
|
@@ -182,7 +192,7 @@ class SchemaRoutes {
|
|
|
182
192
|
};
|
|
183
193
|
|
|
184
194
|
_.each(parameters, (parameter) => {
|
|
185
|
-
const refTypeInfo = this.schemaParser.
|
|
195
|
+
const refTypeInfo = this.schemaParser.schemaUtils.getSchemaRefType(parameter);
|
|
186
196
|
let routeParam = null;
|
|
187
197
|
|
|
188
198
|
if (refTypeInfo && refTypeInfo.rawTypeData.in && refTypeInfo.rawTypeData) {
|
|
@@ -266,9 +276,7 @@ class SchemaRoutes {
|
|
|
266
276
|
return CONTENT_KIND.IMAGE;
|
|
267
277
|
}
|
|
268
278
|
|
|
269
|
-
if (
|
|
270
|
-
_.some(contentTypes, (contentType) => _.startsWith(contentType, "text/"))
|
|
271
|
-
) {
|
|
279
|
+
if (_.some(contentTypes, (contentType) => _.startsWith(contentType, "text/"))) {
|
|
272
280
|
return CONTENT_KIND.TEXT;
|
|
273
281
|
}
|
|
274
282
|
|
|
@@ -303,7 +311,7 @@ class SchemaRoutes {
|
|
|
303
311
|
getTypeFromRequestInfo = ({ requestInfo, parsedSchemas, operationId, defaultType, typeName }) => {
|
|
304
312
|
// TODO: make more flexible pick schema without content type
|
|
305
313
|
const schema = this.getSchemaFromRequestType(requestInfo);
|
|
306
|
-
const refTypeInfo = this.schemaParser.
|
|
314
|
+
const refTypeInfo = this.schemaParser.schemaUtils.getSchemaRefType(requestInfo);
|
|
307
315
|
|
|
308
316
|
if (schema) {
|
|
309
317
|
const content = this.schemaParser.getInlineParseContent(schema, typeName);
|
|
@@ -357,7 +365,7 @@ class SchemaRoutes {
|
|
|
357
365
|
...(requestInfo || {}),
|
|
358
366
|
contentTypes: contentTypes,
|
|
359
367
|
contentKind: this.getContentKind(contentTypes),
|
|
360
|
-
type: this.schemaParser.
|
|
368
|
+
type: this.schemaParser.schemaUtils.safeAddNullToType(
|
|
361
369
|
requestInfo,
|
|
362
370
|
this.getTypeFromRequestInfo({
|
|
363
371
|
requestInfo,
|
|
@@ -398,7 +406,7 @@ class SchemaRoutes {
|
|
|
398
406
|
}
|
|
399
407
|
const headerTypes = Object.fromEntries(
|
|
400
408
|
Object.entries(src).map(([k, v]) => {
|
|
401
|
-
return [k, this.schemaParser.
|
|
409
|
+
return [k, this.schemaParser.getSchemaType(v)];
|
|
402
410
|
}),
|
|
403
411
|
);
|
|
404
412
|
const r = `headers: { ${Object.entries(headerTypes)
|
|
@@ -467,11 +475,11 @@ class SchemaRoutes {
|
|
|
467
475
|
let typeName = null;
|
|
468
476
|
|
|
469
477
|
if (this.config.extractRequestBody) {
|
|
470
|
-
typeName = this.
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
478
|
+
typeName = this.schemaUtils.resolveTypeName(
|
|
479
|
+
routeName.usage,
|
|
480
|
+
this.config.extractingOptions.requestBodySuffix,
|
|
481
|
+
this.config.extractingOptions.requestBodyNameResolver,
|
|
482
|
+
);
|
|
475
483
|
}
|
|
476
484
|
|
|
477
485
|
if (routeParams.formData.length) {
|
|
@@ -483,7 +491,7 @@ class SchemaRoutes {
|
|
|
483
491
|
type = this.schemaParser.getInlineParseContent(schema, typeName);
|
|
484
492
|
} else if (requestBody) {
|
|
485
493
|
schema = this.getSchemaFromRequestType(requestBody);
|
|
486
|
-
type = this.schemaParser.
|
|
494
|
+
type = this.schemaParser.schemaUtils.safeAddNullToType(
|
|
487
495
|
requestBody,
|
|
488
496
|
this.getTypeFromRequestInfo({
|
|
489
497
|
requestInfo: requestBody,
|
|
@@ -568,7 +576,11 @@ class SchemaRoutes {
|
|
|
568
576
|
if (fixedSchema) return fixedSchema;
|
|
569
577
|
|
|
570
578
|
if (extractRequestParams) {
|
|
571
|
-
const typeName = this.
|
|
579
|
+
const typeName = this.schemaUtils.resolveTypeName(
|
|
580
|
+
routeName.usage,
|
|
581
|
+
this.config.extractingOptions.requestParamsSuffix,
|
|
582
|
+
this.config.extractingOptions.requestParamsNameResolver,
|
|
583
|
+
);
|
|
572
584
|
|
|
573
585
|
return this.schemaComponentMap.createComponent("schemas", typeName, { ...schema });
|
|
574
586
|
}
|
|
@@ -578,11 +590,11 @@ class SchemaRoutes {
|
|
|
578
590
|
|
|
579
591
|
extractResponseBodyIfItNeeded = (routeInfo, responseBodyInfo, routeName) => {
|
|
580
592
|
if (responseBodyInfo.responses.length && responseBodyInfo.success && responseBodyInfo.success.schema) {
|
|
581
|
-
const typeName = this.
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
593
|
+
const typeName = this.schemaUtils.resolveTypeName(
|
|
594
|
+
routeName.usage,
|
|
595
|
+
this.config.extractingOptions.responseBodySuffix,
|
|
596
|
+
this.config.extractingOptions.responseBodyNameResolver,
|
|
597
|
+
);
|
|
586
598
|
|
|
587
599
|
const idx = responseBodyInfo.responses.indexOf(responseBodyInfo.success.schema);
|
|
588
600
|
|
|
@@ -605,14 +617,11 @@ class SchemaRoutes {
|
|
|
605
617
|
|
|
606
618
|
extractResponseErrorIfItNeeded = (routeInfo, responseBodyInfo, routeName) => {
|
|
607
619
|
if (responseBodyInfo.responses.length && responseBodyInfo.error.schemas && responseBodyInfo.error.schemas.length) {
|
|
608
|
-
const typeName = this.
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
pascalCase(`${routeName.usage} HttpError`),
|
|
614
|
-
pascalCase(`${routeName.usage} BadResponse`),
|
|
615
|
-
]);
|
|
620
|
+
const typeName = this.schemaUtils.resolveTypeName(
|
|
621
|
+
routeName.usage,
|
|
622
|
+
this.config.extractingOptions.responseErrorSuffix,
|
|
623
|
+
this.config.extractingOptions.responseErrorNameResolver,
|
|
624
|
+
);
|
|
616
625
|
|
|
617
626
|
const errorSchemas = responseBodyInfo.error.schemas.map(this.getSchemaFromRequestType).filter(Boolean);
|
|
618
627
|
|
|
@@ -762,13 +771,13 @@ class SchemaRoutes {
|
|
|
762
771
|
const pathType = routeParams.path.length ? this.schemaParser.getInlineParseContent(pathObjectSchema) : null;
|
|
763
772
|
const headersType = routeParams.header.length ? this.schemaParser.getInlineParseContent(headersObjectSchema) : null;
|
|
764
773
|
|
|
765
|
-
const nameResolver = new SpecificArgNameResolver(pathArgsNames);
|
|
774
|
+
const nameResolver = new SpecificArgNameResolver(this.logger, pathArgsNames);
|
|
766
775
|
|
|
767
776
|
const specificArgs = {
|
|
768
777
|
query: queryType
|
|
769
778
|
? {
|
|
770
779
|
name: nameResolver.resolve(RESERVED_QUERY_ARG_NAMES),
|
|
771
|
-
optional: this.schemaParser.parseSchema(queryObjectSchema
|
|
780
|
+
optional: this.schemaParser.parseSchema(queryObjectSchema).allFieldsAreOptional,
|
|
772
781
|
type: queryType,
|
|
773
782
|
}
|
|
774
783
|
: void 0,
|
|
@@ -782,14 +791,14 @@ class SchemaRoutes {
|
|
|
782
791
|
pathParams: pathType
|
|
783
792
|
? {
|
|
784
793
|
name: nameResolver.resolve(RESERVED_PATH_ARG_NAMES),
|
|
785
|
-
optional: this.schemaParser.parseSchema(pathObjectSchema
|
|
794
|
+
optional: this.schemaParser.parseSchema(pathObjectSchema).allFieldsAreOptional,
|
|
786
795
|
type: pathType,
|
|
787
796
|
}
|
|
788
797
|
: void 0,
|
|
789
798
|
headers: headersType
|
|
790
799
|
? {
|
|
791
800
|
name: nameResolver.resolve(RESERVED_HEADER_ARG_NAMES),
|
|
792
|
-
optional: this.schemaParser.parseSchema(headersObjectSchema
|
|
801
|
+
optional: this.schemaParser.parseSchema(headersObjectSchema).allFieldsAreOptional,
|
|
793
802
|
type: headersType,
|
|
794
803
|
}
|
|
795
804
|
: void 0,
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
const _ = require("lodash");
|
|
2
|
+
const { SCHEMA_TYPES } = require("../constants");
|
|
3
|
+
const { internalCase } = require("../util/internal-case");
|
|
4
|
+
const { pascalCase } = require("../util/pascal-case");
|
|
5
|
+
|
|
6
|
+
class SchemaUtils {
|
|
7
|
+
/**
|
|
8
|
+
* @type {CodeGenConfig}
|
|
9
|
+
*/
|
|
10
|
+
config;
|
|
11
|
+
/**
|
|
12
|
+
* @type {SchemaComponentsMap}
|
|
13
|
+
*/
|
|
14
|
+
schemaComponentsMap;
|
|
15
|
+
|
|
16
|
+
constructor(config, schemaComponentsMap) {
|
|
17
|
+
this.config = config;
|
|
18
|
+
this.schemaComponentsMap = schemaComponentsMap;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
getRequiredProperties = (schema) => {
|
|
22
|
+
return _.uniq((schema && _.isArray(schema.required) && schema.required) || []);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
isRefSchema = (schema) => {
|
|
26
|
+
return !!(schema && schema["$ref"]);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
getEnumNames = (schema) => {
|
|
30
|
+
return schema["x-enumNames"] || schema["xEnumNames"] || schema["x-enumnames"] || schema["x-enum-varnames"];
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
getSchemaRefType = (schema) => {
|
|
34
|
+
if (!this.isRefSchema(schema)) return null;
|
|
35
|
+
return this.schemaComponentsMap.get(schema.$ref);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
isPropertyRequired = (name, propertySchema, rootSchema) => {
|
|
39
|
+
if (propertySchema["x-omitempty"] === false) {
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const isRequired = _.isBoolean(propertySchema.required)
|
|
44
|
+
? !!propertySchema.required
|
|
45
|
+
: _.isArray(rootSchema.required)
|
|
46
|
+
? rootSchema.required.includes(name)
|
|
47
|
+
: !!rootSchema.required;
|
|
48
|
+
|
|
49
|
+
if (this.config.convertedFromSwagger2) {
|
|
50
|
+
return typeof propertySchema.nullable === this.config.Ts.Keyword.Undefined
|
|
51
|
+
? isRequired
|
|
52
|
+
: !propertySchema.nullable;
|
|
53
|
+
}
|
|
54
|
+
return isRequired;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
isNullMissingInType = (schema, type) => {
|
|
58
|
+
const { nullable, type: schemaType } = schema || {};
|
|
59
|
+
return (
|
|
60
|
+
(nullable || !!_.get(schema, "x-nullable") || schemaType === this.config.Ts.Keyword.Null) &&
|
|
61
|
+
_.isString(type) &&
|
|
62
|
+
!type.includes(` ${this.config.Ts.Keyword.Null}`) &&
|
|
63
|
+
!type.includes(`${this.config.Ts.Keyword.Null} `)
|
|
64
|
+
);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
safeAddNullToType = (schema, type) => {
|
|
68
|
+
if (this.isNullMissingInType(schema, type)) {
|
|
69
|
+
return this.config.Ts.UnionType([type, this.config.Ts.Keyword.Null]);
|
|
70
|
+
}
|
|
71
|
+
return type;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
getSchemaPrimitiveType = (rawSchema) => {
|
|
75
|
+
const schema = rawSchema || {};
|
|
76
|
+
|
|
77
|
+
if (schema.type) {
|
|
78
|
+
return internalCase(schema.type);
|
|
79
|
+
}
|
|
80
|
+
if (schema.enum) {
|
|
81
|
+
const enumFieldType = typeof schema.enum[0];
|
|
82
|
+
if (enumFieldType === this.config.Ts.Keyword.Undefined) return;
|
|
83
|
+
|
|
84
|
+
return internalCase(enumFieldType);
|
|
85
|
+
}
|
|
86
|
+
if (_.keys(schema.properties).length) {
|
|
87
|
+
return SCHEMA_TYPES.OBJECT;
|
|
88
|
+
}
|
|
89
|
+
if (!!schema.items) {
|
|
90
|
+
return SCHEMA_TYPES.ARRAY;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return null;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
checkAndAddRequiredKeys = (schema, resultType) => {
|
|
97
|
+
if ("$$requiredKeys" in schema && schema.$$requiredKeys.length) {
|
|
98
|
+
this.config.update({
|
|
99
|
+
internalTemplateOptions: {
|
|
100
|
+
addUtilRequiredKeysType: true,
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
return this.config.Ts.TypeWithGeneric(this.config.Ts.CodeGenKeyword.UtilRequiredKeys, [
|
|
104
|
+
resultType,
|
|
105
|
+
this.config.Ts.UnionType(schema.$$requiredKeys.map(this.config.Ts.StringValue)),
|
|
106
|
+
]);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return resultType;
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
makeAddRequiredToChildSchema = (parentSchema, childSchema) => {
|
|
113
|
+
if (!childSchema) return childSchema;
|
|
114
|
+
|
|
115
|
+
const required = _.uniq([...this.getRequiredProperties(parentSchema), ...this.getRequiredProperties(childSchema)]);
|
|
116
|
+
|
|
117
|
+
const refData = this.getSchemaRefType(childSchema);
|
|
118
|
+
|
|
119
|
+
if (refData) {
|
|
120
|
+
const refObjectProperties = _.keys((refData.rawTypeData && refData.rawTypeData.properties) || {});
|
|
121
|
+
const existedRequiredKeys = refObjectProperties.filter((key) => required.includes(key));
|
|
122
|
+
|
|
123
|
+
if (!existedRequiredKeys.length) return childSchema;
|
|
124
|
+
|
|
125
|
+
return {
|
|
126
|
+
...childSchema,
|
|
127
|
+
$$requiredKeys: existedRequiredKeys,
|
|
128
|
+
};
|
|
129
|
+
} else if (childSchema.properties) {
|
|
130
|
+
const childSchemaProperties = _.keys(childSchema.properties);
|
|
131
|
+
const existedRequiredKeys = childSchemaProperties.filter((key) => required.includes(key));
|
|
132
|
+
|
|
133
|
+
if (!existedRequiredKeys.length) return childSchema;
|
|
134
|
+
|
|
135
|
+
return {
|
|
136
|
+
required: _.uniq([...this.getRequiredProperties(childSchema), ...existedRequiredKeys]),
|
|
137
|
+
...childSchema,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return childSchema;
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
filterSchemaContents = (contents, filterFn) => {
|
|
145
|
+
return _.uniq(_.filter(contents, (type) => filterFn(type)));
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
resolveTypeName = (typeName, suffixes, resolver) => {
|
|
149
|
+
if (resolver) {
|
|
150
|
+
return this.config.componentTypeNameResolver.resolve((reserved) => {
|
|
151
|
+
const variant = resolver(pascalCase(typeName), reserved);
|
|
152
|
+
if (variant == null) return variant;
|
|
153
|
+
return pascalCase(variant);
|
|
154
|
+
});
|
|
155
|
+
} else {
|
|
156
|
+
return this.config.componentTypeNameResolver.resolve(
|
|
157
|
+
suffixes.map((suffix) => pascalCase(`${typeName} ${suffix}`)),
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
module.exports = {
|
|
164
|
+
SchemaUtils,
|
|
165
|
+
};
|
package/src/templates.js
CHANGED
|
@@ -164,8 +164,8 @@ class Templates {
|
|
|
164
164
|
{
|
|
165
165
|
async: false,
|
|
166
166
|
...(options || {}),
|
|
167
|
-
includeFile: (path,
|
|
168
|
-
return this.renderTemplate(this.getTemplateContent(path),
|
|
167
|
+
includeFile: (path, configuration, options) => {
|
|
168
|
+
return this.renderTemplate(this.getTemplateContent(path), configuration, options);
|
|
169
169
|
},
|
|
170
170
|
},
|
|
171
171
|
);
|
package/src/type-name.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
const _ = require("lodash");
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* @typedef {"enum-key" | "type-name"} FormattingSchemaType
|
|
5
|
+
*/
|
|
6
|
+
|
|
3
7
|
class TypeName {
|
|
4
8
|
/** @type {Map<string, string>} */
|
|
5
9
|
formattedModelNamesMap = new Map();
|
|
@@ -17,12 +21,20 @@ class TypeName {
|
|
|
17
21
|
|
|
18
22
|
/**
|
|
19
23
|
* @param name
|
|
20
|
-
* @param options {{
|
|
24
|
+
* @param options {{ type?: FormattingSchemaType }}
|
|
21
25
|
* @return {string}
|
|
22
26
|
*/
|
|
23
27
|
format = (name, options) => {
|
|
24
|
-
|
|
25
|
-
|
|
28
|
+
options = options || {};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @type {FormattingSchemaType}
|
|
32
|
+
*/
|
|
33
|
+
const schemaType = options.type || "type-name";
|
|
34
|
+
|
|
35
|
+
const typePrefix = schemaType === "enum-key" ? this.config.enumKeyPrefix : this.config.typePrefix;
|
|
36
|
+
const typeSuffix = schemaType === "enum-key" ? this.config.enumKeySuffix : this.config.typeSuffix;
|
|
37
|
+
|
|
26
38
|
const hashKey = `${typePrefix}_${name}_${typeSuffix}`;
|
|
27
39
|
|
|
28
40
|
if (typeof name !== "string") {
|
|
@@ -38,41 +50,48 @@ class TypeName {
|
|
|
38
50
|
return this.formattedModelNamesMap.get(hashKey);
|
|
39
51
|
}
|
|
40
52
|
|
|
41
|
-
const fixedModelName = fixModelName(name);
|
|
53
|
+
const fixedModelName = this.fixModelName(name, { type: schemaType });
|
|
42
54
|
|
|
43
|
-
const
|
|
44
|
-
const
|
|
55
|
+
const formattedName = _.replace(_.startCase(`${typePrefix}_${fixedModelName}_${typeSuffix}`), /\s/g, "");
|
|
56
|
+
const formattedResultName = this.config.hooks.onFormatTypeName(formattedName, name, schemaType) || formattedName;
|
|
45
57
|
|
|
46
|
-
this.formattedModelNamesMap.set(hashKey,
|
|
58
|
+
this.formattedModelNamesMap.set(hashKey, formattedResultName);
|
|
47
59
|
|
|
48
|
-
return
|
|
60
|
+
return formattedResultName;
|
|
49
61
|
};
|
|
50
62
|
|
|
51
|
-
isValidName =
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const isValidName = (name) => /^([A-Za-z$_]{1,})$/g.test(name);
|
|
63
|
+
isValidName = (name) => /^([A-Za-z$_]{1,})$/g.test(name);
|
|
55
64
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
65
|
+
/**
|
|
66
|
+
* @param name
|
|
67
|
+
* @param options {{ type?: FormattingSchemaType }}
|
|
68
|
+
* @return {string}
|
|
69
|
+
*/
|
|
70
|
+
fixModelName = (name, options) => {
|
|
71
|
+
if (!this.isValidName(name)) {
|
|
72
|
+
if (!/^[a-zA-Z_$]/g.test(name)) {
|
|
73
|
+
const fixPrefix =
|
|
74
|
+
options && options.type === "enum-key"
|
|
75
|
+
? this.config.fixInvalidEnumKeyPrefix
|
|
76
|
+
: this.config.fixInvalidTypeNamePrefix;
|
|
77
|
+
name = `${fixPrefix} ${name}`;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// specific replaces for TSOA 3.x
|
|
81
|
+
if (name.includes("."))
|
|
82
|
+
name = name
|
|
83
|
+
.replace(/Exclude_keyof[A-Za-z]{1,}/g, (match) => "ExcludeKeys")
|
|
84
|
+
.replace(/%22\~AND\~%22/g, "And")
|
|
85
|
+
.replace(/%22\~OR\~%22/g, "Or")
|
|
86
|
+
.replace(/(\.?%22)|\./g, "_")
|
|
87
|
+
.replace(/__+$/, "");
|
|
88
|
+
|
|
89
|
+
if (name.includes("-")) name = _.startCase(name).replace(/ /g, "");
|
|
60
90
|
}
|
|
61
91
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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
|
-
};
|
|
92
|
+
return name;
|
|
93
|
+
};
|
|
94
|
+
}
|
|
76
95
|
|
|
77
96
|
module.exports = {
|
|
78
97
|
TypeName,
|
package/src/util/logger.js
CHANGED
|
@@ -12,7 +12,7 @@ class Logger {
|
|
|
12
12
|
this.config = config;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
createLogMessage = ({ type, emojiName, messages }) => {
|
|
15
|
+
createLogMessage = ({ type, emojiName, messages, raw }) => {
|
|
16
16
|
if (this.config.silent) return;
|
|
17
17
|
|
|
18
18
|
const emoji = emojify(emojiName);
|
|
@@ -26,6 +26,11 @@ class Logger {
|
|
|
26
26
|
);
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
if (raw) {
|
|
30
|
+
console.log(...raw);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
29
34
|
console[type](
|
|
30
35
|
emoji,
|
|
31
36
|
" ",
|
|
@@ -93,6 +98,19 @@ class Logger {
|
|
|
93
98
|
emojiName: ":exclamation:",
|
|
94
99
|
messages,
|
|
95
100
|
});
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
*
|
|
104
|
+
* @param messages {any[]}
|
|
105
|
+
* @return {void}
|
|
106
|
+
*/
|
|
107
|
+
debug = (...messages) => {
|
|
108
|
+
if (!this.config.debug) return;
|
|
109
|
+
|
|
110
|
+
this.createLogMessage({
|
|
111
|
+
raw: messages,
|
|
112
|
+
});
|
|
113
|
+
};
|
|
96
114
|
}
|
|
97
115
|
|
|
98
116
|
module.exports = {
|
|
@@ -3,19 +3,24 @@ const { getRandomInt } = require("./random.js");
|
|
|
3
3
|
|
|
4
4
|
class NameResolver {
|
|
5
5
|
reservedNames = [];
|
|
6
|
-
|
|
6
|
+
getFallbackName = null;
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
9
|
+
* @type {Logger}
|
|
10
|
+
*/
|
|
11
|
+
logger;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @param {Logger} logger;
|
|
10
15
|
* @param {string[]} reservedNames
|
|
11
16
|
*/
|
|
12
|
-
constructor(reservedNames,
|
|
13
|
-
this.
|
|
17
|
+
constructor(logger, reservedNames, getFallbackName) {
|
|
18
|
+
this.logger = logger;
|
|
19
|
+
this.getFallbackName = getFallbackName;
|
|
14
20
|
this.reserve(reservedNames);
|
|
15
21
|
}
|
|
16
22
|
|
|
17
23
|
/**
|
|
18
|
-
*
|
|
19
24
|
* @param {string[]} names
|
|
20
25
|
*/
|
|
21
26
|
reserve(names) {
|
|
@@ -32,44 +37,59 @@ class NameResolver {
|
|
|
32
37
|
|
|
33
38
|
/**
|
|
34
39
|
*
|
|
35
|
-
* @param {string[]}
|
|
36
|
-
* @param {((variant: string) => string) | undefined} onSelectMutation
|
|
40
|
+
* @param {(string[]) | ((reserved: string[]) => string)} variantsOrResolver
|
|
37
41
|
* @returns {string | null}
|
|
38
42
|
*/
|
|
39
|
-
resolve(
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
43
|
+
resolve(variantsOrResolver) {
|
|
44
|
+
this.logger.debug("resolving name with using", variantsOrResolver);
|
|
45
|
+
if (Array.isArray(variantsOrResolver)) {
|
|
46
|
+
const variants = variantsOrResolver;
|
|
47
|
+
let usageName = null;
|
|
48
|
+
const uniqVariants = _.uniq(_.compact(variants));
|
|
49
|
+
|
|
50
|
+
_.forEach(uniqVariants, (variant) => {
|
|
51
|
+
if (!usageName && !this.isReserved(variant)) {
|
|
52
|
+
usageName = variant;
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
if (usageName) {
|
|
57
|
+
this.reserve([usageName]);
|
|
58
|
+
return usageName;
|
|
47
59
|
}
|
|
48
|
-
});
|
|
49
60
|
|
|
50
|
-
|
|
51
|
-
this.
|
|
52
|
-
|
|
53
|
-
|
|
61
|
+
this.logger.debug("trying to resolve name with using fallback name generator");
|
|
62
|
+
return this.resolve(this.getFallbackName);
|
|
63
|
+
} else if (typeof variantsOrResolver === "function") {
|
|
64
|
+
let usageName = null;
|
|
65
|
+
while (usageName === null) {
|
|
66
|
+
const variant = variantsOrResolver(this.reservedNames);
|
|
54
67
|
|
|
55
|
-
|
|
68
|
+
if (variant === undefined) {
|
|
69
|
+
this.logger.warn("unable to resolve name. current reserved names: ", this.reservedNames);
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
if (!this.isReserved(variant)) {
|
|
73
|
+
usageName = variant;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
56
76
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
return defaultName;
|
|
77
|
+
this.reserve([usageName]);
|
|
78
|
+
return usageName;
|
|
60
79
|
}
|
|
61
80
|
|
|
81
|
+
this.logger.debug("problem with reserving names. current reserved names: ", this.reservedNames);
|
|
62
82
|
return null;
|
|
63
83
|
}
|
|
64
84
|
}
|
|
65
85
|
|
|
66
86
|
class SpecificArgNameResolver extends NameResolver {
|
|
67
87
|
/**
|
|
68
|
-
*
|
|
88
|
+
* @param {Logger} logger;
|
|
69
89
|
* @param {string[]} reservedNames
|
|
70
90
|
*/
|
|
71
|
-
constructor(reservedNames) {
|
|
72
|
-
super(reservedNames, (variants) => {
|
|
91
|
+
constructor(logger, reservedNames) {
|
|
92
|
+
super(logger, reservedNames, (variants) => {
|
|
73
93
|
return (variants[0] && `${variants[0]}${getRandomInt(1, 10)}`) || `arg${getRandomInt(1, 10)}`;
|
|
74
94
|
});
|
|
75
95
|
}
|
|
@@ -77,18 +97,17 @@ class SpecificArgNameResolver extends NameResolver {
|
|
|
77
97
|
|
|
78
98
|
class ComponentTypeNameResolver extends NameResolver {
|
|
79
99
|
/**
|
|
80
|
-
*
|
|
100
|
+
* @param {Logger} logger;
|
|
81
101
|
* @param {string[]} reservedNames
|
|
82
102
|
*/
|
|
83
|
-
constructor(reservedNames) {
|
|
84
|
-
super(reservedNames, (variants) => {
|
|
103
|
+
constructor(logger, reservedNames) {
|
|
104
|
+
super(logger, reservedNames, (variants) => {
|
|
85
105
|
return (variants[0] && `${variants[0]}${getRandomInt(1, 10)}`) || `ComponentType${getRandomInt(1, 10)}`;
|
|
86
106
|
});
|
|
87
107
|
}
|
|
88
108
|
}
|
|
89
109
|
|
|
90
110
|
module.exports = {
|
|
91
|
-
NameResolver,
|
|
92
111
|
SpecificArgNameResolver,
|
|
93
112
|
ComponentTypeNameResolver,
|
|
94
113
|
};
|