import * as path from 'path'; const ncp = require('ncp').ncp; import { createDatabase, writeMigrationsToFile } from './database/database-creator'; import { createViews } from './views/views-creator'; import {createFrontend} from "./frontend-services/fe-service-creator"; import {removeTemplateFolder} from "./helpers"; class SystemGenService { public runSysGen(defs: SystemDef) { ncp(path.join(process.cwd(), 'frame'), path.join(process.cwd(), defs.name), (err: any) => { if (err) { console.log("error in ncp"); console.log(err); } else { console.log('success copying files'); this.buildDatabase(defs.storage, defs.name); this.buildViews(defs, defs.name); } }); ncp(path.join(process.cwd(), 'frontend-frame'), path.join(process.cwd(), `frontend-${defs.name}`), (err: any) => { if (err) { console.log("error in frontend ncp"); console.log(err); } else { console.log("success copying frontend files"); this.buildFrontend(defs); } }); } public buildDatabase(storage: StorageDef, outDir: string) { let creationMigrations = createDatabase(storage); writeMigrationsToFile(creationMigrations, outDir); } public buildViews(systemDef: SystemDef, outDir: string) { createViews(systemDef); } public buildFrontend(systemDef: SystemDef) { createFrontend(systemDef); } public cleanup() { // TODO: remove 'component/{{component}}' folder } } const systemGenService = new SystemGenService(); interface SystemDef { name: string; storage: StorageDef; components: ComponentDef[]; // TODO: add ACLs, Behaviors, UX } interface StorageDef { tables: TableDef[]; relations: ManyToManyDef[]; } interface ComponentDef { component: string; endpoints: EndpointDef[]; } interface EndpointDef { component: string; table: string; type: ('list' | 'count' | 'item' | 'update' | 'create' | 'delete' | 'search'); columns: ColumnRef[]; values?: ValueDef[]; join?: JoinDef[]; orderBy?: Order[]; filters?: Filter[]; // if type is 'list' it will always include skip and limit for pagination } interface Order { column: ColumnRef; direction: 'asc' | 'desc'; } interface Filter { param: string; // the query param used to get the value column: ColumnRef; comparison: '=' | '!=' | '>' | '<' | 'contains' | 'LIKE'; required?: boolean; type?: string; } interface TableDef { name: string; columns: ColumnDef[], relations: BelongsToDef[], } interface ColumnDef { name: string; type: "blob" | "boolean" | "date" | "dateTIME" | "number" | "string"; nullable: boolean; unique?: boolean; autoIncrement?: boolean; default?: string; } interface ColumnRef { name: string; table: string; param?: string; required?: boolean; type?: string; } interface ValueDef { column: string; required: boolean; } interface JoinDef { table: string; on: { left: ColumnRef; right: ColumnRef; } } interface BelongsToDef { type: 'belongs-to'; table: string; } interface ManyToManyDef { left: string; relation: 'many-to-many'; right: string; columns?: ColumnDef[]; } export { BelongsToDef, ColumnDef, ColumnRef, ComponentDef, EndpointDef, Filter, JoinDef, ManyToManyDef, Order, StorageDef, SystemDef, TableDef, systemGenService }