UNPKG

@cosmology/ast

Version:
478 lines (477 loc) 17.8 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getDefaultTSTypeFromAminoTypeDefault = exports.getDefaultTSTypeFromProtoType = exports.getTSTypeForProto = exports.getTSTypeForAmino = exports.getTSTypeFromGoogleType = exports.getTSAminoType = exports.getTSType = exports.getFieldAminoTypeReference = exports.getFieldTypeReference = exports.SymbolNames = exports.getFieldNames = void 0; const t = __importStar(require("@babel/types")); const types_1 = require("@cosmology/types"); const utils_1 = require("../utils"); const proto_1 = require("./proto"); const getFieldNames = (field) => { const propName = field.options?.['(telescope:name)'] ?? field.name; const origName = field.options?.['(telescope:orig)'] ?? field.name; return { propName, origName }; }; exports.getFieldNames = getFieldNames; const getSymbolName = (name, type = 'Msg') => { let typeNameSuffix; switch (type) { case 'ProtoMsg': typeNameSuffix = 'ProtoMsg'; break; case 'AminoMsg': typeNameSuffix = 'AminoMsg'; break; case 'Amino': typeNameSuffix = 'Amino'; break; case 'SDKType': typeNameSuffix = 'SDKType'; break; case 'Encoded': typeNameSuffix = 'Encoded'; break; case 'Msg': default: } return [name, typeNameSuffix].filter(Boolean).join(''); }; exports.SymbolNames = { Msg: (name) => getSymbolName(name, 'Msg'), SDKType: (name) => getSymbolName(name, 'SDKType'), ProtoMsg: (name) => getSymbolName(name, 'ProtoMsg'), AminoMsg: (name) => getSymbolName(name, 'AminoMsg'), Amino: (name) => getSymbolName(name, 'Amino'), Encoded: (name) => getSymbolName(name, 'Encoded'), }; const getFieldTypeReference = (context, field, type = 'Msg') => { let ast = null; let typ = null; if (proto_1.SCALAR_TYPES.includes(field.type)) { // return on scalar typ = (0, exports.getTSTypeForProto)(context, field); return { ast: typ }; } else if (proto_1.GOOGLE_TYPES.includes(field.type)) { typ = (0, exports.getTSTypeFromGoogleType)(context, field.type, type); } else { const propName = (0, utils_1.getProtoFieldTypeName)(context, field); const MsgName = field.parsedType?.type === 'Enum' ? propName : exports.SymbolNames[type](propName); typ = t.tsTypeReference(t.identifier(MsgName)); } const implementsAcceptsAny = context.pluginValue('interfaces.enabled'); const lookupInterface = field.options?.['(cosmos_proto.accepts_interface)']; const isAnyType = field.parsedType?.type === 'Type' && field.parsedType?.name === 'Any'; const isArray = field.rule === 'repeated'; const isBaseType = type === 'Msg'; const isEncodedType = type === 'ProtoMsg'; const isSDKType = type === 'SDKType'; // MARKED AS NOT DRY (symbols) let symbols = null; if (implementsAcceptsAny && lookupInterface) { symbols = context.store._symbols.filter(s => s.implementsType === lookupInterface && s.ref === context.ref.filename); if (!symbols.length && context.options.logLevel >= types_1.TelescopeLogLevel.Warn) { console.warn(`[WARN] ${lookupInterface} is accepted but not implemented`); } } if (!isBaseType) { if (['ProtoMsg', 'SDKType'].includes(type)) { symbols?.forEach(s => { context.addImportDerivative({ type, symbol: s }); }); } // main type could be Any if (['SDKType'].includes(type) && // no derivatives for Enums! field.parsedType.type === 'Type') { context.addImportDerivative({ type, symbol: { ref: context.ref.filename, readAs: field.parsedType.name, source: field.import, symbolName: field.parsedType.name, type: 'import' }, }); } } // cast Any types! const isAnyInterface = isAnyType && lookupInterface && implementsAcceptsAny && symbols; const isTypeCastable = isAnyInterface && isBaseType; const isProtoTypeCastable = isAnyInterface && isEncodedType; const isSDKTypeCastable = isAnyInterface && isSDKType; const isNonArrayNullableType = field.parsedType?.type === 'Type' && field.rule !== 'repeated' && context.pluginValue('prototypes.allowUndefinedTypes'); if (isTypeCastable) { const tp = symbols.map(a => t.tsTypeReference(t.identifier(a.readAs))); tp.push(typ); if (context.pluginValue('interfaces.useUnionTypes')) { if (!isArray) { tp.push(t.tsUndefinedKeyword()); } ast = t.tsUnionType(tp); } else { // intersections if (isArray) { ast = t.tsIntersectionType(tp); } else { ast = t.tsUnionType([ t.tsIntersectionType(tp), t.tsUndefinedKeyword() ]); } } } else if (isProtoTypeCastable) { const tp = symbols.map(a => t.tsTypeReference(t.identifier(exports.SymbolNames.ProtoMsg(a.readAs)))); symbols.forEach(a => { context.addImportDerivative({ type: 'ProtoMsg', symbol: a }); }); tp.push(typ); if (!isArray) { tp.push(t.tsUndefinedKeyword()); } ast = t.tsUnionType(tp); } else if (isSDKTypeCastable) { const tp = symbols.map(a => t.tsTypeReference(t.identifier(exports.SymbolNames.SDKType(a.readAs)))); symbols.forEach(a => { context.addImportDerivative({ type: 'SDKType', symbol: a }); }); tp.push(typ); if (!isArray) { tp.push(t.tsUndefinedKeyword()); } ast = t.tsUnionType(tp); } else if (isNonArrayNullableType) { // regular types! ast = t.tsUnionType([ typ, t.tsUndefinedKeyword() ]); } else { ast = typ; } return { ast, isTypeCastableAnyType: isTypeCastable }; }; exports.getFieldTypeReference = getFieldTypeReference; const getFieldAminoTypeReference = (context, field) => { let ast = null; let typ = null; if (proto_1.SCALAR_TYPES.includes(field.type)) { // return on scalar typ = (0, exports.getTSTypeForAmino)(context, field); return typ; } else if (proto_1.GOOGLE_TYPES.includes(field.type)) { typ = (0, exports.getTSTypeFromGoogleType)(context, field.type, 'Amino'); } else { const propName = (0, utils_1.getProtoFieldTypeName)(context, field); // enums don't need suffixes, etc. const MsgName = field.parsedType?.type === 'Enum' ? propName : exports.SymbolNames.Amino(propName); typ = t.tsTypeReference(t.identifier(MsgName)); } if (field.parsedType?.type === 'Type') { const typeName = field.isNestedMsg ? field.importedName : field.parsedType.name; context.addImportDerivative({ type: 'Amino', symbol: { ref: context.ref.filename, readAs: typeName, source: field.import, symbolName: typeName, type: 'import' }, }); } if (field.parsedType?.type === 'Type' && field.rule !== 'repeated' && context.pluginValue('prototypes.allowUndefinedTypes')) { // NOTE: unfortunately bc of defaults... ast = t.tsUnionType([ typ, t.tsUndefinedKeyword() ]); } else { ast = typ; } return ast; }; exports.getFieldAminoTypeReference = getFieldAminoTypeReference; const getTSType = (context, type) => { switch (type) { case 'string': return t.tsStringKeyword(); case 'double': case 'float': case 'int32': case 'uint32': case 'sint32': case 'fixed32': case 'sfixed32': return t.tsNumberKeyword(); case 'int64': case 'uint64': case 'sint64': case 'fixed64': case 'sfixed64': utils_1.TypeLong.addUtil(context); return t.tsTypeReference(utils_1.TypeLong.getPropIdentifier(context)); case 'bytes': return t.tsTypeReference(t.identifier('Uint8Array')); case 'bool': return t.tsBooleanKeyword(); default: throw new Error('getTSType() type not found'); } ; }; exports.getTSType = getTSType; const getTSAminoType = (context, type, options) => { switch (type) { case 'string': return t.tsStringKeyword(); case 'double': case 'float': case 'int32': case 'uint32': case 'sint32': case 'fixed32': case 'sfixed32': return t.tsNumberKeyword(); case 'int64': case 'uint64': case 'sint64': case 'fixed64': case 'sfixed64': return t.tsStringKeyword(); case 'bytes': // (gogoproto.customname) = "WASMByteCode", if (options?.["(gogoproto.customname)"] === "WASMByteCode") { return t.tsStringKeyword(); } return t.tsTypeReference(t.identifier('Uint8Array')); case 'bool': return t.tsBooleanKeyword(); default: throw new Error('getTSType() type not found'); } ; }; exports.getTSAminoType = getTSAminoType; const getTSTypeFromGoogleType = (context, type, options = 'Msg') => { const identifier = (str) => { return t.identifier(exports.SymbolNames[options](str)); }; switch (type) { case 'google.protobuf.Timestamp': if (options === 'Amino' || options === 'AminoMsg') { return t.tsStringKeyword(); } switch (context.pluginValue('prototypes.typingsFormat.timestamp')) { case 'timestamp': return t.tsTypeReference(identifier('Timestamp')); case 'date': default: return t.tsTypeReference(t.identifier('Date')); } case 'google.protobuf.Duration': switch (context.pluginValue('prototypes.typingsFormat.duration')) { case 'duration': return t.tsTypeReference(identifier('Duration')); case 'string': default: return t.tsStringKeyword(); } case 'google.protobuf.Any': return t.tsTypeReference(identifier('Any')); default: throw new Error('getTSTypeFromGoogleType() type not found'); } ; }; exports.getTSTypeFromGoogleType = getTSTypeFromGoogleType; const getTSTypeForAmino = (context, field) => { switch (field.type) { case 'bytes': if (field.options?.["(gogoproto.casttype)"] === "RawContractMessage") { return t.tsAnyKeyword(); } else { return t.tsStringKeyword(); } default: return (0, exports.getTSAminoType)(context, field.type); } ; }; exports.getTSTypeForAmino = getTSTypeForAmino; const getTSTypeForProto = (context, field) => { return (0, exports.getTSType)(context, field.type); }; exports.getTSTypeForProto = getTSTypeForProto; const getDefaultTSTypeFromProtoType = (context, field, isOneOf, useNullForOptionals = false) => { const isOptional = (0, proto_1.getFieldOptionalityForDefaults)(context, field, isOneOf); const setDefaultCustomTypesToUndefined = context.pluginValue('prototypes.typingsFormat.setDefaultCustomTypesToUndefined'); if (field.rule === 'repeated') { return t.arrayExpression([]); } if (field.keyType) { return t.objectExpression([]); } if (isOptional) { return useNullForOptionals ? t.nullLiteral() : t.identifier('undefined'); } if (field.parsedType?.type === 'Enum') { const enumDefault = getPreferredEnumDefault(context, field); return t.numericLiteral(enumDefault); } switch (field.type) { case 'string': return t.stringLiteral(''); case 'double': case 'float': case 'int32': case 'uint32': case 'sint32': case 'fixed32': case 'sfixed32': return t.numericLiteral(0); case 'uint64': utils_1.TypeLong.addUtil(context); return utils_1.TypeLong.getUZero(context); case 'int64': case 'sint64': case 'fixed64': case 'sfixed64': utils_1.TypeLong.addUtil(context); return utils_1.TypeLong.getZero(context); case 'bytes': return t.newExpression(t.identifier('Uint8Array'), []); case 'bool': return t.booleanLiteral(false); // OTHER TYPES case 'google.protobuf.Timestamp': if (setDefaultCustomTypesToUndefined) { return t.identifier('undefined'); } else { const timestampType = context.pluginValue('prototypes.typingsFormat.timestamp'); switch (timestampType) { case 'timestamp': return t.callExpression(t.memberExpression(t.identifier('Timestamp'), t.identifier('fromPartial')), [t.objectExpression([])]); case 'date': return t.newExpression(t.identifier('Date'), []); default: return t.identifier('undefined'); } } // TODO: add cases for this later on case 'google.protobuf.Duration': if (setDefaultCustomTypesToUndefined) { return t.identifier('undefined'); } else { return getDefaultTSTypeFromProtoTypeDefault(context, field); } case 'google.protobuf.Any': if (setDefaultCustomTypesToUndefined) { return t.identifier('undefined'); } else { return getDefaultTSTypeFromProtoTypeDefault(context, field); } case 'cosmos.base.v1beta1.Coin': if (setDefaultCustomTypesToUndefined) { return t.identifier('undefined'); } else { return getDefaultTSTypeFromProtoTypeDefault(context, field); } case 'cosmos.base.v1beta1.Coins': return t.arrayExpression([]); default: if (!field.type) { console.warn('Undefined! Can\'t get field of type:', field); return t.identifier('undefined'); } else { return getDefaultTSTypeFromProtoTypeDefault(context, field); } } ; }; exports.getDefaultTSTypeFromProtoType = getDefaultTSTypeFromProtoType; const getDefaultTSTypeFromAminoTypeDefault = (context, field) => { const typeName = (0, utils_1.getProtoFieldTypeName)(context, field); return t.callExpression(t.memberExpression(t.identifier(typeName), t.identifier("toAmino")), [ t.callExpression(t.memberExpression(t.identifier((0, utils_1.getProtoFieldTypeName)(context, field)), t.identifier("fromPartial")), [t.objectExpression([])]), ]); }; exports.getDefaultTSTypeFromAminoTypeDefault = getDefaultTSTypeFromAminoTypeDefault; function getDefaultTSTypeFromProtoTypeDefault(context, field) { return t.callExpression(t.memberExpression(t.identifier((0, utils_1.getProtoFieldTypeName)(context, field)), t.identifier('fromPartial')), [t.objectExpression([])]); } function getPreferredEnumDefault(context, field) { const autoFixUndefinedEnumDefault = context.pluginValue('prototypes.typingsFormat.autoFixUndefinedEnumDefault'); if (autoFixUndefinedEnumDefault) { const typeName = (0, utils_1.getProtoFieldTypeName)(context, field); return context.getDefaultOrExistingSmallestEnumValue(getPackage(field), typeName); } else { if (context.ref.proto?.syntax === 'proto2') { return types_1.ENUM_PROTO2_DEFAULT; } else { return types_1.ENUM_PROTO3_DEFAULT; } } } function getPackage(field) { const pkgs = field.scope?.flat(); return pkgs ? pkgs[0] : ''; }