1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.addOptionalInformation = exports.addComment = exports.buildTypeReferenceNode = exports.buildTupleTypeNode = exports.buildIntersectionTypeNode = exports.buildUnionTypeNode = exports.buildFreeFormObjectTypeLiteralNode = exports.buildTypeLiteralNode = exports.buildIndexSignatureNode = exports.buildPropertySignature = exports.buildTypeAliasNode = exports.buildInterfaceNode = exports.buildNamespaceNode = exports.buildBooleanLiteralTypeNode = exports.buildNumericLiteralTypeNode = exports.buildStringLiteralTypeNode = exports.buildNullKeyword = exports.buildSimpleArrayNode = exports.buildStringKeyword = exports.buildVoidKeyword = exports.buildUnknownKeyword = exports.buildNeverKeyword = exports.buildAnyKeyword = exports.buildKeyword = void 0;
|
4 | const tslib_1 = require("tslib");
|
5 | const ts = tslib_1.__importStar(require("typescript"));
|
6 | const config_1 = tslib_1.__importDefault(require("./config"));
|
7 | const validateIdentifier_1 = require("./validateIdentifier");
|
8 | function buildTypeNameIdentifier(name) {
|
9 | return ts.factory.createIdentifier((0, validateIdentifier_1.toValidIdentifier)(name, config_1.default.target));
|
10 | }
|
11 | function buildPropertyNameIdentifier(name) {
|
12 | if ((0, validateIdentifier_1.checkInvalidCharacter)(name, config_1.default.target)) {
|
13 | return ts.factory.createIdentifier(name);
|
14 | }
|
15 | else {
|
16 | return ts.factory.createStringLiteral(name);
|
17 | }
|
18 | }
|
19 | function buildKeyword(kind) {
|
20 | return ts.factory.createKeywordTypeNode(kind);
|
21 | }
|
22 | exports.buildKeyword = buildKeyword;
|
23 | function buildAnyKeyword() {
|
24 | return buildKeyword(ts.SyntaxKind.AnyKeyword);
|
25 | }
|
26 | exports.buildAnyKeyword = buildAnyKeyword;
|
27 | function buildNeverKeyword() {
|
28 | return buildKeyword(ts.SyntaxKind.NeverKeyword);
|
29 | }
|
30 | exports.buildNeverKeyword = buildNeverKeyword;
|
31 | function buildUnknownKeyword() {
|
32 | return buildKeyword(ts.SyntaxKind.UnknownKeyword);
|
33 | }
|
34 | exports.buildUnknownKeyword = buildUnknownKeyword;
|
35 | function buildVoidKeyword() {
|
36 | return buildKeyword(ts.SyntaxKind.VoidKeyword);
|
37 | }
|
38 | exports.buildVoidKeyword = buildVoidKeyword;
|
39 | function buildStringKeyword() {
|
40 | return buildKeyword(ts.SyntaxKind.StringKeyword);
|
41 | }
|
42 | exports.buildStringKeyword = buildStringKeyword;
|
43 | function buildSimpleArrayNode(element) {
|
44 | return ts.factory.createArrayTypeNode(element);
|
45 | }
|
46 | exports.buildSimpleArrayNode = buildSimpleArrayNode;
|
47 | function buildNullKeyword() {
|
48 | return ts.factory.createLiteralTypeNode(ts.factory.createToken(ts.SyntaxKind.NullKeyword));
|
49 | }
|
50 | exports.buildNullKeyword = buildNullKeyword;
|
51 | function buildStringLiteralTypeNode(s) {
|
52 | return ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral(s));
|
53 | }
|
54 | exports.buildStringLiteralTypeNode = buildStringLiteralTypeNode;
|
55 | function buildNumericLiteralTypeNode(n) {
|
56 | if (!isNaN(parseFloat(n)) && parseFloat(n) < 0) {
|
57 | return ts.factory.createLiteralTypeNode(ts.factory.createPrefixUnaryExpression(ts.SyntaxKind.MinusToken, ts.factory.createNumericLiteral(Math.abs(parseFloat(n)))));
|
58 | }
|
59 | return ts.factory.createLiteralTypeNode(ts.factory.createNumericLiteral(n));
|
60 | }
|
61 | exports.buildNumericLiteralTypeNode = buildNumericLiteralTypeNode;
|
62 | function buildBooleanLiteralTypeNode(b) {
|
63 | return ts.factory.createLiteralTypeNode(b ? ts.factory.createTrue() : ts.factory.createFalse());
|
64 | }
|
65 | exports.buildBooleanLiteralTypeNode = buildBooleanLiteralTypeNode;
|
66 | function buildNamespaceNode(name, statements, root) {
|
67 | const modifiers = root
|
68 | ? [ts.factory.createModifier(ts.SyntaxKind.DeclareKeyword)]
|
69 | : undefined;
|
70 | return ts.factory.createModuleDeclaration(modifiers, buildTypeNameIdentifier(name), ts.factory.createModuleBlock(statements), ts.NodeFlags.Namespace |
|
71 | ts.NodeFlags.ExportContext |
|
72 | ts.NodeFlags.ContextFlags);
|
73 | }
|
74 | exports.buildNamespaceNode = buildNamespaceNode;
|
75 | function buildInterfaceNode(id, members, root) {
|
76 | const name = getLastTypeName(id);
|
77 | const modifiers = root
|
78 | ? [ts.factory.createModifier(ts.SyntaxKind.DeclareKeyword)]
|
79 | : [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)];
|
80 | return ts.factory.createInterfaceDeclaration(modifiers, buildTypeNameIdentifier(name), undefined, undefined, members);
|
81 | }
|
82 | exports.buildInterfaceNode = buildInterfaceNode;
|
83 | function buildTypeAliasNode(id, type, root) {
|
84 | const name = getLastTypeName(id);
|
85 | const modifiers = root
|
86 | ? [ts.factory.createModifier(ts.SyntaxKind.DeclareKeyword)]
|
87 | : [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)];
|
88 | return ts.factory.createTypeAliasDeclaration(modifiers, buildTypeNameIdentifier(name), undefined, type);
|
89 | }
|
90 | exports.buildTypeAliasNode = buildTypeAliasNode;
|
91 | function buildPropertySignature(_schema, propertyName, valueType, required, isPattern) {
|
92 | const modifiers = undefined;
|
93 | const questionToken = !(required === null || required === void 0 ? void 0 : required.includes(propertyName))
|
94 | ? ts.factory.createToken(ts.SyntaxKind.QuestionToken)
|
95 | : undefined;
|
96 | if (isPattern) {
|
97 | return ts.factory.createIndexSignature(modifiers, [
|
98 | ts.factory.createParameterDeclaration([], undefined, ts.factory.createIdentifier('pattern'), undefined, ts.factory.createTypeReferenceNode('string', []), undefined),
|
99 | ], valueType);
|
100 | }
|
101 | return ts.factory.createPropertySignature(modifiers, buildPropertyNameIdentifier(propertyName), questionToken, valueType);
|
102 | }
|
103 | exports.buildPropertySignature = buildPropertySignature;
|
104 | function buildIndexSignatureNode(name, indexType, valueType) {
|
105 | return ts.factory.createIndexSignature(undefined, [
|
106 | ts.factory.createParameterDeclaration(undefined, undefined, buildTypeNameIdentifier(name), undefined, indexType, undefined),
|
107 | ], valueType);
|
108 | }
|
109 | exports.buildIndexSignatureNode = buildIndexSignatureNode;
|
110 | function buildTypeLiteralNode(elements) {
|
111 | return ts.factory.createTypeLiteralNode(elements);
|
112 | }
|
113 | exports.buildTypeLiteralNode = buildTypeLiteralNode;
|
114 | function buildFreeFormObjectTypeLiteralNode() {
|
115 | return ts.factory.createTypeLiteralNode([
|
116 | buildIndexSignatureNode('key', buildStringKeyword(), buildAnyKeyword()),
|
117 | ]);
|
118 | }
|
119 | exports.buildFreeFormObjectTypeLiteralNode = buildFreeFormObjectTypeLiteralNode;
|
120 | function buildUnionTypeNode(types, builder, terminate) {
|
121 | const node = ts.factory.createUnionTypeNode(types.map(builder));
|
122 | if (terminate) {
|
123 | return node;
|
124 | }
|
125 | return ts.factory.createParenthesizedType(node);
|
126 | }
|
127 | exports.buildUnionTypeNode = buildUnionTypeNode;
|
128 | function buildIntersectionTypeNode(types, terminate) {
|
129 | const node = ts.factory.createIntersectionTypeNode(types);
|
130 | if (terminate) {
|
131 | return node;
|
132 | }
|
133 | return ts.factory.createParenthesizedType(node);
|
134 | }
|
135 | exports.buildIntersectionTypeNode = buildIntersectionTypeNode;
|
136 | function buildTupleTypeNode(types, minItems, maxItems, additionalItems) {
|
137 | function typesIsArray(types) {
|
138 | return Array.isArray(types);
|
139 | }
|
140 | const typesLength = typesIsArray(types) ? types.length : 1;
|
141 | const nodes = [];
|
142 | if (additionalItems === false && (minItems !== null && minItems !== void 0 ? minItems : 0) > typesLength) {
|
143 | return buildNeverKeyword();
|
144 | }
|
145 | const itemCount = maxItems != null
|
146 | ? additionalItems === false
|
147 | ? typesLength
|
148 | : maxItems
|
149 | : Math.max(typesLength, minItems !== null && minItems !== void 0 ? minItems : 0);
|
150 | for (let i = 0; i < itemCount; i++) {
|
151 | let node = typesIsArray(types)
|
152 | ? i < types.length
|
153 | ? types[i]
|
154 | : additionalItems !== undefined
|
155 | ? additionalItems === false
|
156 | ? buildNeverKeyword()
|
157 | : additionalItems
|
158 | : buildAnyKeyword()
|
159 | : types;
|
160 | if (minItems == null || i >= minItems) {
|
161 | node = ts.factory.createOptionalTypeNode(node);
|
162 | }
|
163 | nodes.push(node);
|
164 | }
|
165 | if (maxItems == null &&
|
166 | (!typesIsArray(types) || additionalItems !== false)) {
|
167 | nodes.push(ts.factory.createRestTypeNode(ts.factory.createArrayTypeNode(typesIsArray(types)
|
168 | ? additionalItems !== undefined
|
169 | ? additionalItems
|
170 | : buildAnyKeyword()
|
171 | : types)));
|
172 | }
|
173 | return ts.factory.createTupleTypeNode(nodes);
|
174 | }
|
175 | exports.buildTupleTypeNode = buildTupleTypeNode;
|
176 | function buildTypeReferenceNode(schema, currentSchema) {
|
177 | const typeName = getTypename(schema.id, currentSchema);
|
178 | let node;
|
179 | for (const name of typeName) {
|
180 | if (node == null) {
|
181 | node = buildTypeNameIdentifier(name);
|
182 | }
|
183 | else {
|
184 | node = ts.factory.createQualifiedName(node, buildTypeNameIdentifier(name));
|
185 | }
|
186 | }
|
187 | if (node == null) {
|
188 | throw new Error('TypeName array must not be empty.');
|
189 | }
|
190 | return ts.factory.createTypeReferenceNode(node, undefined);
|
191 | }
|
192 | exports.buildTypeReferenceNode = buildTypeReferenceNode;
|
193 | function getTypename(id, baseSchema) {
|
194 | const result = id.toNames();
|
195 | const baseId = baseSchema.id;
|
196 | const baseTypes = baseId.toNames().slice(0, -1);
|
197 | for (const type of baseTypes) {
|
198 | if (result.length === 1) {
|
199 | break;
|
200 | }
|
201 | if (result[0] === type) {
|
202 | result.shift();
|
203 | }
|
204 | else {
|
205 | break;
|
206 | }
|
207 | }
|
208 | return result;
|
209 | }
|
210 | function addComment(node, schema, terminate) {
|
211 | var _a;
|
212 | const comments = getComment(schema);
|
213 | if (comments.length === 0) {
|
214 | return node;
|
215 | }
|
216 | else if (!terminate && comments.length === 1) {
|
217 | return ts.addSyntheticLeadingComment(node, ts.SyntaxKind.MultiLineCommentTrivia, ` ${(_a = comments[0]) !== null && _a !== void 0 ? _a : ''} `, false);
|
218 | }
|
219 | else {
|
220 | let result = '*\n';
|
221 | for (const comment of comments) {
|
222 | result += ' * ' + comment + '\n';
|
223 | }
|
224 | result += ' ';
|
225 | return ts.addSyntheticLeadingComment(node, ts.SyntaxKind.MultiLineCommentTrivia, result, true);
|
226 | }
|
227 | }
|
228 | exports.addComment = addComment;
|
229 | function getComment(schema) {
|
230 | const content = schema.content;
|
231 | let comments = [];
|
232 | function protectComment(str) {
|
233 | return str.replace(/\*\//g, '*\u200B/');
|
234 | }
|
235 | function appendComment(value) {
|
236 | if (value == null) {
|
237 | return;
|
238 | }
|
239 | const s = typeof value === 'string' ? value : JSON.stringify(value, null, 2);
|
240 | const lines = s.split('\n').map((line) => protectComment(line));
|
241 | comments = comments.concat(...lines);
|
242 | }
|
243 | if ('$comment' in content) {
|
244 | appendComment(content.$comment);
|
245 | }
|
246 | appendComment(content.title);
|
247 | appendComment(content.description);
|
248 | if ('example' in content || 'examples' in content) {
|
249 | appendComment('example:');
|
250 | if ('example' in content) {
|
251 | appendComment(content.example);
|
252 | }
|
253 | if ('examples' in content) {
|
254 | if (content.examples) {
|
255 | for (const e of content.examples) {
|
256 | appendComment(e);
|
257 | }
|
258 | }
|
259 | }
|
260 | }
|
261 | return comments;
|
262 | }
|
263 | function addOptionalInformation(node, schema, terminate) {
|
264 | const format = schema.content.format;
|
265 | const pattern = schema.content.pattern;
|
266 | if (!format && !pattern) {
|
267 | return node;
|
268 | }
|
269 | let comment = '';
|
270 | if (format) {
|
271 | comment += ' ' + format;
|
272 | }
|
273 | if (pattern) {
|
274 | comment += ' ' + pattern;
|
275 | }
|
276 | if (!terminate) {
|
277 | comment += ' ';
|
278 | }
|
279 | const kind = terminate
|
280 | ? ts.SyntaxKind.SingleLineCommentTrivia
|
281 | : ts.SyntaxKind.MultiLineCommentTrivia;
|
282 | return ts.addSyntheticTrailingComment(node, kind, comment, false);
|
283 | }
|
284 | exports.addOptionalInformation = addOptionalInformation;
|
285 | function getLastTypeName(id) {
|
286 | var _a;
|
287 | const names = id.toNames();
|
288 | return (_a = names[names.length - 1]) !== null && _a !== void 0 ? _a : '';
|
289 | }
|