UNPKG

leds-spark-lib

Version:

Biblioteca de geração de código

223 lines (220 loc) 9.22 kB
import path from "path"; import fs from "fs"; import { isEnumX, isLocalEntity, isModule, isModuleImport, getRef, capitalizeString, createPath, processRelations, CompositeGeneratorNode, expandToStringWithNL, toString } from "../../../models/model.js"; import { generateIdentityUser, generateModel } from "./model-generator.js"; import { generateEnum } from "./enum-generator.js"; export function generateModules(model, target_folder) { const modules = model.abstractElements.filter(isModule); const all_entities = modules.map((module) => module.elements.filter(isLocalEntity)).flat(); const relation_maps = processRelations(all_entities); const imported_entities = processImportedEntities(model); const features = model.configuration?.feature; const clsauth = model.configuration?.entity; const sahred_folder = createPath(target_folder, "Shared"); fs.writeFileSync(path.join(sahred_folder, `ContextDb.cs`), toString(generateContextDb(modules, "Shared", relation_maps, features))); for (const mod of modules) { const package_name = `${mod.name}`; const MODULE_PATH = createPath(target_folder, package_name.replaceAll(".", "/")); const supertype_classes = processSupertypes(mod); const mod_classes = mod.elements.filter(isLocalEntity); for (const cls of mod_classes) { const class_name = cls.name; const { attributes, relations } = getAttrsAndRelations(cls, relation_maps); if (clsauth && getRef(clsauth)?.name === cls.name) { fs.writeFileSync(path.join(MODULE_PATH, `${class_name}.cs`), toString(generateModel(cls, supertype_classes.has(cls), relations, package_name, imported_entities, true))); fs.writeFileSync(path.join(MODULE_PATH, `AppUser.cs`), toString(generateIdentityUser(cls, package_name))); } else { fs.writeFileSync(path.join(MODULE_PATH, `${class_name}.cs`), toString(generateModel(cls, supertype_classes.has(cls), relations, package_name, imported_entities, false))); } } for (const enumx of mod.elements.filter(isEnumX)) { fs.writeFileSync(path.join(MODULE_PATH, `${enumx.name}.cs`), generateEnum(enumx, package_name)); } fs.writeFileSync(path.join(MODULE_PATH, `ContextDbFactory.cs`), generateContextDbFactory(package_name)); } } function processImportedEntities(application) { const map = new Map(); for (const moduleImport of application.abstractElements.filter(isModuleImport)) { moduleImport.entities.forEach((importedEntity) => map.set(importedEntity, moduleImport)); } return map; } function processSupertypes(mod) { const set = new Set(); for (const cls of mod.elements.filter(isLocalEntity)) { const superTypeRef = getRef(cls.superType); if (superTypeRef && isLocalEntity(superTypeRef)) { set.add(superTypeRef); } } return set; } function getAttrsAndRelations(cls, relation_map) { const superTypeRef = getRef(cls.superType); if (superTypeRef && isLocalEntity(superTypeRef)) { const parent = superTypeRef; const { attributes, relations } = getAttrsAndRelations(parent, relation_map); return { attributes: attributes.concat(cls.attributes), relations: relations.concat(relation_map.get(cls) ?? []) }; } else { return { attributes: cls.attributes, relations: relation_map.get(cls) ?? [] }; } } function generateContextDb(modules, package_name, relation_maps, features) { const all_entities = modules.flatMap((mod) => mod.elements.filter(isLocalEntity)); if (features === 'authentication') { return expandToStringWithNL ` namespace ${package_name}{ using Microsoft.EntityFrameworkCore; using Microsoft.AspNetCore.Identity.EntityFrameworkCore; ${generateDbContextUsing(modules)} internal class ContextDb : IdentityDbContext { public ContextDb(DbContextOptions<ContextDb> options) : base(options) { } ${generateDbSet(all_entities)} protected override void OnModelCreating(ModelBuilder modelBuilder) { ${generateDbRelations(all_entities, relation_maps)} } } }`; } else { return expandToStringWithNL ` namespace ${package_name}{ using Microsoft.EntityFrameworkCore; ${generateDbContextUsing(modules)} public class ContextDb : DbContext { public ContextDb(DbContextOptions<ContextDb> options) : base(options) { } ${generateDbSet(all_entities)} protected override void OnModelCreating(ModelBuilder modelBuilder) { ${generateKeyDeclarations(all_entities)} ${generateDbRelations(all_entities, relation_maps)} } } }`; } } function generateDbSet(entities) { return entities.map((cls) => `public DbSet<${cls.name}> ${cls.name}s { get; set; }`).join('\n'); } function generateKeyDeclarations(all_entities) { return all_entities .filter((cls) => !getRef(cls.superType)) .map((cls) => `modelBuilder.Entity<${cls.name}>().HasKey(e => e.Id);`) .join('\n'); } function generateDbRelations(entities, relation_maps) { const node = new CompositeGeneratorNode(); for (const cls of entities) { const { relations } = getAttrsAndRelations(cls, relation_maps); for (const rel of relations) { node.append(generateRelationConfiguration(cls, rel)); node.appendNewLine(); } } node.append('base.OnModelCreating(modelBuilder);'); return toString(node); } function generateDbContextUsing(modules) { let usings = ""; for (const mod of modules) { usings += `using ${mod.name}; \n`; } return usings; } function generateRelationConfiguration(cls, { tgt, card, owner }) { const getPluralName = (name) => `${name}s`; switch (card) { case "OneToOne": if (owner) { return expandToStringWithNL ` // Configuration for One-to-One, where ${cls.name} is the owner modelBuilder.Entity<${cls.name}>() .HasOne(e => e.${tgt.name}) .WithOne(e => e.${cls.name}) .HasForeignKey<${tgt.name}>("${cls.name}Id") .OnDelete(DeleteBehavior.Restrict);`; } else { return ''; } case "OneToMany": if (owner) { const pluralName = getPluralName(tgt.name); return expandToStringWithNL ` // Configuration for One-to-Many, where ${cls.name} is the owner of the collection modelBuilder.Entity<${cls.name}>() .HasMany(e => e.${pluralName}) .WithOne(e => e.${cls.name}) .HasForeignKey(e => e.${cls.name}Id);`; } else { return ''; } case "ManyToOne": if (owner) { const pluralName = getPluralName(cls.name); return expandToStringWithNL ` // Configuration for Many-to-One, where ${cls.name} is the dependent modelBuilder.Entity<${cls.name}>() .HasOne(e => e.${tgt.name}) .WithMany(e => e.${pluralName}) .HasForeignKey(e => e.${tgt.name}Id) .OnDelete(DeleteBehavior.Restrict);`; } else { return ''; } case "ManyToMany": if (owner) { const pluralName = getPluralName(tgt.name); const clsPluralName = getPluralName(cls.name); return expandToStringWithNL ` // Configuration for Many-to-Many using entity type builder modelBuilder.Entity<${cls.name}>() .HasMany(e => e.${pluralName}) .WithMany(e => e.${clsPluralName}) .UsingEntity(j => j.ToTable("${cls.name}${tgt.name}"));`; } else { return ''; } } } function generateContextDbFactory(package_name) { return expandToStringWithNL ` using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Design; using Microsoft.Extensions.Configuration; using System.IO; using Shared; namespace ${package_name} { public class ContextDbFactory : IDesignTimeDbContextFactory<ContextDb> { public ContextDb CreateDbContext(string[] args) { var configuration = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json") .Build(); var optionsBuilder = new DbContextOptionsBuilder<ContextDb>(); var connectionString = configuration.GetConnectionString("${capitalizeString(package_name || "model")}Connection"); optionsBuilder.UseSqlServer(connectionString); return new ContextDb(optionsBuilder.Options); } } }`; } //# sourceMappingURL=module-generator.js.map