UNPKG

10.6 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) {
126 function typesIsArray(types) {
127 return Array.isArray(types);
128 }
129 const nodes = [];
130 const itemCount = maxItems != null
131 ? maxItems
132 : Math.max(typesIsArray(types) ? types.length : 1, minItems !== null && minItems !== void 0 ? minItems : 0);
133 for (let i = 0; i < itemCount; i++) {
134 let node = typesIsArray(types)
135 ? i < types.length
136 ? types[i]
137 : buildAnyKeyword()
138 : types;
139 if (minItems == null || i >= minItems) {
140 node = ts.factory.createOptionalTypeNode(node);
141 }
142 nodes.push(node);
143 }
144 if (maxItems == null) {
145 nodes.push(ts.factory.createRestTypeNode(ts.factory.createArrayTypeNode(typesIsArray(types) ? buildAnyKeyword() : types)));
146 }
147 return ts.factory.createTupleTypeNode(nodes);
148}
149exports.buildTupleTypeNode = buildTupleTypeNode;
150function buildTypeReferenceNode(schema, currentSchema) {
151 const typeName = getTypename(schema.id, currentSchema);
152 if (typeName.length === 0) {
153 throw new Error('TypeName array must not be empty.');
154 }
155 let node = buildTypeNameIdentifier(typeName[0]);
156 for (let i = 1; i < typeName.length; i++) {
157 node = ts.factory.createQualifiedName(node, buildTypeNameIdentifier(typeName[i]));
158 }
159 return ts.factory.createTypeReferenceNode(node, undefined);
160}
161exports.buildTypeReferenceNode = buildTypeReferenceNode;
162function getTypename(id, baseSchema) {
163 const result = id.toNames();
164 const baseId = baseSchema.id;
165 if (baseId) {
166 const baseTypes = baseId.toNames().slice(0, -1);
167 for (const type of baseTypes) {
168 if (result.length === 1) {
169 break;
170 }
171 if (result[0] === type) {
172 result.shift();
173 }
174 else {
175 break;
176 }
177 }
178 }
179 return result;
180}
181function addComment(node, schema, terminate) {
182 const comments = getComment(schema);
183 if (comments.length === 0) {
184 return node;
185 }
186 else if (!terminate && comments.length === 1) {
187 return ts.addSyntheticLeadingComment(node, ts.SyntaxKind.MultiLineCommentTrivia, ` ${comments[0]} `, false);
188 }
189 else {
190 let result = '*\n';
191 for (const comment of comments) {
192 result += ' * ' + comment + '\n';
193 }
194 result += ' ';
195 return ts.addSyntheticLeadingComment(node, ts.SyntaxKind.MultiLineCommentTrivia, result, true);
196 }
197}
198exports.addComment = addComment;
199function getComment(schema) {
200 const content = schema.content;
201 let comments = [];
202 function protectComment(str) {
203 return str.replace(/\*\//g, '*\u200B/');
204 }
205 function appendComment(value) {
206 if (value == null) {
207 return;
208 }
209 const s = typeof value === 'string' ? value : JSON.stringify(value, null, 2);
210 const lines = s.split('\n').map((line) => protectComment(line));
211 comments = comments.concat(...lines);
212 }
213 if ('$comment' in content) {
214 appendComment(content.$comment);
215 }
216 appendComment(content.title);
217 appendComment(content.description);
218 if ('example' in content || 'examples' in content) {
219 appendComment('example:');
220 if ('example' in content) {
221 appendComment(content.example);
222 }
223 if ('examples' in content) {
224 if (content.examples) {
225 for (const e of content.examples) {
226 appendComment(e);
227 }
228 }
229 }
230 }
231 return comments;
232}
233function addOptionalInformation(node, schema, terminate) {
234 const format = schema.content.format;
235 const pattern = schema.content.pattern;
236 if (!format && !pattern) {
237 return node;
238 }
239 let comment = '';
240 if (format) {
241 comment += ' ' + format;
242 }
243 if (pattern) {
244 comment += ' ' + pattern;
245 }
246 if (!terminate) {
247 comment += ' ';
248 }
249 const kind = terminate
250 ? ts.SyntaxKind.SingleLineCommentTrivia
251 : ts.SyntaxKind.MultiLineCommentTrivia;
252 return ts.addSyntheticTrailingComment(node, kind, comment, false);
253}
254exports.addOptionalInformation = addOptionalInformation;
255function getLastTypeName(id) {
256 const names = id.toNames();
257 if (names.length > 0) {
258 return names[names.length - 1];
259 }
260 else {
261 return '';
262 }
263}