UNPKG

@jsonjoy.com/json-type

Version:

High-performance JSON Pointer implementation

307 lines 10.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.objToModule = exports.aliasToTs = void 0; exports.toTypeScriptAst = toTypeScriptAst; const classes_1 = require("../type/classes"); const augmentWithComment = (type, node) => { if (type.title || type.description) { let comment = ''; if (type.title) comment += '# ' + type.title; if (type.title && type.description) comment += '\n\n'; if (type.description) comment += type.description; node.comment = comment; } }; /** * Main router function that converts any Schema to TypeScript AST. * Uses a switch statement to route to the appropriate converter logic. */ function toTypeScriptAst(type) { const typeName = type.kind(); switch (typeName) { case 'any': { const node = { node: 'AnyKeyword' }; return node; } case 'bool': { const node = { node: 'BooleanKeyword' }; return node; } case 'con': { const constSchema = type.getSchema(); const value = constSchema.value; const valueType = typeof value; switch (valueType) { case 'boolean': { if (value === true) { const node = { node: 'TrueKeyword' }; return node; } else { const node = { node: 'FalseKeyword' }; return node; } } case 'string': { const node = { node: 'StringLiteral', text: value, }; return node; } case 'number': { const node = { node: 'NumericLiteral', text: String(value), }; return node; } case 'object': { if (value === null) { const node = { node: 'NullKeyword' }; return node; } // For complex objects, fallback to object keyword const node = { node: 'ObjectKeyword' }; return node; } } // Fallback for other value types const node = { node: 'ObjectKeyword' }; return node; } case 'num': { const node = { node: 'NumberKeyword' }; return node; } case 'str': { const node = { node: 'StringKeyword' }; return node; } case 'bin': { const node = { node: 'GenericTypeAnnotation', id: { node: 'Identifier', name: 'Uint8Array', }, }; return node; } case 'arr': { const arr = type; const { _head = [], _type, _tail = [] } = arr; if (_head.length || _tail.length) { const node = { node: 'TupleType', elements: [], }; for (const headType of _head) { node.elements.push(toTypeScriptAst(headType)); } if (_type) { const rest = { node: 'RestType', type: { node: 'ArrType', elementType: toTypeScriptAst(_type), }, }; node.elements.push(rest); } for (const tailType of _tail) { node.elements.push(toTypeScriptAst(tailType)); } return node; } const node = { node: 'ArrType', elementType: toTypeScriptAst(arr._type), }; return node; } case 'obj': { const obj = type; const objSchema = type.getSchema(); const node = { node: 'TypeLiteral', members: [], }; // Handle fields if (obj.keys && obj.keys.length > 0) { for (const field of obj.keys) { const member = { node: 'PropertySignature', name: field.key, type: toTypeScriptAst(field.val), }; if (field.optional === true) { member.optional = true; } // Add comment using the same logic as the original augmentWithComment const fieldSchema = field.schema; if (fieldSchema.title || fieldSchema.description) { let comment = ''; if (fieldSchema.title) comment += '# ' + fieldSchema.title; if (fieldSchema.title && fieldSchema.description) comment += '\n\n'; if (fieldSchema.description) comment += fieldSchema.description; member.comment = comment; } node.members.push(member); } } // Handle unknown/additional fields if (objSchema.decodeUnknownKeys || objSchema.encodeUnknownKeys) { node.members.push({ node: 'IndexSignature', type: { node: 'UnknownKeyword' }, }); } // Add comment to the type literal itself using the same logic as augmentWithComment augmentWithComment(objSchema, node); return node; } case 'map': { const map = type; const node = { node: 'TypeReference', typeName: 'Record', typeArguments: [{ node: 'StringKeyword' }, toTypeScriptAst(map._value)], }; return node; } case 'or': { const or = type; const node = { node: 'UnionType', types: or.types.map((type) => toTypeScriptAst(type)), }; return node; } case 'ref': { const refSchema = type.getSchema(); const node = { node: 'GenericTypeAnnotation', id: { node: 'Identifier', name: refSchema.ref, }, }; return node; } case 'fn': { const fn = type; const node = { node: 'FnType', parameters: [ { node: 'Parameter', name: { node: 'Identifier', name: 'request', }, type: toTypeScriptAst(fn.req), }, ], type: { node: 'TypeReference', typeName: { node: 'Identifier', name: 'Promise', }, typeArguments: [toTypeScriptAst(fn.res)], }, }; return node; } case 'fn$': { const fn = type; const node = { node: 'FnType', parameters: [ { node: 'Parameter', name: { node: 'Identifier', name: 'request$', }, type: { node: 'TypeReference', typeName: { node: 'Identifier', name: 'Observable', }, typeArguments: [toTypeScriptAst(fn.req)], }, }, ], type: { node: 'TypeReference', typeName: { node: 'Identifier', name: 'Observable', }, typeArguments: [toTypeScriptAst(fn.res)], }, }; return node; } default: { // Fallback for unknown types const node = { node: 'UnknownKeyword' }; return node; } } } const aliasToTs = (alias) => { const type = alias.type; if (type instanceof classes_1.ObjType) { const ast = toTypeScriptAst(type); const node = { node: 'InterfaceDeclaration', name: alias.id, members: ast.members, }; return node; } else { const node = { node: 'TypeAliasDeclaration', name: alias.id, type: toTypeScriptAst(type), }; // TODO: Figure out if this is still needed, and possibly bring it back. // augmentWithComment(type, node); return node; } }; exports.aliasToTs = aliasToTs; const objToModule = (obj) => { const node = { node: 'ModuleDeclaration', name: 'Router', export: true, statements: [ { node: 'TypeAliasDeclaration', name: 'Routes', type: toTypeScriptAst(obj), export: true, }, ], }; const system = obj.system; if (!system) throw new Error('system is undefined'); for (const alias of system.aliases.values()) node.statements.push({ ...(0, exports.aliasToTs)(alias.type), export: true }); return node; }; exports.objToModule = objToModule; //# sourceMappingURL=converter.js.map