@cuba-platform/front-generator
Version:
CUBA Platform front-end clients generator
145 lines • 7.36 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createQuery = exports.generateQueries = void 0;
const method_params_type_1 = require("./method-params-type");
const ts = require("typescript");
const import_utils_1 = require("../import-utils");
const services_generation_1 = require("./services-generation");
const constants_1 = require("../../../common/constants");
const ts_helpers_1 = require("../../../common/ts-helpers");
const ts_shorthands_1 = require("../../../common/ts-shorthands");
const model_utils_1 = require("../model/model-utils");
const QUERIES_VAR_NAME = 'restQueries';
function generateQueries(restQueries, ctx) {
// import declaration
// import { CubaApp, FetchOptions, SerializedEntity, EntitiesWithCount } from "@cuba-platform/rest";
const importDec = (0, import_utils_1.importDeclaration)([constants_1.CUBA_APP_TYPE, constants_1.FETCH_OPTIONS_TYPE, constants_1.SERIALIZED_ENTITY_TYPE, constants_1.ENTITIES_WITH_COUNT_TYPE], constants_1.CUBA_APP_MODULE_SPEC);
// compose import infos of entities, entities are used as function type parameters, i.e. 'Car' entity is used as
// cubaApp.query<Car>("scr$Car", "allCars", {}, fetchOpts);
const entityImportInfos = restQueries
.map(restQuery => restQuery.entity)
.reduce((importInfos, entityName) => {
const entityInfo = (0, model_utils_1.findEntityByName)(entityName, ctx);
// do not add duplicates
if (entityInfo && !importInfos.find(ii => ii.className === entityInfo.entity.className)) {
importInfos.push((0, import_utils_1.entityImportInfo)(entityInfo, constants_1.ENTITIES_DIR));
}
return importInfos;
}, []);
const queriesResult = createQueries(restQueries, ctx);
// includes composed from import infos of entities + import infos of types, used in parameters, i.e
//
// export type queries_FavoriteCar_allCars_params = {
// car: Car;
// };
const includes = (0, import_utils_1.createIncludes)([...queriesResult.importInfos, ...entityImportInfos]);
return (0, ts_helpers_1.renderTSNodes)([importDec, ...includes, ...queriesResult.methodParamTypes, queriesResult.node], '\n\n');
}
exports.generateQueries = generateQueries;
function createQueries(restQueries, ctx) {
const assignmentList = [];
const methodParamTypes = [];
const importInfos = [];
const queriesByEntity = new Map();
restQueries.forEach(q => {
const queriesOfEntity = queriesByEntity.get(q.entity);
if (queriesOfEntity) {
queriesOfEntity.push(q);
}
else {
queriesByEntity.set(q.entity, [q]);
}
});
[...queriesByEntity.entries()].forEach(([entityName, queries]) => {
const createItemResult = createQuery(entityName, queries, ctx);
assignmentList.push(createItemResult.node);
createItemResult.methodParamsTypes.forEach(mpt => methodParamTypes.push(mpt));
importInfos.push(...createItemResult.imports);
});
const variableDeclaration = ts.createVariableDeclaration(QUERIES_VAR_NAME, undefined, ts.createObjectLiteral(assignmentList, true));
const node = ts.createVariableStatement([(0, ts_shorthands_1.exportModifier)()], [variableDeclaration]);
return { node, methodParamTypes, importInfos };
}
/**
* Call example:
* restQueries.Car.carsByType(cubaApp, fetchOpts?)(params?)
* restQueries.Car.carsByTypeCount(cubaApp, fetchOpts?)(params?)
* restQueries.Car.carsByTypeWithCount(cubaApp, fetchOpts?)(params?)
*
* Cuba REST call:
* cubaApp.query("mpg$Car", "carsByType", params, fetchOpts);
* cubaApp.queryCount("mpg$Car", "carsByType", params, fetchOpts);
* cubaApp.queryWithCount("mpg$Car", "carsByType", params, fetchOpts);
*/
function createQuery(entityName, queries, ctx) {
const methodAssignments = [];
const methodParamsTypes = [];
const imports = [];
const className = findClassName(entityName, ctx);
const paramTypePrefix = 'queries_' + className;
//'overload' queries - queries with both same entity and name
(0, method_params_type_1.collectMethods)(queries).forEach((mwo) => {
let paramTypeName = undefined;
//if any of overloads has params - create special type for it
if (mwo.methods.some(m => m.params.length > 0)) {
const { paramTypeNode, importInfos, name } = (0, method_params_type_1.createMethodParamsType)(mwo.methods, paramTypePrefix, ctx);
imports.push(...importInfos);
methodParamsTypes.push(paramTypeNode);
paramTypeName = name;
}
const typeArguments = [ts.createTypeReferenceNode(className, [])];
['', 'Count', 'WithCount'].forEach(suffix => {
const qName = mwo.methodName;
let functionType = undefined;
// Promise<EntitiesWithCount<ClassName>>
if (suffix === 'WithCount')
functionType = createEntitiesWithCountQueryFunctionType(className);
// Promise<SerializedEntity<ClassName>[]>
if (suffix === '')
functionType = createSerializedEntityQueryFunctionType(className);
// Promise<Number>
if (suffix === 'Count')
functionType = createCountQueryFunctionType();
const cubaCallFunc = (0, services_generation_1.cubaAppCallFunc)('query' + suffix, paramTypeName, functionType, [entityName, qName], suffix !== 'Count' ? typeArguments : []);
methodAssignments.push(ts.createPropertyAssignment(qName + suffix, cubaCallFunc));
});
});
//todo do we need to resolve entities with same names, or entity.name is unique in CUBA ?
const node = ts.createPropertyAssignment(className, ts.createObjectLiteral(methodAssignments, true));
return { node, methodParamsTypes, imports };
}
exports.createQuery = createQuery;
/**
* @param className name used in function type
* @return 'Promise<SerializedEntity<ClassName>[]>'
*/
function createSerializedEntityQueryFunctionType(className) {
const entityClassTypeNode = ts.createTypeReferenceNode(className, []);
const entityTypeNode = ts.createTypeReferenceNode(constants_1.SERIALIZED_ENTITY_TYPE, [entityClassTypeNode]);
const entityArrayTypeNode = ts.createArrayTypeNode(entityTypeNode);
return ts.createTypeReferenceNode('Promise', [entityArrayTypeNode]);
}
/**
* @param className name used in function type
* @return 'Promise<EntitiesWithCount<ClassName>>'
*/
function createEntitiesWithCountQueryFunctionType(className) {
const entityClassTypeNode = ts.createTypeReferenceNode(className, []);
const entityTypeNode = ts.createTypeReferenceNode(constants_1.ENTITIES_WITH_COUNT_TYPE, [entityClassTypeNode]);
return ts.createTypeReferenceNode('Promise', [entityTypeNode]);
}
/**
* @return 'Promise<Number>'
*/
function createCountQueryFunctionType() {
const numberTypeNode = ts.createTypeReferenceNode('Number', []);
return ts.createTypeReferenceNode('Promise', [numberTypeNode]);
}
function findClassName(entityName, ctx) {
const entry = [...ctx.entitiesMap.entries()]
.find(([, projEntityInfo]) => {
return projEntityInfo.entity.name == entityName;
});
return entry[1].entity.className;
}
//# sourceMappingURL=queries-generation.js.map