dtsgenerator
Version:
TypeScript d.ts file generator for JSON Schema file
290 lines (289 loc) • 11.9 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
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;
const tslib_1 = require("tslib");
const ts = tslib_1.__importStar(require("typescript"));
const config_1 = tslib_1.__importDefault(require("./config"));
const validateIdentifier_1 = require("./validateIdentifier");
function buildTypeNameIdentifier(name) {
return ts.factory.createIdentifier((0, validateIdentifier_1.toValidIdentifier)(name, config_1.default.target));
}
function buildPropertyNameIdentifier(name) {
if ((0, validateIdentifier_1.checkInvalidCharacter)(name, config_1.default.target)) {
return ts.factory.createIdentifier(name);
}
else {
return ts.factory.createStringLiteral(name);
}
}
function buildKeyword(kind) {
return ts.factory.createKeywordTypeNode(kind);
}
exports.buildKeyword = buildKeyword;
function buildAnyKeyword() {
return buildKeyword(ts.SyntaxKind.AnyKeyword);
}
exports.buildAnyKeyword = buildAnyKeyword;
function buildNeverKeyword() {
return buildKeyword(ts.SyntaxKind.NeverKeyword);
}
exports.buildNeverKeyword = buildNeverKeyword;
function buildUnknownKeyword() {
return buildKeyword(ts.SyntaxKind.UnknownKeyword);
}
exports.buildUnknownKeyword = buildUnknownKeyword;
function buildVoidKeyword() {
return buildKeyword(ts.SyntaxKind.VoidKeyword);
}
exports.buildVoidKeyword = buildVoidKeyword;
function buildStringKeyword() {
return buildKeyword(ts.SyntaxKind.StringKeyword);
}
exports.buildStringKeyword = buildStringKeyword;
function buildSimpleArrayNode(element) {
return ts.factory.createArrayTypeNode(element);
}
exports.buildSimpleArrayNode = buildSimpleArrayNode;
function buildNullKeyword() {
return ts.factory.createLiteralTypeNode(ts.factory.createToken(ts.SyntaxKind.NullKeyword));
}
exports.buildNullKeyword = buildNullKeyword;
function buildStringLiteralTypeNode(s) {
return ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral(s));
}
exports.buildStringLiteralTypeNode = buildStringLiteralTypeNode;
function buildNumericLiteralTypeNode(n) {
if (!isNaN(parseFloat(n)) && parseFloat(n) < 0) {
return ts.factory.createLiteralTypeNode(ts.factory.createPrefixUnaryExpression(ts.SyntaxKind.MinusToken, ts.factory.createNumericLiteral(Math.abs(parseFloat(n)))));
}
return ts.factory.createLiteralTypeNode(ts.factory.createNumericLiteral(n));
}
exports.buildNumericLiteralTypeNode = buildNumericLiteralTypeNode;
function buildBooleanLiteralTypeNode(b) {
return ts.factory.createLiteralTypeNode(b ? ts.factory.createTrue() : ts.factory.createFalse());
}
exports.buildBooleanLiteralTypeNode = buildBooleanLiteralTypeNode;
function buildNamespaceNode(name, statements, root) {
const modifiers = root
? [ts.factory.createModifier(ts.SyntaxKind.DeclareKeyword)]
: undefined;
return ts.factory.createModuleDeclaration(modifiers, buildTypeNameIdentifier(name), ts.factory.createModuleBlock(statements), ts.NodeFlags.Namespace |
ts.NodeFlags.ExportContext |
ts.NodeFlags.ContextFlags);
}
exports.buildNamespaceNode = buildNamespaceNode;
function buildInterfaceNode(id, members, root) {
const name = getLastTypeName(id);
const modifiers = root
? [ts.factory.createModifier(ts.SyntaxKind.DeclareKeyword)]
: [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)];
return ts.factory.createInterfaceDeclaration(modifiers, buildTypeNameIdentifier(name), undefined, undefined, members);
}
exports.buildInterfaceNode = buildInterfaceNode;
function buildTypeAliasNode(id, type, root) {
const name = getLastTypeName(id);
const modifiers = root
? [ts.factory.createModifier(ts.SyntaxKind.DeclareKeyword)]
: [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)];
return ts.factory.createTypeAliasDeclaration(modifiers, buildTypeNameIdentifier(name), undefined, type);
}
exports.buildTypeAliasNode = buildTypeAliasNode;
function buildPropertySignature(_schema, propertyName, valueType, required, isPattern) {
const modifiers = undefined;
const questionToken = !(required === null || required === void 0 ? void 0 : required.includes(propertyName))
? ts.factory.createToken(ts.SyntaxKind.QuestionToken)
: undefined;
if (isPattern) {
return ts.factory.createIndexSignature(modifiers, [
ts.factory.createParameterDeclaration([], undefined, ts.factory.createIdentifier('pattern'), undefined, ts.factory.createTypeReferenceNode('string', []), undefined),
], valueType);
}
return ts.factory.createPropertySignature(modifiers, buildPropertyNameIdentifier(propertyName), questionToken, valueType);
}
exports.buildPropertySignature = buildPropertySignature;
function buildIndexSignatureNode(name, indexType, valueType) {
return ts.factory.createIndexSignature(undefined, [
ts.factory.createParameterDeclaration(undefined, undefined, buildTypeNameIdentifier(name), undefined, indexType, undefined),
], valueType);
}
exports.buildIndexSignatureNode = buildIndexSignatureNode;
function buildTypeLiteralNode(elements) {
return ts.factory.createTypeLiteralNode(elements);
}
exports.buildTypeLiteralNode = buildTypeLiteralNode;
function buildFreeFormObjectTypeLiteralNode() {
return ts.factory.createTypeLiteralNode([
buildIndexSignatureNode('key', buildStringKeyword(), buildAnyKeyword()),
]);
}
exports.buildFreeFormObjectTypeLiteralNode = buildFreeFormObjectTypeLiteralNode;
function buildUnionTypeNode(types, builder, terminate) {
const node = ts.factory.createUnionTypeNode(types.map(builder));
if (terminate) {
return node;
}
return ts.factory.createParenthesizedType(node);
}
exports.buildUnionTypeNode = buildUnionTypeNode;
function buildIntersectionTypeNode(types, terminate) {
const node = ts.factory.createIntersectionTypeNode(types);
if (terminate) {
return node;
}
return ts.factory.createParenthesizedType(node);
}
exports.buildIntersectionTypeNode = buildIntersectionTypeNode;
function buildTupleTypeNode(types, minItems, maxItems, additionalItems) {
function typesIsArray(types) {
return Array.isArray(types);
}
const typesLength = typesIsArray(types) ? types.length : 1;
const nodes = [];
if (additionalItems === false && (minItems !== null && minItems !== void 0 ? minItems : 0) > typesLength) {
return buildNeverKeyword();
}
const itemCount = maxItems != null
? additionalItems === false
? typesLength
: maxItems
: Math.max(typesLength, minItems !== null && minItems !== void 0 ? minItems : 0);
for (let i = 0; i < itemCount; i++) {
let node = typesIsArray(types)
? i < types.length
? types[i]
: additionalItems !== undefined
? additionalItems === false
? buildNeverKeyword()
: additionalItems
: buildAnyKeyword()
: types;
if (minItems == null || i >= minItems) {
node = ts.factory.createOptionalTypeNode(node);
}
nodes.push(node);
}
if (maxItems == null &&
(!typesIsArray(types) || additionalItems !== false)) {
nodes.push(ts.factory.createRestTypeNode(ts.factory.createArrayTypeNode(typesIsArray(types)
? additionalItems !== undefined
? additionalItems
: buildAnyKeyword()
: types)));
}
return ts.factory.createTupleTypeNode(nodes);
}
exports.buildTupleTypeNode = buildTupleTypeNode;
function buildTypeReferenceNode(schema, currentSchema) {
const typeName = getTypename(schema.id, currentSchema);
let node;
for (const name of typeName) {
if (node == null) {
node = buildTypeNameIdentifier(name);
}
else {
node = ts.factory.createQualifiedName(node, buildTypeNameIdentifier(name));
}
}
if (node == null) {
throw new Error('TypeName array must not be empty.');
}
return ts.factory.createTypeReferenceNode(node, undefined);
}
exports.buildTypeReferenceNode = buildTypeReferenceNode;
function getTypename(id, baseSchema) {
const result = id.toNames();
const baseId = baseSchema.id;
const baseTypes = baseId.toNames().slice(0, -1);
for (const type of baseTypes) {
if (result.length === 1) {
break;
}
if (result[0] === type) {
result.shift();
}
else {
break;
}
}
return result;
}
function addComment(node, schema, terminate) {
var _a;
const comments = getComment(schema);
if (comments.length === 0) {
return node;
}
else if (!terminate && comments.length === 1) {
return ts.addSyntheticLeadingComment(node, ts.SyntaxKind.MultiLineCommentTrivia, ` ${(_a = comments[0]) !== null && _a !== void 0 ? _a : ''} `, false);
}
else {
let result = '*\n';
for (const comment of comments) {
result += ' * ' + comment + '\n';
}
result += ' ';
return ts.addSyntheticLeadingComment(node, ts.SyntaxKind.MultiLineCommentTrivia, result, true);
}
}
exports.addComment = addComment;
function getComment(schema) {
const content = schema.content;
let comments = [];
function protectComment(str) {
return str.replace(/\*\//g, '*\u200B/');
}
function appendComment(value) {
if (value == null) {
return;
}
const s = typeof value === 'string' ? value : JSON.stringify(value, null, 2);
const lines = s.split('\n').map((line) => protectComment(line));
comments = comments.concat(...lines);
}
if ('$comment' in content) {
appendComment(content.$comment);
}
appendComment(content.title);
appendComment(content.description);
if ('example' in content || 'examples' in content) {
appendComment('example:');
if ('example' in content) {
appendComment(content.example);
}
if ('examples' in content) {
if (content.examples) {
for (const e of content.examples) {
appendComment(e);
}
}
}
}
return comments;
}
function addOptionalInformation(node, schema, terminate) {
const format = schema.content.format;
const pattern = schema.content.pattern;
if (!format && !pattern) {
return node;
}
let comment = '';
if (format) {
comment += ' ' + format;
}
if (pattern) {
comment += ' ' + pattern;
}
if (!terminate) {
comment += ' ';
}
const kind = terminate
? ts.SyntaxKind.SingleLineCommentTrivia
: ts.SyntaxKind.MultiLineCommentTrivia;
return ts.addSyntheticTrailingComment(node, kind, comment, false);
}
exports.addOptionalInformation = addOptionalInformation;
function getLastTypeName(id) {
var _a;
const names = id.toNames();
return (_a = names[names.length - 1]) !== null && _a !== void 0 ? _a : '';
}
;