package tst import ( "fmt" "strings" . "git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/common" // . "git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/gen" TS "git.eugeniocarvalho.dev/eugeniucarvalho/gg/generators/typescript" ) func GenSchemas(p *Project) error { var ( attribName string propName string attribs []TS.CodeInterface attrib *TS.Group entityInfo *EntityInfo arrayProperties = []*Propertie{} ) appendBasePatchClass() for _, entity := range p.Schemas { attribs = []TS.CodeInterface{} arrayProperties = []*Propertie{} entityInfo = p.ResponseEntity(entity.ID) for _, meta := range entity.Properties { propName = strings.Title(meta.ID) meta.FillTags(p, propName) // Registra a relaao entre as entidades // if meta.Relation { // SR.Add(&Relation{ // Source: meta.GetType(), // Target: entity.ID, // Attr: strings.Replace(meta.Tags["bson"], ",omitempty", "", 1), // Collection: entity.Collection, // }) // } if meta.Array { arrayProperties = append(arrayProperties, meta) } // Adiciona as tags caso sejam definidas if meta.Tags != nil { if name, ok := meta.Tags["json"]; ok { attribName = strings.Split(name, ",")[0] if attribName == "-" { attribName = meta.ID } } } else { attribName = meta.ID } if attribName == "id" { attribName = "_id" } meta.Name = attribName // Adiciona a crescricao como comentario attrib = &TS.Group{} if meta.Description != "" { // propertie.Comment(meta.Description) attrib.Comment(meta.Description) } if attribName != "" { optional := "?" // if getCustom(meta.Custom, "ts.optional").(bool) { // if !meta.Required { // options = "?" // } // attrib.Add(TS.Public().Id(attribName).Op(":").Id(TS.ConvType(meta.Type))) attrib.Add(TS.Id(attribName).Id(optional).Op(":").Id(TS.ConvType(meta.Type))) if meta.Array { attrib.Add(TS.Index()) } attrib.Endl() attribs = append(attribs, attrib) } } // Fim do loop dos atributos // attribs = append(attribs, TS.Constructor(TS.Raw("opts: any")).Block(TS.Raw("opts && Object.assign(this,opts);"))) unshift := []TS.CodeInterface{TS.Id(`constructor(entity?:any){ if(entity){Object.assign(this, entity);}}`)} attribs = append(unshift, attribs...) module.Line().Export().Class().Id(strings.Title(entity.ID)).Block( // module.Line().Export().Interface().Id(strings.Title(entity.ID)).Block( attribs..., ).Line() if !entityInfo.IsGeneric { createPathClass(entity, arrayProperties) } } // Fim do for de schema return nil } func createPathClass(entity *Entity, arrayProperties []*Propertie) { module. Line(). Export(). Class(). Id(strings.Title(entity.ID + "Patch")). Extends(). Id("BasePatch"). BlockFun(func(g *TS.Group) { createClassProperties(g, entity, arrayProperties) createSetInitializeMethod(g, entity, arrayProperties) // createPatchMethod(g, entity, arrayProperties) createAddAndRemoveMethods(g, entity, arrayProperties) // g.Raw(` // protected emit(timeout = 0) { // super.emit(this.Patchs(), timeout); // } // `) }). Line() } func createClassProperties(g *TS.Group, entity *Entity, arrayProperties []*Propertie) { for _, meta := range arrayProperties { g.Line().Add( TS.Raw(fmt.Sprintf("%s = new Map();", meta.ID, strings.Title(entity.ID))), ) } } func createSetInitializeMethod(g *TS.Group, entity *Entity, arrayProperties []*Propertie) { destructuring := []string{} for _, meta := range arrayProperties { destructuring = append(destructuring, fmt.Sprintf("%s=[]", meta.ID)) } destructuringString := strings.Join(destructuring, ",") g.Add(TS. Line(). Line(). // Do(). Constructor(TS.Raw(fmt.Sprintf("{%s} : %s", destructuringString, entity.ID))). BlockFun(func(block *TS.Group) { // block.Add(TS.Raw(`this.instance = instance;`).Line()) block.Add(TS.Raw(`super();`).Line()) // .Raw(`const {`) for _, meta := range arrayProperties { // block.Add(TS.Raw(fmt.Sprintf("if ($instance.%s) { this._set(this.%s, $instance.%s, '',-1);}", meta.ID, meta.ID, meta.ID)).Line()) block.Add(TS.Raw(fmt.Sprintf("if (%s && %s.length) { this._set(this.%s, %s, '',-1);}", meta.ID, meta.ID, meta.ID, meta.ID)).Line()) } }), ) } func createPatchMethod(g *TS.Group, entity *Entity, arrayProperties []*Propertie) { g.Add(TS.Line(). Raw(`Patchs()`). BlockFun(func(block *TS.Group) { block.Add(TS.Raw(`const patchs = {`)) for _, meta := range arrayProperties { block.Add(TS. Line(). Raw(fmt.Sprintf("Add%s : [],", strings.Title(meta.ID))). Line(). Raw(fmt.Sprintf("Remove%s : [],", strings.Title(meta.ID))). Line(). Raw(fmt.Sprintf("Replace%s : [],", strings.Title(meta.ID))), ) } block. Line(). Raw(`};`). Line(). Raw(`return patchs;`). Line() }), ) } func createAddAndRemoveMethods(g *TS.Group, entity *Entity, arrayProperties []*Propertie) { const timeout = 50 for _, meta := range arrayProperties { g.Add(TS. Line(). Id(fmt.Sprintf("Add%s", strings.Title(meta.ID))). Params(TS.Id("itens"), TS.Id(fmt.Sprintf("timeout = %d", timeout))). // Params(TS.Id("itens"), TS.Id("timeout")). Block( TS.Raw(fmt.Sprintf("this._set(this.%s, itens, 'add', timeout);return this;", meta.ID)), ). Line(). Id(fmt.Sprintf("Remove%s", strings.Title(meta.ID))). Params(TS.Id("itens"), TS.Id(fmt.Sprintf("timeout = %d", timeout))). // Params(TS.Id("itens"), TS.Id("timeout")). Block( TS.Raw(fmt.Sprintf("this._set(this.%s, itens, 'remove', timeout);return this;", meta.ID)), ). Line(). Id(fmt.Sprintf("Replace%s", strings.Title(meta.ID))). Params(TS.Id("itens"), TS.Id(fmt.Sprintf("timeout = %d", timeout))). Block( TS.Raw(fmt.Sprintf("this._set(this.%s, itens, 'replace', timeout);return this;", meta.ID)), ), ) } } func appendBasePatchClass() { module.Line().Raw(` export class BasePatch { protected $set = {}; protected $subscription: any; public locked = false; public change$ = new EventEmitter(); public $transformPatch = (patch) => patch; Set(options, timeout = 0) { this.$set = {...this.$set, ...options}; if (timeout >= 0){ this.emit(this.patch(), timeout); } } protected emit(patch:any , timeout = 0) { if (this.$subscription) { clearTimeout(this.$subscription); } this.locked = true; this.$subscription = setTimeout(() => this.change$.emit(patch), timeout); } protected __set(list, add, rem, replace) { list.forEach(element => { const {item} = element; switch (element.action) { case 'add': add.push(item); break; case 'replace': replace.push(item); break; case 'remove': if (element.type !== 'new') { rem.push(item._id || item); } } }); } public from(patches, timeout = 50){ const {$set = {}} = patches; this.Set($set, timeout); Object.keys(patches).map(prop => { if (prop.startsWith('$')) { return;} if (typeof this[prop] === 'function') { this[prop](patches[prop], timeout); } }); } protected _set(_map: Map, itens, action, timeout = 50) { (itens || []).map(item => { const id = (item._id || item); const has = _map.has(id) , el = _map.get(id); switch (action) { case 'replace': _map.set(id, { item, action: 'replace', type: 'new', }); break; case 'add': if (!has) { _map.set(id, { item, action: 'add', type: 'new', }); } else if (el.action === 'remove') { el.action = 'add'; } break; case 'remove': if (has) { el.action = 'remove'; break; } // tslint:disable-next-line:no-switch-case-fall-through default: _map.set(id, { item, action, type: '', }); } }); if (timeout >= 0){ this.emit(this.patch(), timeout); } } patch() { const $this = this; const patchs = {}; if (Object.getOwnPropertyNames(this.$set).length) { patchs['$set'] = this.$set; } Object.keys($this).map(prop => { if (prop.startsWith('$')) { return; } const adds = [],replace = [],remove = []; const captalized = prop[0].toUpperCase() + prop.slice(1); if ($this[prop].size) { this.__set($this[prop], adds, remove, replace); if (adds.length){ patchs[`).Raw("`Add${captalized}`").Raw(`] = adds; } if (replace.length){ patchs[`).Raw("`Replace${captalized}`").Raw(`] = replace; } if (remove.length){ patchs[`).Raw("`Remove${captalized}`").Raw(`] = remove; } } }); return this.$transformPatch(patchs); } } `) }