import {BelongsToDef, ColumnDef, EndpointDef, Filter, ManyToManyDef, SystemDef, TableDef} from "../systemGenService"; import {lowercaseFirstLetter} from "../helpers"; import {buildMapperFunctionName} from "./mapper-creator"; function createServiceFunc(view: EndpointDef) { // TODO: add support for doing things other than talking to the mapper e.g. API calls and cache checks return buildServiceFunction(view); } function buildServiceFunction(view: EndpointDef): string { let func: string = ''; let isListOrSearch: boolean = view.type === 'list' || view.type === 'search'; let funcName: string = buildServiceFunctionName(view); let funcParams: string[] = getFuncParams(view); let columnParams: string[] = view.columns?.filter(column => column.param).map(column => { return '\n ' + column.param + ': ' + column.param; }); let filterParams: string[] = view.filters?.filter(filter => filter.param).map(filter => { return '\n ' + filter.param + ': ' + filter.param; }) || []; if (isListOrSearch) { funcParams.push('offset'); funcParams.push('limit'); } func = ` public ${funcName}(${funcParams.join(', ')}) { let params = {${columnParams}${columnParams.length ? ',' : ''}${filterParams} }; return this.${mapperInstance(view)}.${buildMapperFunctionName(view)}(params${isListOrSearch ? ', offset, limit' : ''}); } `; return func; } function getFuncParams(view: EndpointDef, addTypes=false, systemDef?: SystemDef): string[] { let filters = view.filters || []; let columnList: ParamDef[] = view.columns?.filter((column) => {return column.param;}).map((column) => { return { param: column.param, required: column.required, type: column.type }; }); let filterList: ParamDef[] = filters.filter((column) => {return column.param;}).map((filter) => { return { param: filter.param, required: filter.required, type: filter.type }; }); let relationsList: ParamDef[] = []; if (systemDef) { let storageTable: TableDef | undefined = systemDef.storage.tables.find((table: TableDef) => { return view.component === table.name; }); if (storageTable) { relationsList = storageTable.relations.map((rel: BelongsToDef) => { return { param: rel.table + '_id', required: false, type: 'string' } }); } relationsList = [...relationsList, ...systemDef.storage.relations.filter((rel: ManyToManyDef) => { if (rel.left === view.component || rel.right === view.component) { return true; } return false; }).map((rel: ManyToManyDef) => { if (rel.left === view.component) { return { param: rel.right + '_id', required: false, type: 'string' }; } else { return { param: rel.left + '_id', required: false, type: 'string' }; } })]; } // funcParams should be sorted by 'required' so the optional params can come last and be left off when calling let combinedList = relationsList.concat(columnList).concat(filterList).sort((a, b) => { if (a.required && b.required) { return 0; } if (a.required) { return -1; } if (b.required) { return 1; } return 0; }); return combinedList.map((param) => { if (param.type && addTypes) { return `${param.param}: ${param.type}`; } return param.param || ''; // both lists have already been filtered so the value should never return as an empty string }); } function buildServiceFunctionName(view: EndpointDef): string { return buildMapperFunctionName(view); // the functions should have the same name... I'm pretty sure... } function mapperInstance(view: EndpointDef): string { return `${lowercaseFirstLetter(view.component)}Mapper`; } interface ParamDef { param?: string; required?: boolean; type?: string; } export { createServiceFunc, getFuncParams, buildServiceFunctionName }