@trapi/metadata 0.2.0 → 0.2.1

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 (147) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +10 -34
  3. package/dist/generator/controller.d.ts +2 -2
  4. package/dist/generator/controller.d.ts.map +1 -1
  5. package/dist/generator/controller.js.map +1 -1
  6. package/dist/generator/endpoint.d.ts +4 -5
  7. package/dist/generator/endpoint.d.ts.map +1 -1
  8. package/dist/generator/endpoint.js +6 -8
  9. package/dist/generator/endpoint.js.map +1 -1
  10. package/dist/generator/index.d.ts +1 -0
  11. package/dist/generator/index.d.ts.map +1 -1
  12. package/dist/generator/index.js +1 -0
  13. package/dist/generator/index.js.map +1 -1
  14. package/dist/generator/method.d.ts +2 -2
  15. package/dist/generator/method.d.ts.map +1 -1
  16. package/dist/generator/method.js +11 -13
  17. package/dist/generator/method.js.map +1 -1
  18. package/dist/generator/module.d.ts +6 -7
  19. package/dist/generator/module.d.ts.map +1 -1
  20. package/dist/generator/module.js +10 -8
  21. package/dist/generator/module.js.map +1 -1
  22. package/dist/generator/parameter.d.ts +2 -2
  23. package/dist/generator/parameter.d.ts.map +1 -1
  24. package/dist/generator/parameter.js +10 -7
  25. package/dist/generator/parameter.js.map +1 -1
  26. package/dist/generator/utils.d.ts +5 -0
  27. package/dist/generator/utils.d.ts.map +1 -0
  28. package/dist/generator/utils.js +18 -0
  29. package/dist/generator/utils.js.map +1 -0
  30. package/dist/index.d.ts +1 -2
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +1 -2
  33. package/dist/index.js.map +1 -1
  34. package/dist/module.d.ts +4 -0
  35. package/dist/module.d.ts.map +1 -0
  36. package/dist/module.js +16 -0
  37. package/dist/module.js.map +1 -0
  38. package/dist/type.d.ts +8 -23
  39. package/dist/type.d.ts.map +1 -1
  40. package/dist/utils/index.d.ts +3 -2
  41. package/dist/utils/index.d.ts.map +1 -1
  42. package/dist/utils/index.js +3 -2
  43. package/dist/utils/index.js.map +1 -1
  44. package/dist/utils/object.d.ts +2 -0
  45. package/dist/utils/object.d.ts.map +1 -0
  46. package/dist/utils/object.js +14 -0
  47. package/dist/utils/object.js.map +1 -0
  48. package/dist/utils/path.d.ts +2 -0
  49. package/dist/utils/path.d.ts.map +1 -0
  50. package/dist/utils/path.js +17 -0
  51. package/dist/utils/path.js.map +1 -0
  52. package/dist/utils/typescript.d.ts +8 -0
  53. package/dist/utils/typescript.d.ts.map +1 -0
  54. package/dist/utils/typescript.js +41 -0
  55. package/dist/utils/typescript.js.map +1 -0
  56. package/dist/utils/validator.d.ts.map +1 -1
  57. package/dist/utils/validator.js +2 -2
  58. package/dist/utils/validator.js.map +1 -1
  59. package/package.json +9 -8
  60. package/dist/decorator/functions.d.ts +0 -99
  61. package/dist/decorator/functions.d.ts.map +0 -1
  62. package/dist/decorator/functions.js +0 -140
  63. package/dist/decorator/functions.js.map +0 -1
  64. package/dist/decorator/index.d.ts +0 -7
  65. package/dist/decorator/index.d.ts.map +0 -1
  66. package/dist/decorator/index.js +0 -29
  67. package/dist/decorator/index.js.map +0 -1
  68. package/dist/decorator/mapper/index.d.ts +0 -25
  69. package/dist/decorator/mapper/index.d.ts.map +0 -1
  70. package/dist/decorator/mapper/index.js +0 -115
  71. package/dist/decorator/mapper/index.js.map +0 -1
  72. package/dist/decorator/mapper/maps/decorators-express.d.ts +0 -4
  73. package/dist/decorator/mapper/maps/decorators-express.d.ts.map +0 -1
  74. package/dist/decorator/mapper/maps/decorators-express.js +0 -115
  75. package/dist/decorator/mapper/maps/decorators-express.js.map +0 -1
  76. package/dist/decorator/mapper/maps/internal.d.ts +0 -4
  77. package/dist/decorator/mapper/maps/internal.d.ts.map +0 -1
  78. package/dist/decorator/mapper/maps/internal.js +0 -94
  79. package/dist/decorator/mapper/maps/internal.js.map +0 -1
  80. package/dist/decorator/mapper/maps/typescript-rest.d.ts +0 -4
  81. package/dist/decorator/mapper/maps/typescript-rest.d.ts.map +0 -1
  82. package/dist/decorator/mapper/maps/typescript-rest.js +0 -145
  83. package/dist/decorator/mapper/maps/typescript-rest.js.map +0 -1
  84. package/dist/decorator/mapper/utils.d.ts +0 -17
  85. package/dist/decorator/mapper/utils.d.ts.map +0 -1
  86. package/dist/decorator/mapper/utils.js +0 -73
  87. package/dist/decorator/mapper/utils.js.map +0 -1
  88. package/dist/decorator/representation/index.d.ts +0 -17
  89. package/dist/decorator/representation/index.d.ts.map +0 -1
  90. package/dist/decorator/representation/index.js +0 -61
  91. package/dist/decorator/representation/index.js.map +0 -1
  92. package/dist/decorator/representation/property/utils.d.ts +0 -6
  93. package/dist/decorator/representation/property/utils.d.ts.map +0 -1
  94. package/dist/decorator/representation/property/utils.js +0 -120
  95. package/dist/decorator/representation/property/utils.js.map +0 -1
  96. package/dist/decorator/type.d.ts +0 -178
  97. package/dist/decorator/type.d.ts.map +0 -1
  98. package/dist/decorator/type.js +0 -9
  99. package/dist/decorator/type.js.map +0 -1
  100. package/dist/decorator/utils/index.d.ts +0 -3
  101. package/dist/decorator/utils/index.d.ts.map +0 -1
  102. package/dist/decorator/utils/index.js +0 -25
  103. package/dist/decorator/utils/index.js.map +0 -1
  104. package/dist/decorator/utils/node.d.ts +0 -10
  105. package/dist/decorator/utils/node.d.ts.map +0 -1
  106. package/dist/decorator/utils/node.js +0 -49
  107. package/dist/decorator/utils/node.js.map +0 -1
  108. package/dist/decorator/utils/validator.d.ts +0 -4
  109. package/dist/decorator/utils/validator.d.ts.map +0 -1
  110. package/dist/decorator/utils/validator.js +0 -86
  111. package/dist/decorator/utils/validator.js.map +0 -1
  112. package/dist/resolver/error.d.ts +0 -7
  113. package/dist/resolver/error.d.ts.map +0 -1
  114. package/dist/resolver/error.js +0 -40
  115. package/dist/resolver/error.js.map +0 -1
  116. package/dist/resolver/index.d.ts +0 -5
  117. package/dist/resolver/index.d.ts.map +0 -1
  118. package/dist/resolver/index.js +0 -27
  119. package/dist/resolver/index.js.map +0 -1
  120. package/dist/resolver/type-node.d.ts +0 -53
  121. package/dist/resolver/type-node.d.ts.map +0 -1
  122. package/dist/resolver/type-node.js +0 -1045
  123. package/dist/resolver/type-node.js.map +0 -1
  124. package/dist/resolver/type.d.ts +0 -118
  125. package/dist/resolver/type.d.ts.map +0 -1
  126. package/dist/resolver/type.js +0 -57
  127. package/dist/resolver/type.js.map +0 -1
  128. package/dist/resolver/utils/index.d.ts +0 -3
  129. package/dist/resolver/utils/index.d.ts.map +0 -1
  130. package/dist/resolver/utils/index.js +0 -25
  131. package/dist/resolver/utils/index.js.map +0 -1
  132. package/dist/resolver/utils/initializer.d.ts +0 -5
  133. package/dist/resolver/utils/initializer.d.ts.map +0 -1
  134. package/dist/resolver/utils/initializer.js +0 -97
  135. package/dist/resolver/utils/initializer.js.map +0 -1
  136. package/dist/resolver/utils/validator.d.ts +0 -4
  137. package/dist/resolver/utils/validator.d.ts.map +0 -1
  138. package/dist/resolver/utils/validator.js +0 -131
  139. package/dist/resolver/utils/validator.js.map +0 -1
  140. package/dist/utils/generator.d.ts +0 -6
  141. package/dist/utils/generator.d.ts.map +0 -1
  142. package/dist/utils/generator.js +0 -33
  143. package/dist/utils/generator.js.map +0 -1
  144. package/dist/utils/js-doc.d.ts +0 -8
  145. package/dist/utils/js-doc.d.ts.map +0 -1
  146. package/dist/utils/js-doc.js +0 -102
  147. package/dist/utils/js-doc.js.map +0 -1
@@ -1,1045 +0,0 @@
1
- "use strict";
2
- /*
3
- * Copyright (c) 2021.
4
- * Author Peter Placzek (tada5hi)
5
- * For the full copyright and license information,
6
- * view the LICENSE file that was distributed with this source code.
7
- */
8
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
9
- if (k2 === undefined) k2 = k;
10
- var desc = Object.getOwnPropertyDescriptor(m, k);
11
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
12
- desc = { enumerable: true, get: function() { return m[k]; } };
13
- }
14
- Object.defineProperty(o, k2, desc);
15
- }) : (function(o, m, k, k2) {
16
- if (k2 === undefined) k2 = k;
17
- o[k2] = m[k];
18
- }));
19
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
20
- Object.defineProperty(o, "default", { enumerable: true, value: v });
21
- }) : function(o, v) {
22
- o["default"] = v;
23
- });
24
- var __importStar = (this && this.__importStar) || function (mod) {
25
- if (mod && mod.__esModule) return mod;
26
- var result = {};
27
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
28
- __setModuleDefault(result, mod);
29
- return result;
30
- };
31
- Object.defineProperty(exports, "__esModule", { value: true });
32
- exports.TypeNodeResolver = void 0;
33
- const ts = __importStar(require("typescript"));
34
- const metadata_utils_1 = require("@trapi/metadata-utils");
35
- const decorator_1 = require("../decorator");
36
- const utils_1 = require("../utils");
37
- const error_1 = require("./error");
38
- const utils_2 = require("./utils");
39
- const localReferenceTypeCache = {};
40
- const inProgressTypes = {};
41
- function getPropertyValidators(property) {
42
- return {};
43
- }
44
- class TypeNodeResolver {
45
- constructor(typeNode, current, parentNode, context = {}, referencer) {
46
- this.typeNode = typeNode;
47
- this.current = current;
48
- this.parentNode = parentNode;
49
- this.context = context;
50
- this.referencer = referencer;
51
- this.attemptToResolveKindToPrimitive = (syntaxKind) => {
52
- if (syntaxKind === ts.SyntaxKind.NumberKeyword) {
53
- return 'number';
54
- }
55
- if (syntaxKind === ts.SyntaxKind.StringKeyword) {
56
- return 'string';
57
- }
58
- if (syntaxKind === ts.SyntaxKind.BooleanKeyword) {
59
- return 'boolean';
60
- }
61
- if (syntaxKind === ts.SyntaxKind.VoidKeyword) {
62
- return 'void';
63
- }
64
- return undefined;
65
- };
66
- }
67
- static clearCache() {
68
- Object.keys(localReferenceTypeCache).forEach((key) => {
69
- delete localReferenceTypeCache[key];
70
- });
71
- Object.keys(inProgressTypes).forEach((key) => {
72
- delete inProgressTypes[key];
73
- });
74
- }
75
- resolve() {
76
- const primitiveType = this.getPrimitiveType(this.typeNode, this.parentNode);
77
- if (primitiveType) {
78
- return primitiveType;
79
- }
80
- if (this.typeNode.kind === ts.SyntaxKind.NullKeyword) {
81
- return {
82
- typeName: 'enum',
83
- members: [null],
84
- };
85
- }
86
- if (this.typeNode.kind === ts.SyntaxKind.ArrayType) {
87
- return {
88
- typeName: 'array',
89
- elementType: new TypeNodeResolver(this.typeNode.elementType, this.current, this.parentNode, this.context).resolve(),
90
- };
91
- }
92
- if (ts.isUnionTypeNode(this.typeNode)) {
93
- const types = this.typeNode.types.map((type) => new TypeNodeResolver(type, this.current, this.parentNode, this.context).resolve());
94
- return {
95
- typeName: 'union',
96
- members: types,
97
- };
98
- }
99
- if (ts.isIntersectionTypeNode(this.typeNode)) {
100
- const types = this.typeNode.types.map((type) => new TypeNodeResolver(type, this.current, this.parentNode, this.context).resolve());
101
- return {
102
- typeName: 'intersection',
103
- members: types,
104
- };
105
- }
106
- if (this.typeNode.kind === ts.SyntaxKind.AnyKeyword || this.typeNode.kind === ts.SyntaxKind.UnknownKeyword || this.typeNode.kind === ts.SyntaxKind.UndefinedKeyword) {
107
- return {
108
- typeName: 'any',
109
- };
110
- }
111
- if (ts.isLiteralTypeNode(this.typeNode)) {
112
- return {
113
- typeName: 'enum',
114
- members: [TypeNodeResolver.getLiteralValue(this.typeNode)],
115
- };
116
- }
117
- if (ts.isTypeLiteralNode(this.typeNode)) {
118
- const properties = this.typeNode.members
119
- .filter((member) => ts.isPropertySignature(member))
120
- .reduce((res, propertySignature) => {
121
- const type = new TypeNodeResolver(propertySignature.type, this.current, propertySignature, this.context).resolve();
122
- const property = {
123
- deprecated: (0, utils_1.isExistJSDocTag)(propertySignature, (tag) => tag.tagName.text === 'deprecated'),
124
- example: TypeNodeResolver.getNodeExample(propertySignature),
125
- default: (0, utils_1.getJSDocTagComment)(propertySignature, 'default'),
126
- description: this.getNodeDescription(propertySignature),
127
- format: TypeNodeResolver.getNodeFormat(propertySignature),
128
- name: propertySignature.name.text,
129
- required: !propertySignature.questionToken,
130
- type,
131
- validators: getPropertyValidators(propertySignature) || {},
132
- };
133
- return [property, ...res];
134
- }, []);
135
- const indexMember = this.typeNode.members.find((member) => ts.isIndexSignatureDeclaration(member));
136
- let additionalType;
137
- if (indexMember) {
138
- const indexSignatureDeclaration = indexMember;
139
- const indexType = new TypeNodeResolver(indexSignatureDeclaration.parameters[0].type, this.current, this.parentNode, this.context).resolve();
140
- if (indexType.typeName !== 'string') {
141
- throw new error_1.ResolverError('Only string indexes are supported.', this.typeNode);
142
- }
143
- additionalType = new TypeNodeResolver(indexSignatureDeclaration.type, this.current, this.parentNode, this.context).resolve();
144
- }
145
- return {
146
- additionalProperties: indexMember && additionalType,
147
- typeName: 'nestedObjectLiteral',
148
- properties,
149
- };
150
- }
151
- if (this.typeNode.kind === ts.SyntaxKind.ObjectKeyword || ts.isFunctionTypeNode(this.typeNode)) {
152
- return { typeName: 'object' };
153
- }
154
- if (ts.isMappedTypeNode(this.typeNode) && this.referencer) {
155
- const type = this.current.typeChecker.getTypeFromTypeNode(this.referencer);
156
- const mappedTypeNode = this.typeNode;
157
- const { typeChecker } = this.current;
158
- const getDeclaration = (prop) => prop.declarations && prop.declarations[0];
159
- const isIgnored = (prop) => {
160
- const declaration = getDeclaration(prop);
161
- return (prop.getJsDocTags().find((tag) => tag.name === 'ignore') !== undefined ||
162
- (declaration !== undefined && !ts.isPropertyDeclaration(declaration) && !ts.isPropertySignature(declaration) && !ts.isParameter(declaration)));
163
- };
164
- const properties = type
165
- .getProperties()
166
- // Ignore methods, getter, setter and @ignored props
167
- .filter((property) => isIgnored(property) === false)
168
- // Transform to property
169
- .map((property) => {
170
- const propertyType = typeChecker.getTypeOfSymbolAtLocation(property, this.typeNode);
171
- const declaration = getDeclaration(property);
172
- if (declaration && ts.isPropertySignature(declaration)) {
173
- return Object.assign(Object.assign({}, this.propertyFromSignature(declaration, mappedTypeNode.questionToken)), { name: property.getName() });
174
- }
175
- if (declaration && (ts.isPropertyDeclaration(declaration) || ts.isParameter(declaration))) {
176
- return Object.assign(Object.assign({}, this.propertyFromDeclaration(declaration, mappedTypeNode.questionToken)), { name: property.getName() });
177
- }
178
- // Resolve default value, required and typeNode
179
- let required = false;
180
- const typeNode = this.current.typeChecker.typeToTypeNode(propertyType, undefined, ts.NodeBuilderFlags.NoTruncation);
181
- if (mappedTypeNode.questionToken && mappedTypeNode.questionToken.kind === ts.SyntaxKind.MinusToken) {
182
- required = true;
183
- }
184
- else if (mappedTypeNode.questionToken && mappedTypeNode.questionToken.kind === ts.SyntaxKind.QuestionToken) {
185
- required = false;
186
- }
187
- // Push property
188
- return {
189
- name: property.getName(),
190
- required,
191
- deprecated: false,
192
- type: new TypeNodeResolver(typeNode, this.current, this.typeNode, this.context, this.referencer).resolve(),
193
- validators: {},
194
- };
195
- });
196
- return {
197
- typeName: 'nestedObjectLiteral',
198
- properties,
199
- };
200
- }
201
- if (ts.isConditionalTypeNode(this.typeNode) && this.referencer && ts.isTypeReferenceNode(this.referencer)) {
202
- const type = this.current.typeChecker.getTypeFromTypeNode(this.referencer);
203
- if (type.aliasSymbol) {
204
- let declaration = type.aliasSymbol.declarations[0];
205
- if (declaration.name) {
206
- declaration = this.getModelTypeDeclaration(declaration.name);
207
- }
208
- const name = TypeNodeResolver.getRefTypeName(this.referencer.getText());
209
- return this.handleCachingAndCircularReferences(name, () => {
210
- if (ts.isTypeAliasDeclaration(declaration)) {
211
- // Note: I don't understand why typescript lose type for `this.referencer` (from above with isTypeReferenceNode())
212
- return this.getTypeAliasReference(declaration, this.current.typeChecker.typeToString(type), this.referencer);
213
- }
214
- if (ts.isEnumDeclaration(declaration)) {
215
- return this.getEnumerateType(declaration.name);
216
- }
217
- throw new error_1.ResolverError(`Couldn't resolve Conditional to TypeNode. If you think this should be resolvable, please file an Issue. We found an aliasSymbol and it's declaration was of kind ${declaration.kind}`, this.typeNode);
218
- });
219
- }
220
- if (type.isClassOrInterface()) {
221
- let declaration = type.symbol.declarations[0];
222
- if (declaration.name) {
223
- declaration = this.getModelTypeDeclaration(declaration.name);
224
- }
225
- const name = TypeNodeResolver.getRefTypeName(this.referencer.getText());
226
- return this.handleCachingAndCircularReferences(name, () => this.getModelReference(declaration, this.current.typeChecker.typeToString(type)));
227
- }
228
- try {
229
- return new TypeNodeResolver(this.current.typeChecker.typeToTypeNode(type, undefined, ts.NodeBuilderFlags.NoTruncation), this.current, this.typeNode, this.context, this.referencer).resolve();
230
- }
231
- catch (_a) {
232
- throw new error_1.ResolverError(`Couldn't resolve Conditional to TypeNode. If you think this should be resolvable, please file an Issue. The flags on the result of the ConditionalType was ${type.flags}`, this.typeNode);
233
- }
234
- }
235
- if (ts.isTypeOperatorNode(this.typeNode) && this.typeNode.operator === ts.SyntaxKind.KeyOfKeyword) {
236
- const type = this.current.typeChecker.getTypeFromTypeNode(this.typeNode);
237
- try {
238
- return new TypeNodeResolver(this.current.typeChecker.typeToTypeNode(type, undefined, ts.NodeBuilderFlags.NoTruncation), this.current, this.typeNode, this.context, this.referencer).resolve();
239
- }
240
- catch (err) {
241
- const indexedTypeName = this.current.typeChecker.typeToString(this.current.typeChecker.getTypeFromTypeNode(this.typeNode.type));
242
- throw new error_1.ResolverError(`Could not determine the keys on ${indexedTypeName}`, this.typeNode);
243
- }
244
- }
245
- if (ts.isIndexedAccessTypeNode(this.typeNode) && (this.typeNode.indexType.kind === ts.SyntaxKind.NumberKeyword || this.typeNode.indexType.kind === ts.SyntaxKind.StringKeyword)) {
246
- const numberIndexType = this.typeNode.indexType.kind === ts.SyntaxKind.NumberKeyword;
247
- const objectType = this.current.typeChecker.getTypeFromTypeNode(this.typeNode.objectType);
248
- const type = numberIndexType ? objectType.getNumberIndexType() : objectType.getStringIndexType();
249
- if (type === undefined) {
250
- throw new error_1.ResolverError(`Could not determine ${numberIndexType ? 'number' : 'string'} index on ${this.current.typeChecker.typeToString(objectType)}`, this.typeNode);
251
- }
252
- return new TypeNodeResolver(this.current.typeChecker.typeToTypeNode(type, undefined, undefined), this.current, this.typeNode, this.context, this.referencer).resolve();
253
- }
254
- if (ts.isIndexedAccessTypeNode(this.typeNode) &&
255
- ts.isLiteralTypeNode(this.typeNode.indexType) &&
256
- (ts.isStringLiteral(this.typeNode.indexType.literal) || ts.isNumericLiteral(this.typeNode.indexType.literal))) {
257
- const hasType = (node) => node !== undefined && node.hasOwnProperty('type');
258
- const symbol = this.current.typeChecker.getPropertyOfType(this.current.typeChecker.getTypeFromTypeNode(this.typeNode.objectType), this.typeNode.indexType.literal.text);
259
- if (symbol === undefined) {
260
- throw new error_1.ResolverError(`Could not determine the keys on ${this.current.typeChecker.typeToString(this.current.typeChecker.getTypeFromTypeNode(this.typeNode.objectType))}`, this.typeNode);
261
- }
262
- if (hasType(symbol.valueDeclaration) && symbol.valueDeclaration.type) {
263
- return new TypeNodeResolver(symbol.valueDeclaration.type, this.current, this.typeNode, this.context, this.referencer).resolve();
264
- }
265
- const declaration = this.current.typeChecker.getTypeOfSymbolAtLocation(symbol, this.typeNode.objectType);
266
- try {
267
- return new TypeNodeResolver(this.current.typeChecker.typeToTypeNode(declaration, undefined, undefined), this.current, this.typeNode, this.context, this.referencer).resolve();
268
- }
269
- catch (_b) {
270
- throw new error_1.ResolverError(`Could not determine the keys on ${this.current.typeChecker.typeToString(this.current.typeChecker.getTypeFromTypeNode(this.current.typeChecker.typeToTypeNode(declaration, undefined, undefined)))}`, this.typeNode);
271
- }
272
- }
273
- // @ts-ignore
274
- if (this.typeNode.kind === ts.SyntaxKind.TemplateLiteralType) {
275
- const type = this.current.typeChecker.getTypeFromTypeNode(this.referencer || this.typeNode);
276
- if (type.isUnion() && type.types.every((unionElementType) => unionElementType.isStringLiteral())) {
277
- return {
278
- typeName: 'enum',
279
- members: type.types.map((stringLiteralType) => stringLiteralType.value),
280
- };
281
- }
282
- throw new error_1.ResolverError(`Could not the type of ${this.current.typeChecker.typeToString(this.current.typeChecker.getTypeFromTypeNode(this.typeNode), this.typeNode)}`, this.typeNode);
283
- }
284
- if (ts.isParenthesizedTypeNode(this.typeNode)) {
285
- return new TypeNodeResolver(this.typeNode.type, this.current, this.typeNode, this.context, this.referencer).resolve();
286
- }
287
- if (this.typeNode.kind !== ts.SyntaxKind.TypeReference) {
288
- throw new error_1.ResolverError(`Unknown type: ${ts.SyntaxKind[this.typeNode.kind]}`, this.typeNode);
289
- }
290
- const typeReference = this.typeNode;
291
- if (typeReference.typeName.kind === ts.SyntaxKind.Identifier) {
292
- // Special Utility Type
293
- if (typeReference.typeName.text === 'Record') {
294
- return {
295
- additionalProperties: new TypeNodeResolver(typeReference.typeArguments[1], this.current, this.parentNode, this.context).resolve(),
296
- typeName: 'nestedObjectLiteral',
297
- properties: [],
298
- };
299
- }
300
- const specialReference = TypeNodeResolver.resolveSpecialReference(typeReference.typeName);
301
- if (typeof specialReference !== 'undefined') {
302
- return specialReference;
303
- }
304
- if (typeReference.typeName.text === 'Date') {
305
- return this.getDateType(this.parentNode);
306
- }
307
- if (typeReference.typeName.text === 'Buffer' || typeReference.typeName.text === 'Readable') {
308
- return { typeName: 'buffer' };
309
- }
310
- if (typeReference.typeName.text === 'Array' && typeReference.typeArguments && typeReference.typeArguments.length >= 1) {
311
- return {
312
- typeName: 'array',
313
- elementType: new TypeNodeResolver(typeReference.typeArguments[0], this.current, this.parentNode, this.context).resolve(),
314
- };
315
- }
316
- if (typeReference.typeName.text === 'Promise' && typeReference.typeArguments && typeReference.typeArguments.length === 1) {
317
- return new TypeNodeResolver(typeReference.typeArguments[0], this.current, this.parentNode, this.context).resolve();
318
- }
319
- if (typeReference.typeName.text === 'String') {
320
- return { typeName: 'string' };
321
- }
322
- if (this.context[typeReference.typeName.text]) {
323
- return new TypeNodeResolver(this.context[typeReference.typeName.text], this.current, this.parentNode, this.context).resolve();
324
- }
325
- }
326
- const referenceType = this.getReferenceType(typeReference);
327
- this.current.addReferenceType(referenceType);
328
- return referenceType;
329
- }
330
- // ------------------------------------------------------------------------
331
- // Utility Type(s)
332
- // ------------------------------------------------------------------------
333
- static isSupportedUtilityType(typeName) {
334
- if (typeof typeName === 'undefined') {
335
- return false;
336
- }
337
- return ['NonNullable', 'Pick', 'Omit', 'Partial', 'Readonly', 'Record', 'Required'].indexOf(typeof typeName !== 'string' ? typeName.text : typeName) !== -1;
338
- }
339
- static getUtilityTypeOptions(typeArguments) {
340
- const utilityOptions = {
341
- keys: [],
342
- };
343
- if (typeArguments.length >= 2) {
344
- if (ts.isUnionTypeNode(typeArguments[1])) {
345
- const args = typeArguments[1].types;
346
- for (let i = 0; i < args.length; i++) {
347
- if (ts.isLiteralTypeNode(args[i])) {
348
- utilityOptions.keys.push(TypeNodeResolver.getLiteralValue(args[i]));
349
- }
350
- }
351
- }
352
- if (ts.isLiteralTypeNode(typeArguments[1])) {
353
- utilityOptions.keys.push(TypeNodeResolver.getLiteralValue(typeArguments[1]));
354
- }
355
- }
356
- return utilityOptions;
357
- }
358
- filterUtilityProperties(properties, utilityType, utilityOptions) {
359
- if (typeof utilityType === 'undefined' || typeof utilityOptions === 'undefined') {
360
- return properties;
361
- }
362
- return properties
363
- .filter((property) => {
364
- const name = typeof property.name !== 'string' ? property.name.text : property.name;
365
- switch (utilityType) {
366
- case 'Pick':
367
- return utilityOptions.keys.indexOf(name) !== -1;
368
- case 'Omit':
369
- return utilityOptions.keys.indexOf(name) === -1;
370
- }
371
- return true;
372
- })
373
- .map((property) => {
374
- if ((0, metadata_utils_1.hasOwnProperty)(property, 'required')) {
375
- switch (utilityType) {
376
- case 'Partial':
377
- property.required = false;
378
- break;
379
- case 'Required':
380
- case 'NonNullable':
381
- property.required = true;
382
- break;
383
- }
384
- }
385
- return property;
386
- });
387
- }
388
- static resolveSpecialReference(node) {
389
- switch (node.text) {
390
- case 'Buffer':
391
- case 'DownloadBinaryData':
392
- case 'DownloadResource':
393
- return { typeName: 'buffer' };
394
- default:
395
- return undefined;
396
- }
397
- }
398
- static getLiteralValue(typeNode) {
399
- let value;
400
- switch (typeNode.literal.kind) {
401
- case ts.SyntaxKind.TrueKeyword:
402
- value = true;
403
- break;
404
- case ts.SyntaxKind.FalseKeyword:
405
- value = false;
406
- break;
407
- case ts.SyntaxKind.StringLiteral:
408
- value = typeNode.literal.text;
409
- break;
410
- case ts.SyntaxKind.NumericLiteral:
411
- value = parseFloat(typeNode.literal.text);
412
- break;
413
- case ts.SyntaxKind.NullKeyword:
414
- value = null;
415
- break;
416
- default:
417
- if (typeNode.literal.hasOwnProperty('text')) {
418
- value = typeNode.literal.text;
419
- }
420
- else {
421
- throw new error_1.ResolverError(`Couldn't resolve literal node: ${typeNode.literal.getText()}`);
422
- }
423
- }
424
- return value;
425
- }
426
- getPrimitiveType(typeNode, parentNode) {
427
- if (!typeNode) {
428
- return {
429
- typeName: 'void',
430
- };
431
- }
432
- const resolvedType = this.attemptToResolveKindToPrimitive(typeNode.kind);
433
- if (typeof resolvedType === 'undefined') {
434
- return undefined;
435
- }
436
- if (resolvedType === 'number') {
437
- if (!parentNode) {
438
- return { typeName: 'double' };
439
- }
440
- const tags = (0, utils_1.getJSDocTagNames)(parentNode)
441
- .filter((name) => [
442
- 'isInt',
443
- 'isLong',
444
- 'isFloat',
445
- 'isDouble',
446
- ].some((m) => m.toLowerCase() === name.toLowerCase()))
447
- .map((name) => name.toLowerCase());
448
- const data = (0, decorator_1.getNodeDecorators)(parentNode, (identifier) => [
449
- 'isInt',
450
- 'isLong',
451
- 'isFloat',
452
- 'isDouble',
453
- ].some((m) => m.toLowerCase() === identifier.text.toLowerCase()));
454
- let decorator = data.length > 0 ? data[0].text : undefined;
455
- if (typeof decorator !== 'undefined') {
456
- decorator = decorator.toLowerCase();
457
- }
458
- if (!decorator && tags.length === 0) {
459
- return { typeName: 'double' };
460
- }
461
- switch (decorator || tags[0]) {
462
- case 'isint':
463
- return { typeName: 'integer' };
464
- case 'islong':
465
- return { typeName: 'long' };
466
- case 'isfloat':
467
- return { typeName: 'float' };
468
- case 'isdouble':
469
- return { typeName: 'double' };
470
- default:
471
- return { typeName: 'double' };
472
- }
473
- }
474
- else if (resolvedType === 'string') {
475
- return {
476
- typeName: 'string',
477
- };
478
- }
479
- else if (resolvedType === 'boolean') {
480
- return {
481
- typeName: 'boolean',
482
- };
483
- }
484
- else if (resolvedType === 'void') {
485
- return {
486
- typeName: 'void',
487
- };
488
- }
489
- else {
490
- // todo: should not occur
491
- return resolvedType;
492
- }
493
- }
494
- getDateType(parentNode) {
495
- if (!parentNode) {
496
- return { typeName: 'datetime' };
497
- }
498
- const tags = (0, utils_1.getJSDocTagNames)(parentNode).filter((name) => ['isDate', 'isDateTime'].some((m) => m === name));
499
- if (tags.length === 0) {
500
- return { typeName: 'datetime' };
501
- }
502
- switch (tags[0]) {
503
- case 'isDate':
504
- return { typeName: 'date' };
505
- case 'isDateTime':
506
- return { typeName: 'datetime' };
507
- default:
508
- return { typeName: 'datetime' };
509
- }
510
- }
511
- static getDesignatedModels(nodes, typeName) {
512
- return nodes;
513
- }
514
- getEnumerateType(typeName) {
515
- const enumName = typeName.text;
516
- let enumNodes = this.current.nodes.filter((node) => node.kind === ts.SyntaxKind.EnumDeclaration).filter((node) => node.name.text === enumName);
517
- if (!enumNodes.length) {
518
- return undefined;
519
- }
520
- enumNodes = TypeNodeResolver.getDesignatedModels(enumNodes, enumName);
521
- if (enumNodes.length > 1) {
522
- throw new error_1.ResolverError(`Multiple matching enum found for enum ${enumName}; please make enum names unique.`);
523
- }
524
- const enumDeclaration = enumNodes[0];
525
- const isNotUndefined = (item) => item !== undefined;
526
- const enums = enumDeclaration.members.map(this.current.typeChecker.getConstantValue.bind(this.current.typeChecker)).filter(isNotUndefined);
527
- const enumNames = enumDeclaration.members.map((e) => e.name.getText()).filter(isNotUndefined);
528
- return {
529
- typeName: 'refEnum',
530
- description: this.getNodeDescription(enumDeclaration),
531
- members: enums,
532
- memberNames: enumNames,
533
- refName: enumName,
534
- deprecated: (0, utils_1.isExistJSDocTag)(enumDeclaration, (tag) => tag.tagName.text === 'deprecated'),
535
- };
536
- }
537
- getReferenceType(node) {
538
- let type;
539
- if (ts.isTypeReferenceNode(node)) {
540
- type = node.typeName;
541
- }
542
- else if (ts.isExpressionWithTypeArguments(node)) {
543
- type = node.expression;
544
- }
545
- else {
546
- throw new error_1.ResolverError('Can\'t resolve Reference type.');
547
- }
548
- // Can't invoke getText on Synthetic Nodes
549
- let resolvableName = node.pos !== -1 ? node.getText() : type.text;
550
- if (node.pos === -1 && 'typeArguments' in node && Array.isArray(node.typeArguments)) {
551
- // Add typeArguments for Synthetic nodes (e.g. Record<> in TestClassModel.indexedResponse)
552
- const argumentsString = node.typeArguments
553
- .map((arg) => {
554
- if (ts.isLiteralTypeNode(arg)) {
555
- return `'${String(TypeNodeResolver.getLiteralValue(arg))}'`;
556
- }
557
- const resolvedType = this.attemptToResolveKindToPrimitive(arg.kind);
558
- if (typeof resolvedType === 'undefined') {
559
- return 'any';
560
- }
561
- return resolvedType;
562
- });
563
- resolvableName += `<${argumentsString.join(', ')}>`;
564
- }
565
- const name = this.contextualizedName(resolvableName);
566
- // Handle Utility Types
567
- const identifierName = type.text;
568
- const utilityTypeSupported = TypeNodeResolver.isSupportedUtilityType(identifierName);
569
- const utilityType = utilityTypeSupported ? identifierName : undefined;
570
- let utilityOptions = {
571
- keys: [],
572
- };
573
- if (utilityTypeSupported) {
574
- const { typeArguments } = type.parent;
575
- if (ts.isTypeReferenceNode(typeArguments[0])) {
576
- type = typeArguments[0].typeName;
577
- }
578
- else if (ts.isExpressionWithTypeArguments(typeArguments[0])) {
579
- type = typeArguments[0].expression;
580
- }
581
- else {
582
- throw new error_1.ResolverError('Can\'t resolve Reference type.');
583
- }
584
- utilityOptions = TypeNodeResolver.getUtilityTypeOptions(typeArguments);
585
- }
586
- else {
587
- this.typeArgumentsToContext(node, type, this.context);
588
- }
589
- try {
590
- const existingType = localReferenceTypeCache[name];
591
- if (existingType) {
592
- return existingType;
593
- }
594
- const refEnumType = this.getEnumerateType(type);
595
- if (refEnumType) {
596
- localReferenceTypeCache[name] = refEnumType;
597
- return refEnumType;
598
- }
599
- if (inProgressTypes[name]) {
600
- return this.createCircularDependencyResolver(name);
601
- }
602
- inProgressTypes[name] = true;
603
- const declaration = this.getModelTypeDeclaration(type);
604
- let referenceType;
605
- if (ts.isTypeAliasDeclaration(declaration)) {
606
- referenceType = this.getTypeAliasReference(declaration, name, node);
607
- }
608
- else if (ts.isEnumMember(declaration)) {
609
- referenceType = {
610
- typeName: 'refEnum',
611
- refName: TypeNodeResolver.getRefTypeName(name, utilityType),
612
- members: [this.current.typeChecker.getConstantValue(declaration)],
613
- // @ts-ignore
614
- memberNames: [declaration.name.getText()],
615
- deprecated: (0, utils_1.isExistJSDocTag)(declaration, (tag) => tag.tagName.text === 'deprecated'),
616
- };
617
- }
618
- else {
619
- referenceType = this.getModelReference(declaration, name, utilityType, utilityOptions);
620
- }
621
- localReferenceTypeCache[name] = referenceType;
622
- return referenceType;
623
- }
624
- catch (err) {
625
- // eslint-disable-next-line no-console
626
- console.error(`There was a problem resolving type of '${name}'.`);
627
- throw err;
628
- }
629
- }
630
- getTypeAliasReference(declaration, name, referencer) {
631
- const refName = TypeNodeResolver.getRefTypeName(name);
632
- let type;
633
- if (declaration.type.kind === ts.SyntaxKind.TypeReference) {
634
- const referenceType = this.getReferenceType(declaration.type);
635
- if (referenceType.refName === refName) {
636
- return referenceType;
637
- }
638
- }
639
- if (typeof type === 'undefined') {
640
- type = new TypeNodeResolver(declaration.type, this.current, declaration, this.context, this.referencer || referencer).resolve();
641
- }
642
- const example = TypeNodeResolver.getNodeExample(declaration);
643
- return Object.assign({ typeName: 'refAlias', default: (0, utils_1.getJSDocTagComment)(declaration, 'default'), description: this.getNodeDescription(declaration), refName, format: TypeNodeResolver.getNodeFormat(declaration), type, validators: getPropertyValidators(declaration) || {}, deprecated: (0, utils_1.isExistJSDocTag)(declaration, (tag) => tag.tagName.text === 'deprecated') }, (example && { example }));
644
- }
645
- getModelReference(modelType, name, utilityType, utilityOptions) {
646
- const example = TypeNodeResolver.getNodeExample(modelType);
647
- const description = this.getNodeDescription(modelType);
648
- const deprecated = (0, utils_1.isExistJSDocTag)(modelType, (tag) => tag.tagName.text === 'deprecated') || typeof this.current.decoratorMapper.match('DEPRECATED', modelType) !== 'undefined';
649
- // Handle toJSON methods
650
- if (!modelType.name) {
651
- throw new error_1.ResolverError('Can\'t get Symbol from anonymous class', modelType);
652
- }
653
- const type = this.current.typeChecker.getTypeAtLocation(modelType.name);
654
- const toJSON = this.current.typeChecker.getPropertyOfType(type, 'toJSON');
655
- if (toJSON && toJSON.valueDeclaration && (ts.isMethodDeclaration(toJSON.valueDeclaration) || ts.isMethodSignature(toJSON.valueDeclaration))) {
656
- let nodeType = toJSON.valueDeclaration.type;
657
- if (!nodeType) {
658
- const signature = this.current.typeChecker.getSignatureFromDeclaration(toJSON.valueDeclaration);
659
- const implicitType = this.current.typeChecker.getReturnTypeOfSignature(signature);
660
- nodeType = this.current.typeChecker.typeToTypeNode(implicitType, undefined, ts.NodeBuilderFlags.NoTruncation);
661
- }
662
- return Object.assign({ refName: `${TypeNodeResolver.getRefTypeName(name, utilityType)}Alias`, typeName: 'refAlias', description, type: new TypeNodeResolver(nodeType, this.current).resolve(), deprecated, validators: {} }, (example && { example }));
663
- }
664
- const properties = this.getModelProperties(modelType, undefined, utilityType, utilityOptions);
665
- const additionalProperties = this.getModelAdditionalProperties(modelType);
666
- const inheritedProperties = this.getModelInheritedProperties(modelType) || [];
667
- const referenceType = Object.assign({ additionalProperties, typeName: 'refObject', description, properties: this.filterUtilityProperties(inheritedProperties, utilityType, utilityOptions), refName: TypeNodeResolver.getRefTypeName(name, utilityType), deprecated }, (example && { example }));
668
- referenceType.properties = referenceType.properties.concat(properties);
669
- return referenceType;
670
- }
671
- static getRefTypeName(name, utilityType) {
672
- return encodeURIComponent(name
673
- .replace(/<|>/g, '_')
674
- .replace(/\s+/g, '')
675
- .replace(/,/g, '.')
676
- .replace(/\'([^']*)\'/g, '$1')
677
- .replace(/\"([^"]*)\"/g, '$1')
678
- .replace(/&/g, typeof utilityType !== 'undefined' ? '--' : '-and-')
679
- .replace(/\|/g, typeof utilityType !== 'undefined' ? '--' : '-or-')
680
- .replace(/\[\]/g, '-array')
681
- .replace(/{|}/g, '_') // SuccessResponse_{indexesCreated-number}_ -> SuccessResponse__indexesCreated-number__
682
- .replace(/([a-z]+):([a-z]+)/gi, '$1-$2') // SuccessResponse_indexesCreated:number_ -> SuccessResponse_indexesCreated-number_
683
- .replace(/;/g, '--')
684
- .replace(/([a-z]+)\[([a-z]+)\]/gi, '$1-at-$2') // Partial_SerializedDatasourceWithVersion[format]_ -> Partial_SerializedDatasourceWithVersion~format~_,
685
- .replace(/_/g, '')
686
- .replace(/-/g, ''));
687
- }
688
- contextualizedName(name) {
689
- return Object.entries(this.context).reduce((acc, [key, entry]) => acc
690
- .replace(new RegExp(`<\\s*([^>]*\\s)*\\s*(${key})(\\s[^>]*)*\\s*>`, 'g'), `<$1${entry.getText()}$3>`)
691
- .replace(new RegExp(`<\\s*([^,]*\\s)*\\s*(${key})(\\s[^,]*)*\\s*,`, 'g'), `<$1${entry.getText()}$3,`)
692
- .replace(new RegExp(`,\\s*([^>]*\\s)*\\s*(${key})(\\s[^>]*)*\\s*>`, 'g'), `,$1${entry.getText()}$3>`)
693
- .replace(new RegExp(`<\\s*([^<]*\\s)*\\s*(${key})(\\s[^<]*)*\\s*<`, 'g'), `<$1${entry.getText()}$3<`), name);
694
- }
695
- handleCachingAndCircularReferences(name, declarationResolver) {
696
- try {
697
- const existingType = localReferenceTypeCache[name];
698
- if (existingType) {
699
- return existingType;
700
- }
701
- if (inProgressTypes[name]) {
702
- return this.createCircularDependencyResolver(name);
703
- }
704
- inProgressTypes[name] = true;
705
- const reference = declarationResolver();
706
- localReferenceTypeCache[name] = reference;
707
- this.current.addReferenceType(reference);
708
- return reference;
709
- }
710
- catch (err) {
711
- // eslint-disable-next-line no-console
712
- console.error(`There was a problem resolving type of '${name}'.`);
713
- throw err;
714
- }
715
- }
716
- createCircularDependencyResolver(refName) {
717
- const referenceType = {
718
- typeName: 'refObject',
719
- refName,
720
- };
721
- this.current.registerDependencyResolver((referenceTypes) => {
722
- const realReferenceType = referenceTypes[refName];
723
- if (!realReferenceType) {
724
- return;
725
- }
726
- referenceType.description = realReferenceType.description;
727
- if (realReferenceType.typeName === 'refObject' && referenceType.typeName === 'refObject') {
728
- referenceType.properties = realReferenceType.properties;
729
- }
730
- referenceType.typeName = realReferenceType.typeName;
731
- referenceType.refName = realReferenceType.refName;
732
- });
733
- return referenceType;
734
- }
735
- static nodeIsUsable(node) {
736
- switch (node.kind) {
737
- case ts.SyntaxKind.InterfaceDeclaration:
738
- case ts.SyntaxKind.ClassDeclaration:
739
- case ts.SyntaxKind.TypeAliasDeclaration:
740
- case ts.SyntaxKind.EnumDeclaration:
741
- case ts.SyntaxKind.EnumMember:
742
- return true;
743
- default:
744
- return false;
745
- }
746
- }
747
- // @ts-ignore
748
- static resolveLeftmostIdentifier(type) {
749
- while (type.kind !== ts.SyntaxKind.Identifier) {
750
- type = type.left;
751
- }
752
- return type;
753
- }
754
- // @ts-ignore
755
- static resolveRightMostIdentifier(type) {
756
- while (type.kind !== ts.SyntaxKind.Identifier) {
757
- type = type.right;
758
- }
759
- return type;
760
- }
761
- findMatchingModuleOrEnumDeclaration(statements, name) {
762
- return statements.filter((node) => {
763
- if ((node.kind !== ts.SyntaxKind.ModuleDeclaration || !this.current.isExportedNode(node)) && !ts.isEnumDeclaration(node)) {
764
- return false;
765
- }
766
- const moduleDeclaration = node;
767
- return moduleDeclaration.name.text.toLowerCase() === name.toLowerCase();
768
- });
769
- }
770
- resolveModelTypeScope(leftmost, statements) {
771
- while (leftmost.parent && leftmost.parent.kind === ts.SyntaxKind.QualifiedName) {
772
- const leftmostName = leftmost.kind === ts.SyntaxKind.Identifier ? leftmost.text : leftmost.right.text;
773
- const moduleDeclarations = this.findMatchingModuleOrEnumDeclaration(statements, leftmostName);
774
- if (moduleDeclarations.length > 0) {
775
- statements = Array.prototype.concat(...moduleDeclarations.map((declaration) => {
776
- if (ts.isEnumDeclaration(declaration)) {
777
- return declaration.members;
778
- }
779
- if (!declaration.body || !ts.isModuleBlock(declaration.body)) {
780
- throw new error_1.ResolverError(`Module declaration found for ${leftmostName} has no body.`);
781
- }
782
- return declaration.body.statements;
783
- }));
784
- }
785
- leftmost = leftmost.parent;
786
- }
787
- return statements;
788
- }
789
- getModelTypeDeclaration(type) {
790
- const leftmostIdentifier = TypeNodeResolver.resolveLeftmostIdentifier(type);
791
- const statements = this.resolveModelTypeScope(leftmostIdentifier, this.current.nodes);
792
- const typeName = type.kind === ts.SyntaxKind.Identifier ? type.text : type.right.text;
793
- let modelTypes = statements.filter((node) => {
794
- var _a;
795
- if (!TypeNodeResolver.nodeIsUsable(node) || !this.current.isExportedNode(node)) {
796
- return false;
797
- }
798
- const modelTypeDeclaration = node;
799
- return ((_a = modelTypeDeclaration.name) === null || _a === void 0 ? void 0 : _a.text) === typeName;
800
- });
801
- if (!modelTypes.length) {
802
- throw new error_1.ResolverError(`No matching model found for referenced type ${typeName}. If ${typeName} comes from a dependency, please create an interface in your own code that has the same structure. The compiler can not utilize interfaces from external dependencies.`);
803
- }
804
- if (modelTypes.length > 1) {
805
- // remove types that are from typescript e.g. 'Account'
806
- modelTypes = modelTypes.filter((modelType) => modelType.getSourceFile().fileName.replace(/\\/g, '/').toLowerCase().indexOf('node_modules') <= -1);
807
- modelTypes = TypeNodeResolver.getDesignatedModels(modelTypes, typeName);
808
- }
809
- if (modelTypes.length > 1) {
810
- const conflicts = modelTypes.map((modelType) => modelType.getSourceFile().fileName).join('"; "');
811
- throw new error_1.ResolverError(`Multiple matching models found for referenced type ${typeName}; please make model names unique. Conflicts found: "${conflicts}".`);
812
- }
813
- return modelTypes[0];
814
- }
815
- getModelProperties(node, overrideToken, utilityType, utilityOptions) {
816
- const isIgnored = (e) => (0, utils_1.isExistJSDocTag)(e, (tag) => tag.tagName.text === 'ignore');
817
- // Interface model
818
- if (ts.isInterfaceDeclaration(node)) {
819
- return node.members.filter((member) => !isIgnored(member) && ts.isPropertySignature(member)).map((member) => this.propertyFromSignature(member, overrideToken));
820
- }
821
- // Class model
822
- let properties = node.members
823
- .filter((member) => !isIgnored(member))
824
- .filter((member) => member.kind === ts.SyntaxKind.PropertyDeclaration)
825
- .filter((member) => !this.hasStaticModifier(member))
826
- .filter((member) => this.hasPublicModifier(member));
827
- const classConstructor = node.members.find((member) => ts.isConstructorDeclaration(member));
828
- if (classConstructor && classConstructor.parameters) {
829
- const constructorProperties = classConstructor.parameters.filter((parameter) => this.isAccessibleParameter(parameter));
830
- properties.push(...constructorProperties);
831
- }
832
- properties = this.filterUtilityProperties(properties, utilityType, utilityOptions);
833
- return properties.map((property) => this.propertyFromDeclaration(property, overrideToken, utilityType));
834
- }
835
- propertyFromSignature(propertySignature, overrideToken) {
836
- const identifier = propertySignature.name;
837
- if (!propertySignature.type) {
838
- throw new error_1.ResolverError('No valid type found for property declaration.');
839
- }
840
- let required = !propertySignature.questionToken;
841
- if (overrideToken && overrideToken.kind === ts.SyntaxKind.MinusToken) {
842
- required = true;
843
- }
844
- else if (overrideToken && overrideToken.kind === ts.SyntaxKind.QuestionToken) {
845
- required = false;
846
- }
847
- const property = {
848
- deprecated: (0, utils_1.isExistJSDocTag)(propertySignature, (tag) => tag.tagName.text === 'deprecated'),
849
- default: (0, utils_1.getJSDocTagComment)(propertySignature, 'default'),
850
- description: this.getNodeDescription(propertySignature),
851
- example: TypeNodeResolver.getNodeExample(propertySignature),
852
- format: TypeNodeResolver.getNodeFormat(propertySignature),
853
- name: identifier.text,
854
- required,
855
- type: new TypeNodeResolver(propertySignature.type, this.current, propertySignature.type.parent, this.context, propertySignature.type).resolve(),
856
- validators: getPropertyValidators(propertySignature) || {},
857
- };
858
- return property;
859
- }
860
- propertyFromDeclaration(propertyDeclaration, overrideToken, utilityType) {
861
- const identifier = propertyDeclaration.name;
862
- let typeNode = propertyDeclaration.type;
863
- if (!typeNode) {
864
- const tsType = this.current.typeChecker.getTypeAtLocation(propertyDeclaration);
865
- typeNode = this.current.typeChecker.typeToTypeNode(tsType, undefined, ts.NodeBuilderFlags.NoTruncation);
866
- }
867
- if (!typeNode) {
868
- throw new error_1.ResolverError('No valid type found for property declaration.');
869
- }
870
- const type = new TypeNodeResolver(typeNode, this.current, propertyDeclaration, this.context, typeNode).resolve();
871
- let required = !propertyDeclaration.questionToken && !propertyDeclaration.initializer;
872
- if (overrideToken && overrideToken.kind === ts.SyntaxKind.MinusToken) {
873
- required = true;
874
- }
875
- else if (overrideToken && overrideToken.kind === ts.SyntaxKind.QuestionToken) {
876
- required = false;
877
- }
878
- if (typeof utilityType !== 'undefined') {
879
- if (utilityType === 'Partial') {
880
- required = false;
881
- }
882
- if (utilityType === 'Required') {
883
- required = true;
884
- }
885
- }
886
- const property = {
887
- deprecated: (0, utils_1.isExistJSDocTag)(propertyDeclaration, (tag) => tag.tagName.text === 'deprecated'),
888
- default: (0, utils_2.getInitializerValue)(propertyDeclaration.initializer, this.current.typeChecker),
889
- description: this.getNodeDescription(propertyDeclaration),
890
- example: TypeNodeResolver.getNodeExample(propertyDeclaration),
891
- format: TypeNodeResolver.getNodeFormat(propertyDeclaration),
892
- name: identifier.text,
893
- required,
894
- type,
895
- validators: getPropertyValidators(propertyDeclaration) || {},
896
- };
897
- return property;
898
- }
899
- getModelAdditionalProperties(node) {
900
- if (node.kind === ts.SyntaxKind.InterfaceDeclaration) {
901
- const indexMember = node.members.find((member) => member.kind === ts.SyntaxKind.IndexSignature);
902
- if (!indexMember) {
903
- return undefined;
904
- }
905
- const indexSignatureDeclaration = indexMember;
906
- const indexType = new TypeNodeResolver(indexSignatureDeclaration.parameters[0].type, this.current, this.parentNode, this.context).resolve();
907
- if (indexType.typeName !== 'string') {
908
- throw new error_1.ResolverError('Only string indexers are supported.', this.typeNode);
909
- }
910
- return new TypeNodeResolver(indexSignatureDeclaration.type, this.current, this.parentNode, this.context).resolve();
911
- }
912
- return undefined;
913
- }
914
- typeArgumentsToContext(type, targetEntity, context) {
915
- // this.context = {};
916
- const declaration = this.getModelTypeDeclaration(targetEntity);
917
- const typeParameters = 'typeParameters' in declaration ? declaration.typeParameters : undefined;
918
- if (typeParameters) {
919
- for (let index = 0; index < typeParameters.length; index++) {
920
- const typeParameter = typeParameters[index];
921
- const typeArg = type.typeArguments && type.typeArguments[index];
922
- let resolvedType;
923
- // Argument may be a forward reference from context
924
- if (typeArg && ts.isTypeReferenceNode(typeArg) && ts.isIdentifier(typeArg.typeName) && context[typeArg.typeName.text]) {
925
- resolvedType = context[typeArg.typeName.text];
926
- }
927
- else if (typeArg) {
928
- resolvedType = typeArg;
929
- }
930
- else if (typeParameter.default) {
931
- resolvedType = typeParameter.default;
932
- }
933
- else {
934
- throw new error_1.ResolverError(`Could not find a value for type parameter ${typeParameter.name.text}`, type);
935
- }
936
- this.context = Object.assign(Object.assign({}, this.context), { [typeParameter.name.text]: resolvedType });
937
- }
938
- }
939
- return context;
940
- }
941
- getModelInheritedProperties(modelTypeDeclaration) {
942
- let properties = [];
943
- const { heritageClauses } = modelTypeDeclaration;
944
- if (!heritageClauses) {
945
- return properties;
946
- }
947
- heritageClauses.forEach((clause) => {
948
- if (!clause.types) {
949
- return;
950
- }
951
- clause.types.forEach((t) => {
952
- const baseEntityName = t.expression;
953
- // create subContext
954
- const resetCtx = this.typeArgumentsToContext(t, baseEntityName, this.context);
955
- const referenceType = this.getReferenceType(t);
956
- if (referenceType) {
957
- if (referenceType.typeName === 'refEnum') {
958
- // since it doesn't have properties to iterate over, then we don't do anything with it
959
- }
960
- else if (referenceType.typeName === 'refAlias') {
961
- let type = referenceType;
962
- while (type.typeName === 'refAlias') {
963
- type = type.type;
964
- }
965
- if (type.typeName === 'refObject') {
966
- properties = [...properties, ...type.properties];
967
- }
968
- else if (type.typeName === 'nestedObjectLiteral') {
969
- properties = [...properties, ...type.properties];
970
- }
971
- }
972
- else if (referenceType.typeName === 'refObject') {
973
- referenceType.properties.forEach((property) => properties.push(property));
974
- }
975
- else {
976
- // todo: should never assert
977
- }
978
- }
979
- // reset subContext
980
- this.context = resetCtx;
981
- });
982
- });
983
- return properties;
984
- }
985
- hasPublicModifier(node) {
986
- return (!node.modifiers ||
987
- node.modifiers.every((modifier) => modifier.kind !== ts.SyntaxKind.ProtectedKeyword && modifier.kind !== ts.SyntaxKind.PrivateKeyword));
988
- }
989
- hasStaticModifier(node) {
990
- return (node.modifiers &&
991
- node.modifiers.some((modifier) => modifier.kind === ts.SyntaxKind.StaticKeyword));
992
- }
993
- isAccessibleParameter(node) {
994
- // No modifiers
995
- if (!node.modifiers) {
996
- return false;
997
- }
998
- // public || public readonly
999
- if (node.modifiers.some((modifier) => modifier.kind === ts.SyntaxKind.PublicKeyword)) {
1000
- return true;
1001
- }
1002
- // readonly, not private readonly, not public readonly
1003
- const isReadonly = node.modifiers.some((modifier) => modifier.kind === ts.SyntaxKind.ReadonlyKeyword);
1004
- const isProtectedOrPrivate = node.modifiers.some((modifier) => modifier.kind === ts.SyntaxKind.ProtectedKeyword || modifier.kind === ts.SyntaxKind.PrivateKeyword);
1005
- return isReadonly && !isProtectedOrPrivate;
1006
- }
1007
- getNodeDescription(node) {
1008
- const symbol = this.current.typeChecker.getSymbolAtLocation(node.name);
1009
- if (!symbol) {
1010
- return undefined;
1011
- }
1012
- /**
1013
- * TODO: Workaround for what seems like a bug in the compiler
1014
- * Warrants more investigation and possibly a PR against typescript
1015
- */
1016
- if (node.kind === ts.SyntaxKind.Parameter) {
1017
- // TypeScript won't parse jsdoc if the flag is 4, i.e. 'Property'
1018
- symbol.flags = 0;
1019
- }
1020
- const comments = symbol.getDocumentationComment(this.current.typeChecker);
1021
- if (comments.length) {
1022
- return ts.displayPartsToString(comments);
1023
- }
1024
- return undefined;
1025
- }
1026
- static getNodeFormat(node) {
1027
- return (0, utils_1.getJSDocTagComment)(node, 'format');
1028
- }
1029
- static getNodeExample(node) {
1030
- const example = (0, utils_1.getJSDocTagComment)(node, 'example');
1031
- if (example) {
1032
- try {
1033
- return JSON.parse(example);
1034
- }
1035
- catch (_a) {
1036
- return undefined;
1037
- }
1038
- }
1039
- else {
1040
- return undefined;
1041
- }
1042
- }
1043
- }
1044
- exports.TypeNodeResolver = TypeNodeResolver;
1045
- //# sourceMappingURL=type-node.js.map