@cosmology/ast
Version:
Cosmos TypeScript AST generation
297 lines (296 loc) • 15.6 kB
JavaScript
;
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.createRpcInterface = exports.createRpcClientClass = exports.getRpcClassName = exports.createRpcClientInterface = void 0;
const t = __importStar(require("@babel/types"));
const utils_1 = require("../../../../utils");
const utils_2 = require("@cosmology/utils");
const rpc_1 = require("../utils/rpc");
const binary_coder_expression_1 = require("../../../../utils/binary-coder-expression");
const rpcMethodDefinition = (name, svc, trailingComments, leadingComments) => {
const requestType = svc.requestType;
const responseType = svc.responseType;
const fieldNames = Object.keys(svc.fields ?? {});
const hasParams = fieldNames.length > 0;
const optional = (0, rpc_1.optionalBool)(hasParams, fieldNames);
const methodArgs = (0, utils_1.identifier)('request', t.tsTypeAnnotation(t.tsTypeReference(t.identifier(requestType))), optional);
return (0, utils_1.tsMethodSignature)(t.identifier(name), null, [
methodArgs
], (0, rpc_1.returnReponseType)(responseType), trailingComments, leadingComments);
};
const rpcTxMethodDefinition = (name, svc, trailingComments, leadingComments) => {
const requestType = svc.requestType;
const responseType = t.tsTypeReference(t.identifier("any"));
const methodArgs = [
(0, utils_1.identifier)("signerAddress", t.tsTypeAnnotation(t.tsStringKeyword())),
(0, utils_1.identifier)("message", t.tsTypeAnnotation(t.tsTypeReference(t.identifier(requestType)))),
(0, utils_1.identifier)("fee", t.tsTypeAnnotation(t.tsUnionType([
t.tsNumberKeyword(),
t.tsTypeReference(t.identifier("StdFee")),
t.tsLiteralType(t.stringLiteral("auto")),
]))),
(0, utils_1.identifier)("memo", t.tsTypeAnnotation(t.tsStringKeyword()), true),
];
return (0, utils_1.tsMethodSignature)(t.identifier(name), null, methodArgs, (0, rpc_1.returnReponseType)(responseType), trailingComments, leadingComments);
};
// this.Accounts = this.Accounts.bind(this);
// MARKED AS NOT DRY (used in rpc/lcd)
const bindThis = (name) => {
return t.expressionStatement(t.assignmentExpression('=', t.memberExpression(t.thisExpression(), t.identifier(name)), t.callExpression(t.memberExpression(t.memberExpression(t.thisExpression(), t.identifier(name)), t.identifier('bind')), [
t.thisExpression()
])));
};
// const data = QueryAccountsRequest.encode(request).finish();
const encodeData = (name) => {
return t.variableDeclaration('const', [
t.variableDeclarator(t.identifier('data'), t.callExpression(t.memberExpression(t.callExpression(t.memberExpression(t.identifier(name), t.identifier('encode')), [
t.identifier('request')
]), t.identifier('finish')), []))
]);
};
// const promise = this.rpc.request("cosmos.auth.v1beta1.Query", "Accounts", data);
const promiseRequest = (name, packageImportName) => {
name = (0, rpc_1.cleanType)(name);
return t.variableDeclaration('const', [
t.variableDeclarator(t.identifier('promise'), t.callExpression(t.memberExpression(t.memberExpression(t.thisExpression(), t.identifier('rpc')), t.identifier('request')), [
t.stringLiteral(packageImportName),
t.stringLiteral(name),
t.identifier('data')
]))
]);
};
// return promise.then((data) => QueryAccountsResponse.decode(new _m0.Reader(data)));
const returnPromise = (name, context) => {
name = (0, rpc_1.cleanType)(name);
return t.returnStatement(t.callExpression(t.memberExpression(t.identifier('promise'), t.identifier('then')), [
t.arrowFunctionExpression([
t.identifier('data')
], t.callExpression(t.memberExpression(t.identifier(name), t.identifier('decode')), [
t.newExpression(binary_coder_expression_1.BinaryCoder.getReaderMemberExp(context), [
t.identifier('data')
]),
...(context.options.interfaces.enabled && context.options.interfaces.useUseInterfacesParams ? [
t.identifier('undefined'),
t.identifier('useInterfaces')
] : []),
]))
]));
};
const makeComment = (comment) => {
return [{ type: 'CommentBlock', value: ` ${comment} ` }];
};
const rpcClassMethod = (context, name, msg, svc, packageImport) => {
const requestType = svc.requestType;
const responseType = svc.responseType;
const comment = svc.comment ?? svc.name;
let methodArgs = (0, utils_1.identifier)('request', t.tsTypeAnnotation(t.tsTypeReference(t.identifier(requestType))));
const fieldNames = Object.keys(svc.fields ?? {});
const hasParams = fieldNames.length > 0;
// if no params, then let's default to empty object for cleaner API
if (!hasParams) {
methodArgs = t.assignmentPattern(methodArgs, t.objectExpression([]));
}
else if (hasParams && fieldNames.length === 1 && fieldNames.includes('pagination')) {
const paginationDefaultFromPartial = context.pluginValue('prototypes.paginationDefaultFromPartial');
// if only argument "required" is pagination
// also default to empty
methodArgs = t.assignmentPattern(methodArgs, t.objectExpression([
t.objectProperty(t.identifier('pagination'), paginationDefaultFromPartial ? t.callExpression(t.memberExpression(t.identifier("PageRequest"), t.identifier("fromPartial")), [t.objectExpression([])]) :
t.identifier('undefined'), false, false)
]));
}
const body = t.blockStatement([
// const data = QueryAccountsRequest.encode(request).finish();
encodeData(requestType),
// const promise = this.rpc.request("cosmos.auth.v1beta1.Query", "Accounts", data);
promiseRequest(msg, packageImport),
// return promise.then((data) => QueryAccountsResponse.decode(new _m0.Reader(data)));
returnPromise(responseType, context)
]);
if (context.pluginValue('classesUseArrowFunctions')) {
return (0, utils_1.classProperty)(t.identifier(name), (0, utils_1.arrowFunctionExpression)([methodArgs], body, (0, rpc_1.returnReponseType)(responseType), true), undefined, undefined, undefined, undefined, undefined, undefined, makeComment(comment));
}
return (0, utils_1.classMethod)('method', t.identifier(name), [
methodArgs,
...(context.options.interfaces.enabled && context.options.interfaces.useUseInterfacesParams ? [
t.assignmentPattern((0, utils_1.identifier)('useInterfaces', t.tsTypeAnnotation(t.tsBooleanKeyword())), t.identifier((context.pluginValue('interfaces.useByDefaultRpc') ?? true).toString()))
] : []),
], body, (0, rpc_1.returnReponseType)(responseType));
};
const rpcTxClassMethod = (context, name, msg, svc, packageImport) => {
const requestType = svc.requestType;
const responseType = t.tsTypeReference(t.identifier("any"));
const comment = svc.comment ?? svc.name;
const methodArgs = [
(0, utils_1.identifier)("signerAddress", t.tsTypeAnnotation(t.tsStringKeyword())),
(0, utils_1.identifier)("message", t.tsTypeAnnotation(t.tsTypeReference(t.identifier(requestType)))),
t.assignmentPattern((0, utils_1.identifier)("fee", t.tsTypeAnnotation(t.tsUnionType([
t.tsNumberKeyword(),
t.tsTypeReference(t.identifier("StdFee")),
t.tsLiteralType(t.stringLiteral("auto")),
]))), t.stringLiteral("auto")),
t.assignmentPattern((0, utils_1.identifier)("memo", t.tsTypeAnnotation(t.tsStringKeyword())), t.stringLiteral("")),
];
const body = t.blockStatement([
// generate:
// const data = [
// {
// typeUrl: MsgCreateValidator.typeUrl,
// value: message,
// },
// ];
t.variableDeclaration('const', [
t.variableDeclarator(t.identifier('data'), t.arrayExpression([
t.objectExpression([
t.objectProperty(t.identifier('typeUrl'), t.memberExpression(t.identifier(svc.requestType), t.identifier('typeUrl'))),
t.objectProperty(t.identifier('value'), t.identifier('message'))
])
]))
]),
// generate:
// return this.rpc.signAndBroadcast!(
// signerAddress,
// data,
// fee,
// memo
// );
t.returnStatement(t.callExpression(t.memberExpression(t.memberExpression(t.thisExpression(), t.identifier('rpc')), t.identifier('signAndBroadcast!')), [
t.identifier('signerAddress'),
t.identifier('data'),
t.identifier('fee'),
t.identifier('memo')
]))
]);
if (context.pluginValue('classesUseArrowFunctions')) {
return (0, utils_1.classProperty)(t.identifier(name), (0, utils_1.arrowFunctionExpression)(methodArgs, body, (0, rpc_1.returnReponseType)(responseType), true), undefined, undefined, undefined, undefined, undefined, undefined, makeComment(comment));
}
return (0, utils_1.classMethod)('method', t.identifier(name), methodArgs, body, (0, rpc_1.returnReponseType)(responseType));
};
const rpcClassConstructor = (context, methods) => {
const useTelescopeGeneratedType = context.pluginValue('prototypes.typingsFormat.useTelescopeGeneratedType');
let bound = [];
if (!context.pluginValue('classesUseArrowFunctions')) {
bound = methods.map(method => bindThis(method));
}
return (0, utils_1.classMethod)('constructor', t.identifier('constructor'), [
(0, utils_1.identifier)('rpc', t.tsTypeAnnotation(t.tsTypeReference(t.identifier(useTelescopeGeneratedType ? 'TxRpc' : 'Rpc'))))
], t.blockStatement([
t.expressionStatement(t.assignmentExpression('=', t.memberExpression(t.thisExpression(), t.identifier('rpc')), t.identifier('rpc'))),
/// methods
...bound
]));
};
const createRpcClientInterface = (context, service, name, methodKeys, nameMapping) => {
const serviceImplement = context.pluginValue('rpcClients.serviceImplement');
const camelRpcMethods = context.pluginValue('rpcClients.camelCase');
const keys = methodKeys && methodKeys.length ? methodKeys : Object.keys(service.methods ?? {});
const methods = keys
.map((key) => {
const methodName = camelRpcMethods ? (0, utils_2.camel)(key) : key;
const implementType = (0, utils_2.getServiceImplement)(service.name, context.ref.proto.package, methodName, serviceImplement);
const method = service.methods[key];
if (!method) {
return null;
}
const nameWithPkg = `${context.ref.proto.package}.${methodName}`;
const methodAlias = nameMapping && nameMapping[nameWithPkg] ? nameMapping[nameWithPkg] : methodName;
const leadingComments = method.comment ? [(0, utils_1.commentBlock)((0, rpc_1.processRpcComment)(method))] : [];
let trailingComments = [];
switch (implementType) {
case "Tx":
context.addUtil("StdFee");
return rpcTxMethodDefinition(methodAlias, method, trailingComments, leadingComments);
case "Query":
default:
return rpcMethodDefinition(methodAlias, method, trailingComments, leadingComments);
}
}).filter(Boolean);
const obj = t.exportNamedDeclaration(t.tsInterfaceDeclaration(t.identifier(name ?? service.name), null, [], t.tsInterfaceBody([
...methods
])));
if (service.comment) {
obj.leadingComments = [(0, utils_1.commentBlock)(`* ${service.comment} `)];
}
return obj;
};
exports.createRpcClientInterface = createRpcClientInterface;
const getRpcClassName = (service) => {
return `${service.name}ClientImpl`;
};
exports.getRpcClassName = getRpcClassName;
const createRpcClientClass = (context, service) => {
const serviceImplement = context.pluginValue('rpcClients.serviceImplement');
const useTelescopeGeneratedType = context.pluginValue('prototypes.typingsFormat.useTelescopeGeneratedType');
if (useTelescopeGeneratedType) {
context.addUtil('TxRpc');
}
else {
context.addUtil('Rpc');
}
binary_coder_expression_1.BinaryCoder.addUtil(context, 'reader');
const camelRpcMethods = context.pluginValue('rpcClients.camelCase');
const name = (0, exports.getRpcClassName)(service);
const implementsName = service.name;
const methodNames = Object.keys(service.methods ?? {})
.map(key => {
return camelRpcMethods ? (0, utils_2.camel)(key) : key;
});
const methods = Object.keys(service.methods ?? {})
.map(key => {
const name = camelRpcMethods ? (0, utils_2.camel)(key) : key;
const implementType = (0, utils_2.getServiceImplement)(service.name, context.ref.proto.package, name, serviceImplement);
const method = service.methods[key];
switch (implementType) {
case "Tx":
context.addUtil("StdFee");
return rpcTxClassMethod(context, name, key, method, context.ref.proto.package + '.' + service.name);
case "Query":
default:
return rpcClassMethod(context, name, key, method, context.ref.proto.package + '.' + service.name);
}
});
return t.exportNamedDeclaration((0, utils_1.classDeclaration)(t.identifier(name), null, t.classBody([
(0, utils_1.classProperty)(t.identifier('rpc'), null, t.tsTypeAnnotation(t.tsTypeReference(t.identifier(useTelescopeGeneratedType ? 'TxRpc' : 'Rpc'))), null, false, false, true, 'private'),
// CONSTRUCTOR
rpcClassConstructor(context, methodNames),
// METHODS
...methods
]), null, [
t.tsExpressionWithTypeArguments(t.identifier(implementsName))
]));
};
exports.createRpcClientClass = createRpcClientClass;
const createRpcInterface = (context, service) => {
return t.tsInterfaceDeclaration(t.identifier('Rpc'), null, [], t.tsInterfaceBody([
t.tsMethodSignature(t.identifier('request'), null, [
(0, utils_1.identifier)('service', t.tsTypeAnnotation(t.tsStringKeyword())),
(0, utils_1.identifier)('method', t.tsTypeAnnotation(t.tsStringKeyword())),
(0, utils_1.identifier)('data', t.tsTypeAnnotation(t.tsTypeReference(t.identifier('Uint8Array'))))
], t.tsTypeAnnotation(t.tsTypeReference(t.identifier('Promise'), t.tsTypeParameterInstantiation([
t.tsTypeReference(t.identifier('Uint8Array'))
]))))
]));
};
exports.createRpcInterface = createRpcInterface;