import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics'; import { FormFieldType, ModelField, ModelRelation, ClassRelationEnum, Model } from '@vmfvmf/ywtc-lib'; import { qryChatGpt } from '../../../../shared/chatgpt-api'; import { camelize, classify, dasherize } from '@angular-devkit/core/src/utils/strings'; import { getEnumById, getModelById, getPrjSrd } from '../../../../router.gen'; import { E2EGenerator } from '../../../../shared/generator'; import { P5 } from '../../../../router.map'; const dummyItemsNumber = 10; let imports: Set; export function gen(model: Model): Rule { model = new Model(model); return async (tree: Tree, _context: SchematicContext) => { imports = new Set(); let fieldsStr = await getModelFactory(model); fieldsStr = addOnetoOneRelation(fieldsStr, model.getChildForms()); fieldsStr = addManytoOneRelation(fieldsStr, model.relations.filter(r => r.relation === ClassRelationEnum.ManyToOne)); fieldsStr = addOnetoManyRelation(fieldsStr, model.getChildTables()); fieldsStr = addManytoManyRelation(fieldsStr, model.relations.filter(rel => rel.relation == ClassRelationEnum.ManyToMany)); const fields = model.fields; importEnums(model.fields); importChildTableEnums(model.getChildTables().map(rel => getModelById(rel.toModelId))); if(model.fields.some(f => f.angularType.includes('DATE'))) { imports.add(`import { pipeTransform } from 'cypress/support/utils/pipe-transform';`); } model.getChildTables() .map(rel => getModelById(rel.toModelId)) .map((childModel: Model) => `import { I${classify(childModel.name)} } from 'src/app/${getPrjSrd().prjNDashd}-frontend/${dasherize(childModel.name)}/${dasherize(childModel.name)}';`) .forEach(imp => imports.add(imp)); const tablesNamesToReset = [getPrjSrd().mdlNUndes, ...model.relations.map((rel: ModelRelation) => dasherize(rel.toModelName).replace('-', '_'))] .map(name => `${P5}'${getPrjSrd().dbName}.${name}'`) .join(',\n'); const columnsFieldNameMap = new Map(); const childTableEntityFactoryArray: string[] = []; for(let childTable of model.getChildTables()) { childTableEntityFactoryArray.push(await getChildEntityFactoryStr(getModelById(childTable.toModelId))) } model.fields .forEach((f: ModelField) => columnsFieldNameMap.set(dasherize(f.name).replace('-', '_'), f.name)); const noResultSearchMProp = model.getFilters() .find((field: ModelField) => [FormFieldType.INPUT, FormFieldType.TEXT_AREA].includes(field.formField.type)) || model.fields[0]; const noResultSearchMField = noResultSearchMProp; const noResultSearchFieldStr = noResultSearchMProp?.name || ''; const noResultSearchValueStr = !noResultSearchMProp ? '' : noResultSearchMField.angularType == 'ENUM' ? noResultSearchMField.enumDefName + '.' + JSON.parse(getEnumById(noResultSearchMField.enumDefId).optionsJson)[0].value : noResultSearchMField.angularType == 'DATE' ? new Date() : noResultSearchMField.angularType == 'NUMBER' ? 9999 : "'NORESULT'"; const importsStr = Array.from(imports.values()).sort().join('\n'); return new E2EGenerator(__filename).gen({ fieldsStr, fields, ...getPrjSrd(), tablesNamesToReset, dummyItemsNumber, getFieldNameInfo, columnsFieldNameMap, noResultSearchValueStr, importsStr, noResultSearchFieldStr }); }; } function addOnetoOneRelation(fieldsStr: string, relationsOneToOne: ModelRelation[]) { relationsOneToOne.forEach(rel => { let i = -1; imports.add(`import { ${camelize(rel.toModelName)}Pool } from './${dasherize(rel.name)}-factory';`); fieldsStr = fieldsStr.split("{") .map(s => s.replace("}", `,"${camelize(rel.toModelName)}": ${rel.name}Pool[${i++}]\n}`)).join("{"); }); return fieldsStr; } function addOnetoManyRelation(fieldsStr: string, relationsOnetoMany: ModelRelation[]) { relationsOnetoMany.forEach(rel => { let i = -1; imports.add(`import { ${camelize(rel.toModelName)}Pool } from './${dasherize(rel.toModelName)}-factory';`); fieldsStr = fieldsStr.split("{") .map(s => s.replace("}", `,"${rel.name}": [${camelize(rel.toModelName)}Pool[${i++}]]\n}`)).join("{"); }); return fieldsStr; } function addManytoOneRelation(fieldsStr: string, relationsManytoOne: ModelRelation[]) { relationsManytoOne.forEach(rel => { let i = -1; fieldsStr = fieldsStr.split("{") .map(s => s.replace("}", `,"${rel.name}Id": ${i++}\n}`)).join("{"); }); return fieldsStr; } function addManytoManyRelation(fieldsStr: string, relationsMtoN: ModelRelation[]) { relationsMtoN.forEach(rel => { fieldsStr = fieldsStr.split("{") .map(s => s.replace("}", `,"${rel.name}Ids": [${getRandomNxM()}]\n}`)).join("{"); }); return fieldsStr; } function getRandomNxM() { let relSet = new Set(); let max = 1 + Math.floor(Math.random() * 3) for (var j = 0; j < max; j++) { relSet.add(1 + Math.floor(Math.random() * 7)); } return Array.from(relSet).map(n => n.toString()).join(","); } async function getChildEntityFactoryStr(childTable: Model): Promise { const modelName = childTable.name; const modelNameDash = dasherize(modelName); const modelNameCamel = camelize(modelName); const modelNameToUpper = modelNameDash.replace('-', '_').toLocaleUpperCase(); const fieldsStr = await getModelFactory(childTable); return `const ${modelNameCamel}Pool = ${fieldsStr}; export const ${modelNameToUpper}_FACTORY: IEntityFactory = {\n\tSEARCH_POOL: ${modelNameCamel}Pool,\n\tNO_RESULT_SEARCH: {},\n\tNEW: ${modelNameCamel}Pool[0],\n\t UPDATED: ${modelNameCamel}Pool[1]\n}`; } export function getFieldNameInfo(fieldName: string, fields: Array) { return fields.filter(f => f.name == fieldName) .map(f => f.angularType == 'DATE' ? `\${pipeTransform.date(p.${fieldName}, 'yyyy-MM-dd')}` : `\${p.${fieldName}}` )[0]; } function importChildTableEnums(childTables: Model[]) { childTables.map(cTable => importEnums(cTable.fields)); } export async function getModelFactory(model: Model) { return (await generateValueFor(model)).answer; } export function importEnums(fields: Array) { fields .filter(f => f.angularType == 'ENUM') .map(f => `import { ${f.enumDefName} } from 'src/app/${getPrjSrd().prjNDashd}-frontend/enums/${dasherize(f.enumDefName)}';`) .forEach(en => imports.add(en)); } async function generateValueFor(model: Model) { return await qryChatGpt(model.id); }