import { Rule } from '@angular-devkit/schematics'; import { dasherize } from '@angular-devkit/core/src/utils/strings'; import { AngularFieldType, mapAngularTypeToFieldName, ModelField, ModelRelation, ClassRelationEnum, Model } from '@vmfvmf/ywtc-lib'; import { FrontEndGenerator } from '../../../shared/generator'; import { getPrjSrd } from '../../../router.gen'; var importSet: Set; export function gen(model: Model): Rule { importSet = new Set(); const comomFields = generateCommonFields(model.fields); const classFields = [comomFields, generateRelationFields(model.relations)].join('\n'); const interfaceFields = [comomFields, generateIRelationFields(model.relations)].join('\n'); const imports = Array.from(importSet).sort().join('\n'); const constructorFieldsSet = new Set(); model.fields.forEach(field => constructorFieldsSet.add(field.name)); model.relations .filter(rel => [ClassRelationEnum.OneToOne, ClassRelationEnum.OneToMany].includes(rel.relation)) .forEach(rel => constructorFieldsSet.add(rel.name)); model.relations .filter(rel => [ClassRelationEnum.ManyToOne].includes(rel.relation)) .forEach(rel => constructorFieldsSet.add(`${rel.name}Id`)); model.relations.filter(rel => rel.relation === ClassRelationEnum.ManyToMany) .forEach(rel => constructorFieldsSet.add(`${rel.name}Ids`)); const constructorFieldsStr = Array.from(constructorFieldsSet).join(', '); const fieldsInitialization = [ generateFieldsInitialization(model.fields), generateRelationInitialization(model.relations) ].join('\n'); const httpParamsStr = getHttpParamsStr(model); return new FrontEndGenerator(__filename).gen({ ...model, ...getPrjSrd(), constructorFieldsStr, httpParamsStr, imports, classFields, interfaceFields, fieldsInitialization }); } function getHttpParamsStr(model: Model) { let fields = model.fields .filter(field => field.angularType === AngularFieldType.DATETIME) .map(field => `httpParams = httpParams.set("${field.name}", this.${field.name}!.toISOString().split('.')[0]);`); if (fields && fields.length > 0) { return `\n\n\toverride toHttpParams() { let httpParams = super.toHttpParams(); ${fields.join('\n')} return httpParams; }` } return ''; } export function importEnums(fields: Array): Array { let enumNamesSet = new Set(); fields.filter(f => f.angularType === AngularFieldType.ENUM).forEach(f => enumNamesSet.add(f.enumDefName)); return Array.from(enumNamesSet).map(f => `import { ${f} } from '../enums/${dasherize(f)}';`); } function generateRelationFields(relations: Array) { return relations.map(classFieldFromRelation).join('\n'); } export function generateCommonFields(fields: Array) { return fields.map(fieldFromAbstractField).join('\n'); } export function generateIRelationFields(relations: Array) { return relations.map(fieldFromAbstractFieldForInterface).join('\n'); } function fieldFromAbstractField(field: ModelField) { return `\t${field.name}?: ${getFieldType(field)};` } function classFieldFromRelation(rel: ModelRelation) { let fieldType = ''; switch(rel.relation) { case ClassRelationEnum.OneToOne: fieldType = `${rel.toModelName}`; importSet.add(`import { ${fieldType }, I${fieldType } } from '../${dasherize(fieldType)}/${dasherize(fieldType)}';`); break; case ClassRelationEnum.OneToMany: fieldType = `Array<${rel.toModelName}>`; importSet.add(`import { ${rel.toModelName }, I${rel.toModelName } } from '../${dasherize(rel.toModelName)}/${dasherize(rel.toModelName)}';`); break; case ClassRelationEnum.ManyToOne: return `\t${rel.name}Id?: number;`; case ClassRelationEnum.ManyToMany: return `\t${rel.name}Ids?: Array;`; } return `\t${rel.name}?: ${fieldType};`; } function fieldFromAbstractFieldForInterface(rel: ModelRelation) { if ([ClassRelationEnum.ManyToOne].includes(rel.relation)) { return `\t${rel.name}Id?: number;`; } else if ([ClassRelationEnum.ManyToMany].includes(rel.relation)) { return `\t${rel.name}Ids?: Array;`; } return `\t${rel.name}?: ${getRelationFieldIType(rel)};` } function getRelationFieldIType(rel: ModelRelation) { if (rel.relation === ClassRelationEnum.ManyToMany) { return 'number[]'; } else if (ClassRelationEnum.OneToMany === rel.relation) { return `I${rel.toModelName}[]`; } else if (ClassRelationEnum.OneToOne === rel.relation) { return `I${rel.toModelName}`; } return ''; } function getFieldType(field: ModelField) { let fieldType = ''; if (AngularFieldType.ENUM === (field as ModelField).angularType!) { fieldType = field.enumDefName; importSet.add(`import { ${fieldType} } from '../enums/${dasherize(fieldType)}';`); } else { fieldType = mapAngularTypeToFieldName.get((field as ModelField).angularType); } return field.collection ? `Array<${fieldType}>` : fieldType; } export function generateFieldsInitialization(fields: Array) { return fields.map(field => `\t\tthis.${field.name} = ${field.name};`).join('\n'); } export function generateRelationInitialization(relations: Array) { return relations.map(rel => { switch(rel.relation) { case ClassRelationEnum.OneToOne: return `\t\tthis.${rel.name} = new ${rel.toModelName}(${rel.name});`; case ClassRelationEnum.ManyToMany: return `\t\tthis.${rel.name}Ids = ${rel.name}Ids ? [...${rel.name}Ids] : [];`; case ClassRelationEnum.OneToMany: return `\tthis.${rel.name} = ${rel.name}?.map(${rel.name[0]} => new ${rel.toModelName}(${rel.name[0]})) ?? [];`; case ClassRelationEnum.ManyToOne: return `\tthis.${rel.name}Id = ${rel.name}Id`; } }).join('\n'); }