@cosmology/ast
Version:
Cosmos TypeScript AST generation
168 lines (167 loc) • 6.79 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.buildRpcStores = exports.createMobxQueryStores = void 0;
const t = __importStar(require("@babel/types"));
const utils_1 = require("../../utils");
const utils_2 = require("@cosmology/utils");
const utils_3 = require("@cosmology/utils");
const case_1 = require("case");
const makeQueryStoreName = (name) => {
return `Query${(0, case_1.pascal)(name)}Store`;
};
/**
* Entry for building stores.
* @param {Object=} context - context of generating the file
* @param {Object=} service - method details
*/
const createMobxQueryStores = (context, service) => {
const isIncluded = context.pluginValue('mobx.enabled') &&
(0, utils_2.isRefIncluded)(context.ref, context.pluginValue('mobx.include'));
if (isIncluded) {
// before this, make sure:
// 1. refactor adding getQueryService part into helpers.
// 2. add new query store class to helpers.
// build whole ast, don't forget to add utils.
return (0, exports.buildRpcStores)(context, service);
}
return null;
};
exports.createMobxQueryStores = createMobxQueryStores;
/**
* Create an AST to generate creating store functions.
* eg:
* export const createRpcQueryMobxStores = (rpc: ProtobufRpcClient | undefined) => {
* const queryService = getQueryService(rpc);
*
* class QueryCertificatesStore {
* ...
* }
*
* return {
* QueryCertificatesStore
* };
* };
* @param {Object=} context - context of generating the file
* @param {Object=} service - method details
* @returns {ParseResult} created AST
*/
const buildRpcStores = (context, service) => {
// add imports
context.addUtil('ProtobufRpcClient');
//TODO: add util for getQueryService
const isCamelRpcMethods = context.pluginValue('rpcClients.camelCase');
const storeNames = [];
const stores = Object.keys(service.methods ?? {}).map((key) => {
const method = service.methods[key];
const name = isCamelRpcMethods ? (0, utils_3.camel)(key) : key;
storeNames.push({
name,
comment: method.comment
});
return buildStore(context, name, method);
});
return t.exportNamedDeclaration(t.variableDeclaration('const', [
t.variableDeclarator(t.identifier('createRpcQueryMobxStores'), t.arrowFunctionExpression([
(0, utils_1.identifier)('rpc', t.tsTypeAnnotation(t.tsUnionType([
t.tsTypeReference(t.identifier('ProtobufRpcClient')),
t.tsUndefinedKeyword()
])))
],
// body
t.blockStatement([
// query service
t.variableDeclaration('const', [
t.variableDeclarator(t.identifier('queryService'), t.callExpression(t.identifier('getQueryService'), [
t.identifier('rpc')
]))
]),
...stores,
// return the methods...
t.returnStatement(t.objectExpression(storeNames.map(({ name, comment }) => {
const id = t.identifier(makeQueryStoreName(name));
return (0, utils_1.objectProperty)(id, id, false, true, null, (0, utils_1.makeCommentLineWithBlocks)(comment));
})))
])
// end body
))
]));
};
exports.buildRpcStores = buildRpcStores;
/**
* Create an AST of inherited store.
* eg:
* class QueryCertificatesStore {
* store = new QueryStore<QueryCertificatesRequest, QueryCertificatesResponse>(queryService?.certificates);
* certificates(request: QueryCertificatesRequest) {
* return this.store.getData(request);
* }
* }
* @param {Object=} context - context of generating the file
* @param {string} name - name of the store
* @param {Object=} serviceMethod - method details
* @returns {ParseResult} created AST
*/
const buildStore = (context, name, serviceMethod) => {
//add util for QueryStore
context.addUtil('QueryStore');
//add util for MobxResponse
context.addUtil('MobxResponse');
//add util for makeObservable
context.addUtil('makeObservable');
//add util for override
context.addUtil('override');
const requestType = serviceMethod.requestType;
const responseType = serviceMethod.responseType;
const fieldNames = Object.keys(serviceMethod.fields ?? {});
const hasParams = fieldNames.length > 0;
let isOptional = false;
// // if no params, then let's default to empty object for cleaner API
if (!hasParams) {
isOptional = true;
}
else if (hasParams &&
fieldNames.length === 1 &&
fieldNames.includes('pagination')) {
// if only argument "required" is pagination
// also default to empty
isOptional = true;
}
const storeClassName = makeQueryStoreName(name);
const storeQueryClass = t.classDeclaration(t.identifier(storeClassName), null, t.classBody([
t.classProperty(t.identifier('store'), (0, utils_1.newExpression)(t.identifier('QueryStore'), [
t.optionalMemberExpression(t.identifier('queryService'), t.identifier(name), false, true)
], t.tsTypeParameterInstantiation([
t.tsTypeReference(t.identifier(requestType)),
t.tsTypeReference(t.identifier(responseType))
]))),
t.classMethod('method', t.identifier(name), [
(0, utils_1.identifier)('request', t.tsTypeAnnotation(t.tsTypeReference(t.identifier(requestType))))
], t.blockStatement([
t.returnStatement(t.callExpression(t.memberExpression(t.memberExpression(t.thisExpression(), t.identifier('store')), t.identifier('getData')), [t.identifier('request')]))
], []))
]));
return storeQueryClass;
};
;