UNPKG

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