Browse Source

change paths handler

EUGENIO SOUZA CARVALHO 3 years ago
parent
commit
a6095dcc3a

+ 8 - 3
Dockerfile

@@ -1,5 +1,7 @@
 FROM golang:1.14.6-alpine3.12 as builder
 LABEL maintainer Eugenio Carvalho <eugeniucarvalho@gmail.com>
+ARG BUILD_ID
+
 ENV NODE_VERSION 12.13.0
 ENV YARN_VERSION 1.19.1
 ENV GIT_TERMINAL_PROMPT=1
@@ -94,8 +96,11 @@ RUN addgroup -g 1000 node \
   && rm /var/cache/apk/*
 
 RUN npm install -g typescript typescript-formatter
-
-COPY ./eon-amd64 /usr/bin/eon
+COPY eon-amd64 /usr/bin/eon
+COPY api /dep/apicodegen/api
+COPY authorization /dep/apicodegen/authorization
+COPY common /dep/apicodegen/common
+COPY go.* /dep/apicodegen/
 RUN mkdir /workdir
 VOLUME /workdir
-WORKDIR /workdir
+WORKDIR /workdir/project

+ 7 - 1
api/errs/errs.go

@@ -65,7 +65,13 @@ func (e *Error) LastDescription() *Detail {
 // Error retorna a mensagem de erro principal
 
 func (e *Error) Error() string {
-	return e.Message
+	reason := ""
+
+	if len(e.Errors) > 0 {
+		reason = e.LastDescription().Reason
+	}
+
+	return fmt.Sprintf("[%s] %s",reason, e.Message)
 }
 
 // The operation was cancelled, typically by the caller.

+ 158 - 0
api/mail/adapter_aws_ses.go

@@ -0,0 +1,158 @@
+package mail
+
+import (
+	"fmt"
+
+	"git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/api/errs"
+	"git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/api/types"
+
+	//go get -u github.com/aws/aws-sdk-go
+	"github.com/aws/aws-sdk-go/aws"
+	"github.com/aws/aws-sdk-go/aws/awserr"
+	"github.com/aws/aws-sdk-go/aws/session"
+	"github.com/aws/aws-sdk-go/service/ses"
+)
+
+const (
+	// The character encoding for the email.
+	AwsCharSet = "UTF-8"
+)
+
+var (
+	AwsErrorCodeMap = map[string]string{
+		ses.ErrCodeMessageRejected: ses.ErrCodeMessageRejected,
+		ses.ErrCodeMailFromDomainNotVerifiedException: ses.ErrCodeMailFromDomainNotVerifiedException,
+		ses.ErrCodeConfigurationSetDoesNotExistException: ses.ErrCodeConfigurationSetDoesNotExistException,
+	}
+)
+
+
+type AwsSESAdapter struct {
+}
+
+func (adapter *AwsSESAdapter) Send(mail *Mail, options *SendMailOptions) (err *errs.Error) {
+	var (
+		sendError error
+		result *ses.SendEmailOutput
+		sess *session.Session
+	)
+	sess, sendError = session.NewSession(&aws.Config{
+		Region: aws.String("us-east-1")},
+	)
+
+	// Create an SES session.
+	svc := ses.New(sess)
+	destination := mail.Destination
+	body := mail.Body
+	// Assemble the email.
+	input := &ses.SendEmailInput{
+		Destination: &ses.Destination{
+			CcAddresses: destination.CcAddresses,
+			ToAddresses: destination.ToAddresses,
+		},
+		Source: mail.Sender,
+		Message: &ses.Message{
+			Subject: &ses.Content{
+				Charset: aws.String(AwsCharSet),
+				Data:    mail.Subject,
+			},
+			Body: &ses.Body{
+				Html: &ses.Content{
+					Charset: aws.String(AwsCharSet),
+					Data:    body.Html,
+				},
+				Text: &ses.Content{
+					Charset: aws.String(AwsCharSet),
+					Data:    body.Text,
+				},
+			},
+		},
+		// Uncomment to use a configuration set
+		// ConfigurationSetName: aws.String(ConfigurationSet),
+	}
+
+	// Attempt to send the email.
+	if result, sendError = svc.SendEmail(input); sendError != nil {
+		err = adapter.handlerError(sendError)
+		return
+	}
+
+	fmt.Println("Email Sent to address: ")
+	fmt.Println(result)
+
+	return
+}
+
+func (adapter *AwsSESAdapter) SendTemplateEmail(mail *Mail, options *SendMailOptions) (err *errs.Error) {
+	var (
+		sendError error
+		jsonData string
+		sess *session.Session
+		result *ses.SendTemplatedEmailOutput
+	)
+
+	sess, sendError = session.NewSession(&aws.Config{
+		Region: aws.String("us-east-1")},
+	)
+
+	// Create an SES session.
+	svc := ses.New(sess)
+
+	if mail.TemplateData == nil {
+		mail.TemplateData = &types.Map{}
+	}
+	
+	if jsonData, err = types.JSON(mail.TemplateData); err != nil {
+		return
+	}
+
+
+	destination := mail.Destination
+	// Assemble the email.
+	// input := &ses.SendEmailInput{
+	input := &ses.SendTemplatedEmailInput{
+		Template:     mail.Template,
+		TemplateData: aws.String(jsonData),
+		Destination: &ses.Destination{
+			CcAddresses: destination.CcAddresses,
+			ToAddresses: destination.ToAddresses,
+		},
+		Source: mail.Sender,
+		// Uncomment to use a configuration set
+		// ConfigurationSetName: aws.String(ConfigurationSet),
+	}
+
+	// Attempt to send the email.
+	// Display error messages if they occur.
+	if result, sendError = svc.SendTemplatedEmail(input); sendError != nil {
+		err = adapter.handlerError(sendError)
+		return
+	}
+
+	fmt.Println("Email Sent to address:")
+	fmt.Println(result)
+
+	return
+}
+
+
+func (adapter *AwsSESAdapter) handlerError(sendError error) (err *errs.Error)  {
+	var (
+		message string
+		reason string
+		found bool
+	)
+	if aerr, ok := sendError.(awserr.Error); ok {
+		if reason, found = AwsErrorCodeMap[aerr.Code()]; !found {
+			reason = ""
+		}
+		message = aerr.Error()
+	} else {
+		message = err.Error()
+	}
+	err = errs.Internal().Details(&errs.Detail{
+		Reason : reason,
+		Message: message,
+	})
+	return
+}

+ 76 - 0
api/mail/service.go

@@ -0,0 +1,76 @@
+package mail
+
+import (
+	"git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/api/errs"
+)
+
+type Destination struct {
+	CcAddresses []*string
+	ToAddresses []*string
+}
+
+type Body struct {
+	Html *string
+	Text *string
+}
+
+type Mail struct {
+	Template *string
+	Sender *string
+	Subject *string
+	Body *Body 
+	TemplateData interface{}
+	Destination *Destination 
+}
+
+type SendMailOptions struct {
+	Adapter string
+	Sync bool
+}
+
+type MailAdapter interface {
+	Send(mail *Mail, options *SendMailOptions) (err *errs.Error)
+	SendTemplateEmail(mail *Mail, options *SendMailOptions) (err *errs.Error)
+}
+
+type MailAdapters = map[string]MailAdapter
+
+var (
+	Adapters = MailAdapters{}
+)
+
+func init(){
+	Adapters["default"] = &AwsSESAdapter{}
+}
+
+func Send(mail *Mail, options *SendMailOptions) (err *errs.Error) {
+	var (
+		adapterID = "default"
+		adapter MailAdapter
+		found bool
+		sendSync  = true
+		sendHandler func(mail *Mail, options *SendMailOptions) (err *errs.Error)
+	)
+	
+	if options != nil {
+		if options.Adapter != "" { adapterID = options.Adapter}
+		if options.Sync { sendSync = options.Sync}
+	}
+	
+
+	if adapter, found = Adapters[adapterID]; found {
+		if mail.Template != nil {
+			sendHandler = adapter.SendTemplateEmail
+		} else {
+			sendHandler = adapter.Send
+		}
+
+		if sendSync {
+			err = sendHandler(mail, options)
+		}else {
+			go sendHandler(mail, options)
+		}
+	}
+	
+	return
+}

+ 63 - 20
api/mongo.go

@@ -15,6 +15,7 @@ import (
 	"time"
 
 	"git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/api/errs"
+	"git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/api/types"
 	"github.com/davecgh/go-spew/spew"
 	"github.com/jeremywohl/flatten"
 	"github.com/kataras/iris"
@@ -348,7 +349,7 @@ func (t *Mongo) RemoveMany(f *Filter) (res *mongo.DeleteResult, err *errs.Error)
 	}()
 
 	f.CheckQuery = true
-	if (f.Options != nil ) {
+	if f.Options != nil {
 		deleteOptions = f.Options.(*options.DeleteOptions)
 	}
 
@@ -361,7 +362,7 @@ func (t *Mongo) RemoveMany(f *Filter) (res *mongo.DeleteResult, err *errs.Error)
 		); lerr != nil {
 			err = errs.FromError(lerr)
 
-		} 
+		}
 		// else if res.DeletedCount == 0 {
 		// 	err = errs.NotFound().Details(&errs.Detail{
 		// 		Message: "No entity has been deleted",
@@ -865,6 +866,9 @@ func (t *Mongo) FindMany(f *Filter) (cursor *mongo.Cursor, err *errs.Error) {
 		wg := sync.WaitGroup{}
 		wg.Add(2)
 
+		out, _ := json.Marshal(f.Query)
+		fmt.Println("))))))))))))))))))))))", string(out))
+
 		go func() {
 			var countError error
 			defer wg.Done()
@@ -913,26 +917,41 @@ func (t *Mongo) FindMany(f *Filter) (cursor *mongo.Cursor, err *errs.Error) {
 					err = errs.FromError(lerr)
 					return
 				}
-				orderOperator := map[int]string{
-					1:  "$gt",
-					-1: "$lt",
-				}
 
-				if f.Sort == nil {
-					f.Sort = &bson.M{}
-				}
+				if f.Sort != nil {
+					orderOperator := map[int]string{
+						1:  "$gte",
+						-1: "$lte",
+					}
+					var firstPropOrder *int
+
+					for prop, order := range *f.Sort {
+						value := data[fmt.Sprintf(".%s", prop)]
+						if prop == "_id" {
+							value = bson.M{"$oid": value}
+						}
+						nextPageQuery[prop] = bson.M{
+							orderOperator[order.(int)]: value,
+						}
+						if firstPropOrder == nil {
+							firstPropOrder = types.Int(order.(int))
+						}
+					}
 
-				if (*f.Sort)["_id"] == nil {
-					(*f.Sort)["_id"] = 1
-				}
+					if (*f.Sort)["_id"] == nil {
 
-				for prop, order := range *f.Sort {
-					value := data[fmt.Sprintf(".%s", prop)]
-					if prop == "_id" {
-						value = bson.M{"$oid": value}
-					}
-					nextPageQuery[prop] = bson.M{
-						orderOperator[order.(int)]: value,
+						if firstPropOrder == nil {
+							firstPropOrder = types.Int(1)
+						}
+
+						orderOperator = map[int]string{
+							1:  "$gt",
+							-1: "$lt",
+						}
+
+						nextPageQuery["_id"] = bson.M{
+							orderOperator[*firstPropOrder]: bson.M{"$oid": data["._id"]},
+						}
 					}
 				}
 
@@ -940,9 +959,15 @@ func (t *Mongo) FindMany(f *Filter) (cursor *mongo.Cursor, err *errs.Error) {
 					err = errs.FromError(lerr)
 					return
 				}
+
 				f.NextPageToken = primitive.NewObjectID().Hex()
 				t.FindManyNextPaginationMux.Lock()
 				NextPageTokenMap[f.NextPageToken] = string(out)
+
+				// fmt.Println("=========================================\n")
+				// fmt.Println("string(out):", string(out))
+				// fmt.Println("=========================================\n\n")
+
 				t.FindManyNextPaginationMux.Unlock()
 			}
 			entitiesValue.Elem().Set(slicev)
@@ -1044,7 +1069,6 @@ func (t *Mongo) exec(f *Filter, execAction execfn, errorAction func(*errs.Error)
 		ctx, _ = context.WithTimeout(context.Background(), time.Minute)
 	}
 
-	
 	fmt.Println("###############", t.client == nil)
 
 	collection := t.client.Database(f.DB).Collection(f.Collection)
@@ -1053,6 +1077,25 @@ func (t *Mongo) exec(f *Filter, execAction execfn, errorAction func(*errs.Error)
 	return
 }
 
+func (this *Mongo) CreateCollection(createOptions *Filter) (exists bool, err *errs.Error) {
+
+	// createCmd := bson.D{
+	// 	{"create", createOptions.Collection},
+	// }
+	// sess := this.client.StartSession()
+	// sess.
+	return
+
+	// if sess != nil {
+	// 	err := mongo.WithSession(mtest.Background, sess, func(sc mongo.SessionContext) error {
+	// 		return mt.DB.RunCommand(sc, createCmd).Err()
+	// 	})
+	// 	return err
+	// }
+	// return mt.DB.RunCommand(mtest.Background, createCmd).Err()
+	// }
+}
+
 func createDebugEvent(options *Filter, eventType string, fn func(event *DebugEvent)) {
 	// debug := options.Context.Values().Get("#debug")
 	if options.Context != nil {

+ 60 - 0
api/types/types.go

@@ -0,0 +1,60 @@
+package types
+
+import (
+	"encoding/json"
+
+	"git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/api/errs"
+)
+
+type Map = map[string]interface{}
+
+func String(str string) *string {
+	return &str;
+}
+
+func True() *bool {
+	value := true
+	return &value
+}
+
+func False() *bool {
+	value := false
+	return &value
+}
+
+func Bool(value bool) *bool {
+	return &value
+}
+
+func Int(value int) *int {
+	return &value
+}
+
+func Int32(value int32) *int32 {
+	return &value
+}
+
+func Int64(value int64) *int64 {
+	return &value
+}
+
+func Float64(value float64) *float64 {
+	return &value
+}
+
+func Float32(value float32) *float32 {
+	return &value
+}
+
+func JSON(data interface{}) (jsonData string,err *errs.Error) {
+	out, errorMarshal := json.Marshal(data)
+	if errorMarshal != nil {
+		err = errs.Internal().Details(&errs.Detail{
+			Reason: "failedConvertToJSON",
+			Message : errorMarshal.Error(),
+		})
+	}else {
+		jsonData = string(out)
+	}
+	return
+}

+ 4 - 5
api/utils.go

@@ -61,11 +61,11 @@ func (this *references) Int64(value int64) *int64 {
 	return &value
 }
 
-func (this *references) Float32(value float32) *float32 {
+func (this *references) Float64(value float64) *float64 {
 	return &value
 }
 
-func (this *references) Float64(value float32) *float32 {
+func (this *references) Float32(value float32) *float32 {
 	return &value
 }
 
@@ -101,8 +101,7 @@ type EntityModel struct {
 // 	return model.Rules
 // }
 
-
-func PasswordBcryptHash(password string)(hash string, err *errs.Error) { 
+func PasswordBcryptHash(password string) (hash string, err *errs.Error) {
 	var (
 		bytes  []byte
 		errgen error
@@ -110,7 +109,7 @@ func PasswordBcryptHash(password string)(hash string, err *errs.Error) {
 
 	if bytes, errgen = bcrypt.GenerateFromPassword(
 		[]byte(password),
-		14,
+		10,
 	); errgen != nil {
 		err = errs.Internal().Details(&errs.Detail{
 			Reason:  "passwordHashFailed",

+ 4 - 1
build.sh

@@ -1,3 +1,6 @@
 #!/bin/bash
+# BUILD_ID=`uuidgen |tr -d '-'`
+# echo $BUILD_ID
 GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o eon-amd64 && \
-docker build -t eon-compile:0.0.1 .
+docker build -t eoncompiler/eon-compile:latest . && \
+rm eon-amd64

+ 6 - 9
commands/compile.go

@@ -4,8 +4,8 @@ import (
 	"fmt"
 
 	. "git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/common"
-	. "git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/gen"
 	"git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/flag"
+	. "git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/gen"
 	"github.com/davecgh/go-spew/spew"
 )
 
@@ -14,12 +14,10 @@ func compile() (err error) {
 
 	fmt.Println("COMPILE WITH SETUP...", *flag.Mode, *flag.BuildProfile, *flag.Out)
 	// Cria um novo projeto a partir do diretorio atual
-	if project, err = CreateProject(*flag.Mode); err != nil {
+	if project, err = CreateProject(); err != nil {
 		panic(err)
 	}
-
-	project.OutDirectory(*flag.Out)
-
+	
 	// Executa a geracao de codigo para o projeto
 	if err = project.Build(&BuildOptions{
 		Mode: *flag.BuildProfile,
@@ -28,9 +26,8 @@ func compile() (err error) {
 		panic(err)
 	}
 	// Salva o json contendo a descricao completa do projeto
-
-	if err = project.Save(fmt.Sprintf("%s/project.gen.json", *flag.Out)); err != nil {
-		panic(err)
-	}
+	// if err = project.Save(fmt.Sprintf("%s/project.gen.json", *flag.Out)); err != nil {
+	// 	panic(err)
+	// }
 	return
 }

+ 7 - 10
commands/serve.go

@@ -4,16 +4,16 @@ import (
 	"fmt"
 	"time"
 
+	"encoding/json"
+	"os"
+	"path/filepath"
+
 	. "git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/common"
 	. "git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/gen"
-	"git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/flag"
+	"github.com/fsnotify/fsnotify"
 	"github.com/kataras/iris/v12"
 	"github.com/kataras/iris/v12/middleware/logger"
 	"github.com/kataras/iris/v12/middleware/recover"
-	"github.com/fsnotify/fsnotify"
-	"os"
-	"path/filepath"
-	"encoding/json"
 )
 
 var watcher, _ = fsnotify.NewWatcher()
@@ -27,7 +27,7 @@ func serve() (err error) {
 
 	fmt.Println("Serve WITH SETUP...")
 	// Cria um novo projeto a partir do diretorio atual
-	if project, err = CreateProject(*flag.Mode); err != nil {
+	if project, err = CreateProject(); err != nil {
 		panic(err)
 	}
 
@@ -70,7 +70,7 @@ func serve() (err error) {
 					fmt.Println("modified file:", event.Name)
 					fmt.Println("update...")
 					time.Sleep(time.Second)
-					if project, err = CreateProject(*flag.Mode); err != nil {
+					if project, err = CreateProject(); err != nil {
 						panic(err)
 					}
 					
@@ -96,9 +96,6 @@ func serve() (err error) {
 		}
 	}()
 
-
-	project.OutDirectory(*flag.Out)
-
 	app := iris.New()
 	app.Logger().SetLevel("debug")
 	// Optionally, add two built'n handlers

+ 47 - 11
common/models.go

@@ -92,8 +92,6 @@ func ImportMap(base string) string {
 }
 
 type Project struct {
-	OutPath                   string                                                      `json:"outPath"`
-	CurrentDirectory          string                                                      `json:"outPath"`
 	Package                   string                                                      `json:"package"`
 	Kind                      string                                                      `json:"kind"`
 	Etag                      string                                                      `json:"etag"`
@@ -115,8 +113,10 @@ type Project struct {
 	Middlewares               []string                                                    `json:"middlewares"`
 	ServicePath               string                                                      `json:"servicePath"`
 	GitRepository             string                                                      `json:"git.repository"`
+	HasMetrics                bool                                                        `json:"hasMetrics"`
 	Environment               Environment                                                 `json:"environment"`
 	Variables                 map[string]interface{}                                      `json:"variables"`
+	Metrics                   map[string]*Metric                                          `json:"metrics"`
 	Resource                  *Resource                                                   `json:"-"`
 	Schemas                   []*Entity                                                   `json:"schemas"`
 	SchemasRef                map[string]*Entity                                          `json:"-"`
@@ -133,6 +133,45 @@ type Project struct {
 	ACL                       *ACL                                                        `json:"acl"`
 	Custom                    map[string]interface{}                                      `json:"custom"`
 	TranslatorBuildOptionsMap map[string]func(*Project, *BuildOptions) (*BuildSet, error) `json:"-"`
+	Paths					  PathMap													  `json:"paths"`
+}
+
+type PathMap map[string]string
+
+func (paths PathMap) Format(id, format string, arguments ...interface{} ) string {
+	path, found := paths[id]
+	if !found {
+		path = ""
+	}
+	return path + fmt.Sprintf(format, arguments...)
+}
+
+func (paths PathMap) Dist(format string, arguments ...interface{} ) string {
+	return paths.Format("dist", format , arguments...)
+}
+func (paths PathMap) Build(format string, arguments ...interface{} ) string {
+	return paths.Format("build", format , arguments...)
+}
+func (paths PathMap) Current(format string, arguments ...interface{} ) string {
+	return paths.Format("current", format , arguments...)
+}
+func (paths PathMap) Include(format string, arguments ...interface{} ) string {
+	return paths.Format("include", format , arguments...)
+}
+func (paths PathMap) Project(format string, arguments ...interface{} ) string {
+	return paths.Format("project", format , arguments...)
+}
+
+type Metric struct {
+	Description string   			  `json:"description"`
+	Props       map[string]*Parameter       `json:"props"`
+	Return      *MetricReturn `json:"return"`
+}
+
+type MetricReturn struct {
+	Type 		string  		  `json:"type"`
+	Range 		bool 	  		  `json:"range"`
+	Props       map[string]*Parameter   `json:"props"`
 }
 
 type ACL struct {
@@ -187,11 +226,12 @@ type Scope struct {
 }
 
 type EnvironmentVariable struct {
-	ID          string `json:"id"`
-	CamelID     string `json:"-"`
-	Default     string `json:"default"`
-	Required    bool   `json:"required,omitempty"`
-	Description string `json:"description"`
+	ID          string  `json:"id"`
+	CamelID     string  `json:"-"`
+	Default     string  `json:"default"`
+	Required    bool    `json:"required,omitempty"`
+	Reference   *string `json:"reference,omitempty"`
+	Description string  `json:"description"`
 }
 
 type Environment map[string]*EnvironmentVariable
@@ -750,10 +790,6 @@ func (project *Project) Build(options *BuildOptions) (err error) {
 	return
 }
 
-func (p *Project) OutDirectory(path string) {
-	p.OutPath = path
-}
-
 func (p *Project) Client(id string) *Client {
 	for _, c := range p.Clients {
 		if c.Id == id {

+ 0 - 1
common/utils.go

@@ -105,7 +105,6 @@ func JsonParseMode(path, mode string, v interface{}) (err error) {
 	if err = ParseJson(path+".json", v); err != nil {
 		return
 	}
-	// fmt.Println(fmt.Sprintf("%s.%s.json", path, mode))
 
 	err = ParseJson(fmt.Sprintf("%s.%s.json", path, mode), v, true)
 	return

BIN
eon-amd64


+ 1 - 1
flag/flag.go

@@ -50,7 +50,7 @@ func Initialize() (err error) {
 		}
 	}()
 
-	Out = flag.String("out", "../build", "Target directory of the compilation.")
+	Out = flag.String("out", "../dist", "Target directory of the compilation.")
 
 	// todo add list of valid commands on erro
 	Command = os.Args[1]

+ 49 - 39
gen/gen.go

@@ -9,11 +9,18 @@ import (
 	"strings"
 
 	. "git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/common"
+	"git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/flag"
 	GO "git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/translate/got"
 	TS "git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/translate/tst"
 )
 
-func CreateProject(mode string) (*Project, error) {
+var (
+	expandTranscludeExpression = regexp.MustCompile(`"\$\._transclude_":(true|"\w+")`)
+	expandVarExpression        = regexp.MustCompile(`"\$(\.\w+)"`)
+	removeAllSpacesExpression  = regexp.MustCompile(`(\s|\t|\r|\n)+`)
+)
+
+func CreateProject() (*Project, error) {
 
 	var (
 		err              error
@@ -23,6 +30,7 @@ func CreateProject(mode string) (*Project, error) {
 		entity           *Entity
 		resource         *Resource
 		directory        string
+		mode 			 = *flag.Mode
 		paramAcceptFiled = map[string]bool{}
 		p                = &Project{
 			Mode:             mode,
@@ -46,30 +54,21 @@ func CreateProject(mode string) (*Project, error) {
 	if directory, err = os.Getwd(); err != nil {
 		return nil, err
 	}
+	root, _ := filepath.Abs("../")
+
+	p.Paths = PathMap{
+		"current": root,
+		"dist": fmt.Sprintf("%s/dist", root),
+		"build": fmt.Sprintf("%s/build", root),
+		"include": fmt.Sprintf("%s/project/include", root),
+		"project": fmt.Sprintf("%s/project", root),
+	}
 
-	p.CurrentDirectory = directory
-
-	// Carrega a configuracao default do projeto
-	// root := []string{fmt.Sprintf("%s/project.json", directory)}
-
-	// if mode != "" {
-	// 	root = append(root, fmt.Sprintf("%s/project.%s.json", directory, mode))
-	// }
-
-	// for _, file := range root {
-	// 	if file == "" {
-	// 		continue
-	// 	}
-	// 	if err = ParseJson(file, p); err != nil {
-	// 		return nil, err
-	// 	}
-	// }
-
-	if err = JsonParseMode(fmt.Sprintf("%s/project", directory), mode, p); err != nil {
+	if err = JsonParseMode(p.Paths.Project("/project"), mode, p); err != nil {
 		return nil, err
 	}
 
-	if err = ParseJson("queries.json", &p.Queries); err != nil {
+	if err = ParseJson(p.Paths.Project("/queries.json"), &p.Queries); err != nil {
 		p.Queries.Blacklistwords = map[string][]string{}
 		p.Queries.Queries = map[string]string{}
 	}
@@ -82,7 +81,7 @@ func CreateProject(mode string) (*Project, error) {
 		return nil, err
 	}
 
-	if err = ParseJson("common.json", &p.Resource); err != nil {
+	if err = ParseJson(p.Paths.Project("/common.json"), &p.Resource); err != nil {
 		p.Resource = &Resource{}
 	}
 
@@ -92,7 +91,7 @@ func CreateProject(mode string) (*Project, error) {
 		}
 	}
 
-	if err = JsonParseMode("env/environment", mode, &p.Environment); err != nil {
+	if err = JsonParseMode(p.Paths.Project("/env/environment"), mode, &p.Environment); err != nil {
 		return nil, err
 	}
 
@@ -100,8 +99,27 @@ func CreateProject(mode string) (*Project, error) {
 		variable.ID = id
 	}
 
+	p.Metrics = map[string]*Metric{}
 	// Carrega os arquivos de entidades localizados na pasta entities
-	path = fmt.Sprintf("%s/entities", directory)
+	// path = fmt.Sprintf("%s/metrics", directory)
+	path =  p.Paths.Project("/metrics")
+	if files, err = GetFiles(path); err == nil {
+		fmt.Println("Read metrics...")
+		for _, file := range files {
+			if file.Name()[0] == '*' {
+				continue
+			}
+			if !file.IsDir() {
+				if err = ParseJson(filepath.Join(path, file.Name()), &p.Metrics); err != nil {
+					return nil, err
+				}
+			}
+		}
+	}
+	p.HasMetrics = len(p.Metrics)>0
+	
+	// Carrega os arquivos de entidades localizados na pasta entities
+	path = p.Paths.Project("/entities")
 	if files, err = GetFiles(path); err == nil {
 		fmt.Println("Read entities...")
 		for _, file := range files {
@@ -119,7 +137,7 @@ func CreateProject(mode string) (*Project, error) {
 	}
 
 	// Carrega os arquivos de recursos localizados na pasta resources
-	path = fmt.Sprintf("%s/resources", directory)
+	path = p.Paths.Project("/resources")
 	if files, err = GetFiles(path); err == nil {
 		fmt.Println("Read resources...")
 		for _, file := range files {
@@ -249,14 +267,15 @@ func CreateProject(mode string) (*Project, error) {
 
 func readBuildVersion(project *Project, directory string) {
 	var (
-		filename = fmt.Sprintf("%s/buildversion", directory)
+		filename = project.Paths.Project("/.buildversion")
 		build    = ""
 		buildInt = 0
 		err      error
 	)
-	// defer func() {
-	// 	FilePutContents(filename, strconv.Itoa(buildInt), 0777)
-	// }()
+
+	defer func() {
+		FilePutContents(filename, strconv.Itoa(buildInt), 0777)
+	}()
 
 	if build, err = FileGetContents(filename); err != nil {
 		build = "0"
@@ -317,10 +336,6 @@ func interpolateProject(project *Project) (err error) {
 		}
 	}
 
-	// enviroment variables
-
-	//
-
 	for _, variable := range project.Environment {
 		variable.Default = ResolveParams(variable.Default, data)
 	}
@@ -328,11 +343,6 @@ func interpolateProject(project *Project) (err error) {
 	return
 }
 
-var (
-	expandTranscludeExpression = regexp.MustCompile(`"\$\._transclude_":(true|"\w+")`)
-	expandVarExpression        = regexp.MustCompile(`"\$(\.\w+)"`)
-	removeAllSpacesExpression  = regexp.MustCompile(`(\s|\t|\r|\n)+`)
-)
 
 func loadQueries(project *Project, directory string) (err error) {
 	var (
@@ -340,7 +350,7 @@ func loadQueries(project *Project, directory string) (err error) {
 		data     string
 		queryKey string
 	)
-	path := fmt.Sprintf("%s/queries", directory)
+	path := project.Paths.Project("/queries")
 
 	if files, err = GetFiles(path); err == nil {
 		fmt.Println("Read queries...")

+ 5 - 1
go.mod

@@ -7,6 +7,8 @@ require (
 	git.eugeniocarvalho.dev/eugeniucarvalho/utils v1.0.2
 	github.com/CloudyKit/fastprinter v0.0.0-20170127035650-74b38d55f37a // indirect
 	github.com/DataDog/zstd v1.4.4 // indirect
+	github.com/ahmdrz/goinsta/v2 v2.4.5 // indirect
+	github.com/aws/aws-sdk-go v1.35.19
 	github.com/buger/goterm v0.0.0-20200322175922-2f3e71b85129
 	github.com/dave/jennifer v1.4.0
 	github.com/davecgh/go-spew v1.1.1
@@ -24,11 +26,13 @@ require (
 	github.com/kataras/iris/v12 v12.1.3
 	github.com/pascaldekloe/jwt v1.7.0
 	github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
+	github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e // indirect
+	github.com/tcnksm/go-input v0.0.0-20180404061846-548a7d7a8ee8 // indirect
+	github.com/theckman/go-ipdata v0.7.2 // indirect
 	github.com/xdg/stringprep v1.0.0 // indirect
 	go.mongodb.org/mongo-driver v1.3.2
 	golang.org/x/crypto v0.0.0-20191219195013-becbf705a915
 	golang.org/x/net v0.0.0-20200528225125-3c3fba18258b // indirect
 	golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e // indirect
 	gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
-	gopkg.in/yaml.v2 v2.2.7 // indirect
 )

+ 13 - 23
go.sum

@@ -1,7 +1,3 @@
-git.eugeniocarvalho.dev/eugeniucarvalho/gg v1.0.0 h1:BcjI7XjCPLrcFeGeV3gJzt8Mf981eAG7Jf2X+fLGL0Q=
-git.eugeniocarvalho.dev/eugeniucarvalho/gg v1.0.0/go.mod h1:MsGB35SSYCc7sCff9PcM08TAd9UvFhFhXMvU3STh82k=
-git.eugeniocarvalho.dev/eugeniucarvalho/gg v1.0.1 h1:vMtnzkyW0NdUtL7/M0ihbLkE06zXzwyGKmLNmfxnRNs=
-git.eugeniocarvalho.dev/eugeniucarvalho/gg v1.0.1/go.mod h1:Uw49/w2AVJNPUDR8uiRVb0cyGg5vy1bThuggLwnziFo=
 git.eugeniocarvalho.dev/eugeniucarvalho/gg v1.0.2 h1:oqhoKd/7GD0oim7Oy+08mBWqkiWf2w1kkTjs310+XcU=
 git.eugeniocarvalho.dev/eugeniucarvalho/gg v1.0.2/go.mod h1:Uw49/w2AVJNPUDR8uiRVb0cyGg5vy1bThuggLwnziFo=
 git.eugeniocarvalho.dev/eugeniucarvalho/utils v1.0.2 h1:pi9aCd86+20NXV+QYITfUuEhY9rqv14mWeuBoT9sLq0=
@@ -13,17 +9,18 @@ github.com/CloudyKit/fastprinter v0.0.0-20170127035650-74b38d55f37a h1:3SgJcK9l5
 github.com/CloudyKit/fastprinter v0.0.0-20170127035650-74b38d55f37a/go.mod h1:EFZQ978U7x8IRnstaskI3IysnWY5Ao3QgZUKOXlsAdw=
 github.com/CloudyKit/jet v2.1.3-0.20180809161101-62edd43e4f88+incompatible h1:rZgFj+Gtf3NMi/U5FvCvhzaxzW/TaPYgUYx3bAPz9DE=
 github.com/CloudyKit/jet v2.1.3-0.20180809161101-62edd43e4f88+incompatible/go.mod h1:HPYO+50pSWkPoj9Q/eq0aRGByCL6ScRlUmiEX5Zgm+w=
-github.com/DataDog/zstd v1.4.4 h1:+IawcoXhCBylN7ccwdwf8LOH2jKq7NavGpEPanrlTzE=
 github.com/DataDog/zstd v1.4.4/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
 github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY=
 github.com/Joker/jade v1.0.1-0.20190614124447-d475f43051e7 h1:mreN1m/5VJ/Zc3b4pzj9qU6D9SRQ6Vm+3KfI328t3S8=
 github.com/Joker/jade v1.0.1-0.20190614124447-d475f43051e7/go.mod h1:6E6s8o2AE4KhCrqr6GRJjdC/gNfTdxkIXvuGZZda2VM=
 github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398 h1:WDC6ySpJzbxGWFh4aMxFFC28wwGp5pEuoTtvA4q/qQ4=
 github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0=
+github.com/ahmdrz/goinsta/v2 v2.4.5/go.mod h1:XUEELCWd3hVSqADejqxTa8Uc7Yto9cb6a6HrfkGwVf8=
 github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
+github.com/aws/aws-sdk-go v1.35.19 h1:vdIqQnOIqTNtvnOdt9r3Bf/FiCJ7KV/7O2BIj4TPx2w=
+github.com/aws/aws-sdk-go v1.35.19/go.mod h1:tlPOdRjfxPBpNIwqDj61rmsnA85v9jc0Ps9+muhnW+k=
 github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible h1:Ppm0npCCsmuR9oQaBtRuZcmILVE74aXE+AmrJj8L2ns=
 github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g=
-github.com/buger/goterm v0.0.0-20200322175922-2f3e71b85129 h1:gfAMKE626QEuKG3si0pdTRcr/YEbBoxY+3GOH3gWvl4=
 github.com/buger/goterm v0.0.0-20200322175922-2f3e71b85129/go.mod h1:u9UyCz2eTrSGy6fbupqJ54eY5c4IC8gREQ1053dK12U=
 github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
 github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
@@ -50,7 +47,6 @@ github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV
 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
 github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc=
 github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98=
-github.com/go-fsnotify/fsnotify v0.0.0-20180321022601-755488143dae h1:PeVNzgTRtWGm6fVic5i21t+n5ptPGCZuMcSPVMyTWjs=
 github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
 github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
 github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0=
@@ -106,6 +102,9 @@ github.com/iris-contrib/schema v0.0.1 h1:10g/WnoRR+U+XXHWKBHeNy/+tZmM2kcAVGLOsz+
 github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw=
 github.com/jeremywohl/flatten v1.0.1 h1:LrsxmB3hfwJuE+ptGOijix1PIfOoKLJ3Uee/mzbgtrs=
 github.com/jeremywohl/flatten v1.0.1/go.mod h1:4AmD/VxjWcI5SRB0n6szE2A6s2fsNHDLO0nAlMHgfLQ=
+github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
+github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
+github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
 github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
 github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
 github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
@@ -129,8 +128,6 @@ github.com/kataras/sitemap v0.0.5 h1:4HCONX5RLgVy6G4RkYOV3vKNcma9p236LdGOipJsaFE
 github.com/kataras/sitemap v0.0.5/go.mod h1:KY2eugMKiPwsJgx7+U103YZehfvNGOXURubcGyk0Bz8=
 github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
 github.com/klauspost/compress v1.9.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
-github.com/klauspost/compress v1.9.4 h1:xhvAeUPQ2drNUhKtrGdTGNvV9nNafHMUkRyLkzxJoB4=
-github.com/klauspost/compress v1.9.4/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
 github.com/klauspost/compress v1.9.5 h1:U+CaK85mrNNb4k8BNOfgJtJ/gr6kswUCFj6miSzVC6M=
 github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@@ -161,9 +158,9 @@ github.com/pascaldekloe/jwt v1.7.0/go.mod h1:TKhllgThT7TOP5rGr2zMLKEDZRAgJfBbtKy
 github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
 github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo=
 github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
-github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
 github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
-github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
 github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
@@ -178,6 +175,7 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV
 github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
 github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
 github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
+github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
 github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
 github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
 github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
@@ -188,8 +186,9 @@ github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DM
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
-github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/tcnksm/go-input v0.0.0-20180404061846-548a7d7a8ee8/go.mod h1:IlWNj9v/13q7xFbaK4mbyzMNwrZLaWSHx/aibKIZuIg=
+github.com/theckman/go-ipdata v0.7.2/go.mod h1:ibU+1MWRdXpFzO0uiDSpOxNATeLeWdN4KQnGMJpJbQI=
 github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
 github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
 github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
@@ -199,8 +198,6 @@ github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc/go.mod h1:Jhud4/sHM
 github.com/xdg/stringprep v1.0.0 h1:d9X0esnoa3dFsV0FG35rAT0RIhYFlPq7MiP+DW89La0=
 github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
 github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
-go.mongodb.org/mongo-driver v1.2.0 h1:6fhXjXSzzXRQdqtFKOI1CDw6Gw5x6VflovRpfbrlVi0=
-go.mongodb.org/mongo-driver v1.2.0/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
 go.mongodb.org/mongo-driver v1.3.2 h1:IYppNjEV/C+/3VPbhHVxQ4t04eVW0cLp0/pNdW++6Ug=
 go.mongodb.org/mongo-driver v1.3.2/go.mod h1:MSWZXKOynuguX+JSvwP8i+58jYCXxbia8HS3gZBapIE=
 golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@@ -211,16 +208,12 @@ golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8U
 golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20191219195013-becbf705a915 h1:aJ0ex187qoXrJHPo8ZasVTASQB7llQP6YeNzgDALPRk=
 golang.org/x/crypto v0.0.0-20191219195013-becbf705a915/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/net v0.0.0-20181220203305-927f97764cc3 h1:eH6Eip3UpmR+yM/qI9Ijluzb1bNv/cAU/n+6l8tRSis=
 golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 h1:efeOvDhwQ29Dj3SdAV/MJf8oukgn+8D8WgaCaRMchF8=
 golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjutRKlBEZQ6wTn8ozI/nI=
 golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20200528225125-3c3fba18258b h1:IYiJPiJfzktmDAO1HQiwjMjwjlYKHAL7KzeD544RJPs=
 golang.org/x/net v0.0.0-20200528225125-3c3fba18258b/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
@@ -237,7 +230,6 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb h1:fgwFCsaw9buMuxNd6+DQfAuSFqbNiQZpcgJQAgJsK6k=
 golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
 golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -247,12 +239,10 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.org/x/tools v0.0.0-20190327201419-c70d86f8b7cf h1:++r/Kj1CfG42p6XntDItK1TfB5V6Vq/baDeKvV1q5gY=
 golang.org/x/tools v0.0.0-20190327201419-c70d86f8b7cf/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
-golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d h1:bt+R27hbE7uVf7PY9S6wpNg9Xo2WRe/XQT0uGq9RQQw=
 golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -263,5 +253,5 @@ gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno=
 gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
 gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo=
-gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
+gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

+ 7 - 3
translate/got/build.go

@@ -22,8 +22,7 @@ var Build = func(project *Project, buildOptions *BuildOptions) (fn *BuildSet, er
 		}
 	)
 
-	path := fmt.Sprintf("%s/include/go", project.CurrentDirectory)
-	if files, err = GetFiles(path); err == nil {
+	if files, err = GetFiles(project.Paths.Include("/go")); err == nil {
 		for _, file := range files {
 			if file.Name()[0] == '*' {
 				continue
@@ -43,9 +42,14 @@ var Build = func(project *Project, buildOptions *BuildOptions) (fn *BuildSet, er
 		After: []*Command{
 			{
 				Id:          "build",
-				Cmd:         "GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o server",
+				Cmd:         "GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o ../dist/server",
 				Description: "Compila a aplicação server da api",
 			},
+			// {
+			// 	Id:          "clear",
+			// 	Cmd:         "",
+			// 	Description: "Clear temporary files",
+			// },
 		},
 	}
 	return

+ 1 - 6
translate/got/constants.go

@@ -63,10 +63,5 @@ func CreateVariables(p *Project) error {
 
 	file.Add(filterFunctionList...)
 
-	return Write(fmt.Sprintf("%s/%s/models/variables_gen.go", p.OutPath, p.Package), file)
+	return Write(p.Paths.Build("/%s/models/variables_gen.go", p.Package), file)
 }
-
-// ctx, _ = `).Qual("context", "WithTimeout").Call(
-// 	G.Qual("context", "Background()"),
-// 	G.Lit(30).Op("*").Qual("time", "Second"),
-// ).Id(`

+ 34 - 27
translate/got/environment.go

@@ -1,7 +1,6 @@
 package got
 
 import (
-	"fmt"
 	"text/template"
 
 	. "git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/common"
@@ -18,41 +17,49 @@ func init() {
 	environmentStmtsTmpl, environmentStmtsErr = ParseTemplate(`
 
 	import (
+		"os"
 		"fmt"
 		common "git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/common"
-		"os"
 	)
 	
-	const (
-		{{range .variables}} Env{{.CamelID}} = "{{.ID}}"
+	var (
+		{{range .variables}} {{.CamelID}} = "{{.Default}}"
 		{{end}}
+		value     string
+		variables = []common.EnvironmentVariable{
+			{{range .variables}}{
+				ID:          "{{.ID}}",
+				Description: "{{.Description}}",
+				Required:    {{.Required}},
+				Reference:  & {{.CamelID}},
+				Default:     "{{.Default}}",
+			},{{end}}
+		}
 	)
+	
+	func init(){
+		for _, variable := range variables {			
+			value = os.Getenv(variable.ID)
 
-	func InitEnvironment() error {
-		var (
-			value     string
-			variables = []common.EnvironmentVariable{
-				{{range .variables}}{
-					ID:          Env{{.CamelID}},
-					Description: "{{.Description}}",
-					Required:    {{.Required}},
-					Default:     "{{.Default}}",
-				},{{end}}
+			if variable.Required && value == "" &&  *variable.Reference == "" {
+				panic(fmt.Errorf("Environment Variable '%s' not defined! %s", variable.ID, variable.Description))
 			}
-		)
-	
-		for _, variable := range variables {
-			if value = os.Getenv(variable.ID); value == "" {
-				if variable.Default == "" && variable.Required {
-					panic(fmt.Errorf("Environment Variable '%s' not defined! %s", variable.ID, variable.Description))
-				}
-				value = variable.Default
+			
+			if value != "" {
+				// remove in future
+				common.Setenv(variable.ID, value)
+				*variable.Reference = value
 			}
-			common.Setenv(variable.ID, value)
 		}
+	}
+
+	func InitEnvironment() error {
 		fmt.Println("Environment...")
-		for _, pair := range os.Environ() {
-			fmt.Printf("\t├ %s\n",pair)
+		// for _, pair := range os.Environ() {
+		// 	fmt.Printf("\t├ %s\n",pair)
+		// }
+		for _, variable := range variables {
+			fmt.Printf("\t├ %s: %s\n",variable.ID, *variable.Reference)
 		}
 		return nil
 	}`)
@@ -72,9 +79,9 @@ func CreateEnvironment(p *Project) error {
 
 	out, _ := TemplateToString(environmentStmtsTmpl, context)
 
-	file := G.NewFile(p.Package)
+	file := G.NewFile("env")
 
 	file.Id(out)
 
-	return Write(fmt.Sprintf("%s/%s/environment.go", p.OutPath, p.Package), file)
+	return Write(p.Paths.Build("/%s/env/variables.go", p.Package), file)
 }

+ 0 - 3
translate/got/functions.go

@@ -17,14 +17,11 @@ func generateHookCall(project *Project, method *Method, hookId string) {
 
 	path := fmt.Sprintf(
 		"../project/include/go/hook_%s_%s_%s_gen.go",
-		// project.OutPath,
-		// project.Package,
 		method.Entity,
 		method.ID,
 		hookId,
 	)
 
-	// return
 	if _, fileErr := os.Stat(path); os.IsNotExist(fileErr) {
 
 		methodId := fmt.Sprintf(

+ 3 - 1
translate/got/middleware_delete.go

@@ -134,7 +134,7 @@ var (
 				relations        = SR.Get(method.Entity)
 				relationCount    = len(relations)
 				dependenceMethod = BASE_HAS_DEPENDE + method.Entity
-				createDepFunc    = SR.Has(method.Entity)
+				createDepFunc    = SR.Has(method.Entity) && dependenceMethodDeclared[method.Entity] != true
 				beforeSend       = method.Hook("beforeSend")
 				beforePersist    = method.Hook("beforePersist")
 				context          = map[string]interface{}{
@@ -152,6 +152,8 @@ var (
 					"beforeResponse":   parseMethodActions(method.BeforeResponse),
 				}
 			)
+
+			dependenceMethodDeclared[method.Entity] = true
 			// Nome do metodo que verifica se a entidade tem dependencias
 
 			out, _ := TemplateToString(deleteStmtsTmpl, context)

+ 21 - 9
translate/got/middleware_main.go

@@ -8,6 +8,7 @@ import (
 	"git.eugeniocarvalho.dev/eugeniucarvalho/utils"
 	G "github.com/dave/jennifer/jen"
 	"github.com/davecgh/go-spew/spew"
+	"go.mongodb.org/mongo-driver/bson/primitive"
 	// . "git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/gen"
 )
 
@@ -24,7 +25,7 @@ func CreateMainFile(project *Project) (err error) {
 	address = strings.Replace(address, "//", "", -1)
 
 	Index.Id(`import (
-	
+		env `).Lit(goPackageRepository+"/build/v1/env").Id(`
 		`).Id(project.ID).Lit(goPackageRepository+"/build/v1").Id(`
 		models `).Lit(goPackageRepository+"/build/v1/models").Id(`
 		"git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/api" // Pacotes do framework web
@@ -39,8 +40,8 @@ func CreateMainFile(project *Project) (err error) {
 		var (
 			err error
 		)
-	
-		if err = `).Id(project.ID).Id(`.InitEnvironment(); err != nil {
+		
+		if err = env.InitEnvironment(); err != nil {
 			panic(err)
 		}
 
@@ -59,8 +60,10 @@ func CreateMainFile(project *Project) (err error) {
 		// session := &api.Mongo{ Config: os.Getenv("MONGO_CONFIG") }
 		models.Api.Config = os.Getenv("MONGO_CONFIG")
 	
-		if err = models.Api.Init(); err != nil {
-			panic(err)
+		if models.Api.Config != "" {
+			if err = models.Api.Init(); err != nil {
+				panic(err)
+			}
 		}
 		
 		if err = `).Id(fmt.Sprintf("%s.AppInitialize(app)", project.ID)).Id(`; err != nil {
@@ -70,16 +73,25 @@ func CreateMainFile(project *Project) (err error) {
 		`).Id(project.ID).Id(`.Register(app)
 
 		fmt.Println("API_VERSION: ", api.BuildVersion)
-		app.Run(iris.Addr(os.Getenv("APP_ADDRS")), iris.WithoutServerError(iris.ErrServerClosed))
+		fmt.Println("BUILD_VERSION: ", `).Lit(primitive.NewObjectID().Hex()).Id(`)
+
+		// app.Run(iris.Addr(os.Getenv("APP_ADDRS")), iris.WithoutServerError(iris.ErrServerClosed))
+		// app.Run(, iris.WithoutServerError(iris.ErrServerClosed))
+
+		// $ openssl req -new -newkey rsa:4096 -x509 -sha256 \
+		// -days 365 -nodes -out cert.crt -keyout key.key
+		app.Run(
+			iris.TLS(os.Getenv("APP_ADDRS"),"cert.crt","key.key"),
+			iris.WithoutServerError(iris.ErrServerClosed),
+		)
 	}
 	`)
 
-	if err = Write(fmt.Sprintf("%s/main.go", project.OutPath), Index); err != nil {
+	if err = Write(project.Paths.Build("/main.go"), Index); err != nil {
 		return
 	}
 
-	// path := fmt.Sprintf("%s/v1/app_initialize.go", project.OutPath)
-	path := fmt.Sprintf("../project/include/go/app_initialize.go")
+	path := project.Paths.Include("/go/app_initialize.go")
 
 	if !utils.FileExists(path) {
 

+ 135 - 0
translate/got/middleware_metric.go

@@ -0,0 +1,135 @@
+package got
+
+import (
+	"fmt"
+	"strings"
+	"text/template"
+
+	. "git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/common"
+	"git.eugeniocarvalho.dev/eugeniucarvalho/utils"
+	G "github.com/dave/jennifer/jen"
+)
+
+func CreateMetricFiles(project *Project) (err error) {
+
+	if !project.HasMetrics {
+		return
+	}
+
+	if err = createMetricIndex(project); err != nil {
+		return
+	}
+
+	if err = createMetricHandler(project); err != nil {
+		return
+	}
+	return nil
+}
+
+func createMetricIndex(project *Project) (err error) {
+
+	var (
+		Index               = G.NewFile("metrics")
+		metricsTmpl *template.Template
+		out string
+	)
+	
+	metricsTmpl, err = ParseTemplate(`
+	import (
+		"github.com/eugeniucarvalho/metric-query-parser/parser"
+	)
+
+	func InitMetrics() {
+		{{range .metrics}}
+		// {{.description}}
+		parser.RegisterHandler("{{.id}}", {{.functionId}} )
+		{{end}}
+	}
+	`)
+
+	metrics := []map[string]interface{}{}
+	
+	for id, metric  := range project.Metrics {
+		metrics = append(metrics, map[string]interface{}{
+			"id": id,
+			"functionId": strings.Title(id),
+			"description": metric.Description,
+		})
+	}
+
+	context:= map[string]interface{}{
+		"metrics": metrics,
+	}
+
+	if out, err = TemplateToString(metricsTmpl, context); err != nil {
+		return
+	}
+	
+	Index.Id(out)
+		
+	err = Write(project.Paths.Include("/go/metrics/index_gen.go"), Index)
+	return
+}
+
+func createMetricHandler(project *Project) (err error) {
+
+	var (
+		metricsTmpl *template.Template
+		out string
+	)
+	
+	metricsTmpl, err = ParseTemplate(`
+
+	{{if .metric.Return.Props}}
+	type {{.functionId}}Result struct {
+		{{range $id, $prop := .metric.Return.Props}}
+		{{$prop.ID}} {{$prop.Type}}
+		{{end}}
+	}
+	{{end}}
+
+	// {{.metric.Description}}
+	func {{.functionId}}(props map[string]interface{}) (result interface{}, err error) {
+		// TO DO....		 
+		return {{.return}}, nil
+	}
+	`)
+
+	for id, metric  := range project.Metrics {
+		path := project.Paths.Include("/go/metrics/%s_gen.go", id)
+
+		if utils.FileExists(path) {
+			continue
+		}
+		functionId := strings.Title(id)
+		returnValue := `""`
+
+
+		if metric.Return.Props != nil {
+			returnValue = fmt.Sprintf("%sResult{}", functionId)
+			for propId, prop := range metric.Return.Props {
+				prop.ID = strings.Title(propId)
+			}
+		}
+		
+		if metric.Return.Range {
+			returnValue = fmt.Sprintf("[]%s", returnValue)
+		}
+		
+		context:= map[string]interface{}{
+			"id": id,
+			"functionId": functionId,
+			"metric": metric,
+			"return": returnValue,
+		}
+
+		if out, err = TemplateToString(metricsTmpl, context); err != nil {
+			return
+		}
+
+		Index := G.NewFile("metrics")
+		Index.Id(out)
+		err = Write(path, Index)
+	}
+	return
+}

+ 34 - 0
translate/got/middleware_metric_handler.go

@@ -0,0 +1,34 @@
+package got
+
+import (
+	G "github.com/dave/jennifer/jen"
+)
+
+var (
+	parser          = "github.com/eugeniucarvalho/metric-query-parser/parser"
+	GenMetricsStmts = &Middleware{
+		Id:   "metrics",
+		Type: "method",
+		Fn: func(ctx *MiddlewareContext) error {
+			ctx.Statement.Block(G.Id(`
+			var (
+				metrics    =  `).Qual(parser, "MetricsMap").Values().Id(`
+				errResolve error
+			)
+		
+			if err = api.ReadJson(ctx, &metrics); err != nil {
+				return
+			}
+		
+			if resp, errResolve = `).Qual(parser, "NewMetricQueryParser").Call().Id(`.Resolve(metrics); errResolve != nil {
+				err = errs.Internal().Details(&errs.Detail{
+					Reason:  "metricHandlerError",
+					Message: errResolve.Error(),
+				})
+			}
+			return`)).Line()
+
+			return nil
+		},
+	}
+)

+ 4 - 2
translate/got/middleware_patch.go

@@ -29,8 +29,10 @@ func init() {
 	values := ctx.Values()
 	values.Set("patchs", patchs)
 	entity.LastUpdate = api.NowUnix()
-	user := values.Get("$user.ref").(*models.UserReference)
-	entity.UpdatedBy = user
+	user, hasUserRef := values.Get("$user.ref").(*models.UserReference)
+	if hasUserRef {
+		entity.UpdatedBy = user
+	}
 	values.Set("entity", entity)
 	{{if .entityAlias }} 
 	values.Set("{{.entityAlias}}", entity) 

+ 5 - 4
translate/got/middleware_post.go

@@ -36,12 +36,13 @@ func init() {
 		return
 	}
 
-	user := values.Get("$user.ref").(*models.UserReference)
-	entity.CreatedBy = user
-	entity.UpdatedBy = user
+	user, hasUserRef := values.Get("$user.ref").(*models.UserReference)
+	if hasUserRef {
+		entity.CreatedBy = user
+		entity.UpdatedBy = user
+	}
 	entity.SetMode("create")
 
-
 	if err = api.Validate(entity); err != nil {
 		return
 	}

+ 5 - 2
translate/got/middleware_put.go

@@ -31,8 +31,11 @@ func init() {
 
 	values := ctx.Values()
 	entity.LastUpdate = api.NowUnix()
-	user := values.Get("$user.ref").(*models.UserReference)
-	entity.UpdatedBy = user
+	
+	user, hasUserRef := values.Get("$user.ref").(*models.UserReference)
+	if hasUserRef {
+		entity.UpdatedBy = user
+	}
 	values.Set("entity", entity)
 	
 	{{if .preconditions}}

+ 9 - 13
translate/got/middleware_undelete.go

@@ -26,11 +26,13 @@ func init() {
 	values.Set("patchs", patchs)
 	values.Set("entity", entity)
 
-	user := values.Get("$user.ref").(*models.UserReference)
-	
-	entity.SetDeleted(false)
+	user, hasUserRef := values.Get("$user.ref").(*models.UserReference)
+	if hasUserRef {
+		entity.UpdatedBy = user
+	}
 	entity.LastUpdate = api.NowUnix()
-	entity.UpdatedBy = user
+	entity.SetDeleted(false)
+	
 
 	{{if .preconditions}}
 		if _, err = executeAction(
@@ -85,10 +87,9 @@ var (
 				beforeSend    = method.Hook("beforeSend")
 				beforePersist = method.Hook("beforePersist")
 				context       = map[string]interface{}{
-					"dbName":         dbName,
-					"collectionName": collectionName,
-					"entity":         method.Entity,
-					// "createDepFunc":    createDepFunc,
+					"dbName":           dbName,
+					"collectionName":   collectionName,
+					"entity":           method.Entity,
 					"relationCount":    relationCount,
 					"relations":        relations,
 					"dependenceMethod": dependenceMethod,
@@ -103,11 +104,6 @@ var (
 			out, _ := TemplateToString(undeleteStmtsTmpl, context)
 			ctx.Statement.Block(G.Id(out)).Line()
 
-			// if createDepFunc {
-			// 	out, _ = TemplateToString(hasDepUndeleteStmtsTmpl, context)
-			// 	afterMethod.Id(out)
-			// }
-
 			return nil
 		},
 	}

+ 1 - 1
translate/got/middlewares.go

@@ -38,5 +38,5 @@ func CreateMiddleware(p *Project, middle *Middleware) error {
 		return err
 	}
 
-	return Write(fmt.Sprintf("%s/%s/middleware_%s.go", p.OutPath, p.Package, middle.Id), file)
+	return Write(p.Paths.Build("/%s/middleware_%s.go", p.Package, middle.Id), file)
 }

+ 1 - 1
translate/got/params.go

@@ -34,5 +34,5 @@ func createParamsFile(p *Project) (err error) {
 		}
 	}`)
 	// `).Id(string(out)).Id(`
-	return Write(fmt.Sprintf("%s/%s/params.go", p.OutPath, p.Package), file)
+	return Write(p.Paths.Build("/%s/params.go", p.Package), file)
 }

+ 76 - 85
translate/got/resources.go

@@ -39,6 +39,7 @@ var (
 		"get_list":  GenGetStmtsList,
 		"undelete":  GenUndeleteStmts,
 		"implement": GenImplement,
+		"metrics":   GenMetricsStmts,
 	}
 	ResourceWG = sync.WaitGroup{}
 )
@@ -84,12 +85,7 @@ func CreateDummy(p *Project, resource *Resource, method *Method) error {
 	// Verifica se existe um arquivo na pasta de include.
 	// Caso o arquivo não exista um novo arquivo é criado.
 
-	// outputfile := fmt.Sprintf("%s/include/go/api_%s_%s.go", CurrentDirectory, strings.ToLower(resource.ID), strings.ToLower(method.ID))
-	outputfile := fmt.Sprintf(
-		"../project/include/go/api_%s_%s_gen.go",
-		strings.ToLower(resource.ID),
-		strings.ToLower(method.ID),
-	)
+	outputfile := p.Paths.Include("/go/api_%s_%s_gen.go",strings.ToLower(resource.ID),strings.ToLower(method.ID))
 
 	if _, err := os.Stat(outputfile); os.IsNotExist(err) {
 
@@ -215,7 +211,7 @@ func GenResources(p *Project) (err error) {
 
 		// GenCall(f, resource)
 
-		path = fmt.Sprintf("%s/%s/api_%s_gen.go", p.OutPath, p.Package, strings.ToLower(resource.ID))
+		path = p.Paths.Build("/%s/api_%s_gen.go", p.Package, strings.ToLower(resource.ID))
 
 		if err = Write(path, file); err != nil {
 			return err
@@ -257,7 +253,7 @@ func GenQueries(p *Project, resourcesIdMap map[string]bool) {
 
 	func init() {`).Do(queries).Id(`}`)
 
-	if err := Write(fmt.Sprintf("%s/%s/%s_gen.go", p.OutPath, p.Package, "queries"), file); err != nil {
+	if err := Write(p.Paths.Build("/%s/%s_gen.go", p.Package, "queries"), file); err != nil {
 		panic(err)
 	}
 }
@@ -281,31 +277,26 @@ func GenIndexApi(p *Project) error {
 	statments = append(statments, G.Id(fmt.Sprintf("%s := ", callActionId)).Qual(API_URL, "CallAction"))
 	statments = append(statments, RequestParams)
 
-	// statments = append(statments)
-
 	// Inicializa o mapa de filtros da api
 	Index.Id(`
-		import(
-			// "reflect"
-			// "runtime"
-			// "strings"
-			"fmt"
-		)
+	import(
+		"fmt"
+	)
+	var (
+		filtersApiReference = map[string]*`).Qual(CODE_GEN_V2_COMMON, "ApiFilter").Id(`{}
+		FormatSelection = map[string]string{}
+		Debug = api.NewDebug()
+	)
+	func init(){
 		var (
-			filtersApiReference = map[string]*`).Qual(CODE_GEN_V2_COMMON, "ApiFilter").Id(`{}
-			FormatSelection = map[string]string{}
-			Debug = api.NewDebug()
-		)
-		func init(){
-			var (
-				entity *common.ApiFilter
-				files []`).Qual("os", "FileInfo").Id(`
-				path  = "./filters"
+			entity *common.ApiFilter
+			files []`).Qual("os", "FileInfo").Id(`
+			path  = "./filters"
 				err   error
 			)
 
 			files, _ = `).Qual(CODE_GEN_V2_COMMON, "GetFiles").Id(`(path)
-
+			
 			for _, file := range files {
 				if !file.IsDir() {
 					entity = &common.ApiFilter{}  
@@ -315,20 +306,29 @@ func GenIndexApi(p *Project) error {
 					filtersApiReference[entity.Id] = entity
 				}
 			}
-
-		}
-
-		type Action struct {
-			Name string
-			Fn func(context.Context) (interface{}, *`).Qual(API_ERROR, "Error").Id(`)
+			
+			`).Do(func(s *G.Statement) {
+		if p.HasMetrics {
+			s.Add(G.Line().
+				Comment("Register metric handlers").
+				Line().
+				Qual(fmt.Sprintf("%s/build/%s/metrics", p.Custom["go.package.repository"].(string), p.Package), "InitMetrics").
+				Call())
 		}
-
-		func executeAction(ctx context.Context, actions []Action) (resp interface{},err *errs.Error){
-			var (
-				stopPropagation bool
-				// parts []string
-				event *api.DebugEvent
-			)
+	}).Id(`
+			}
+			
+			type Action struct {
+				Name string
+				Fn func(context.Context) (interface{}, *`).Qual(API_ERROR, "Error").Id(`)
+			}
+			
+			func executeAction(ctx context.Context, actions []Action) (resp interface{},err *errs.Error){
+				var (
+					stopPropagation bool
+					// parts []string
+					event *api.DebugEvent
+				)
 			debug, debugActive := ctx.Values().Get("#debug").(*api.DebugTaks);
 			
 			for _, action := range actions {
@@ -437,6 +437,39 @@ func GenIndexApi(p *Project) error {
 	// 	G.Id(fmt.Sprintf(`FilterHandle("../api/%s/filters")`, p.Package)),
 	// ))
 
+	// if p.HasMetrics {
+	// 	statments = append(statments, G.Line().
+	// 		Comment("Register metric handlers").
+	// 		Line().
+	// 		Qual(fmt.Sprintf("%s/build/%s/metrics", p.Custom["go.package.repository"].(string), p.Package), "InitMetrics").
+	// 		Call(),
+	// 	)
+
+	// 	statments = append(statments, G.Line().Comment("Metrics handler").Line().Id("app").Dot("Handle").Call(
+	// 		G.Lit("POST"),
+	// 		G.Lit("/api/v1/metrics"),
+	// 		G.Id(`apply("JWT(\"metrics:query\",jwtchk)", JWT("metrics:query", jwtchk))`),
+	// 		G.Id(`apply("metrics", func(ctx context.Context) (resp interface{}, err *errs.Error) {
+	// 			var (
+	// 				metrics      = `).Qual("github.com/eugeniucarvalho/metric-query-parser/parser", "MetricsMap").Values().Id(`
+	// 				errResolve error
+	// 			)
+
+	// 			if err = api.ReadJson(ctx, &metrics); err != nil {
+	// 				return
+	// 			}
+
+	// 			if resp, errResolve = `).Qual("github.com/eugeniucarvalho/metric-query-parser/parser", "NewMetricQueryParser").Call().Id(`.Resolve(metrics); errResolve != nil {
+	// 				err = errs.Internal().Details(&errs.Detail{
+	// 					Reason:  "metricHandlerError",
+	// 					Message: errResolve.Error(),
+	// 				})
+	// 			}
+	// 			return
+	// 		})`),
+	// 	))
+	// }
+
 	// Cria a funcao que trata os metodos options
 	statments = append(statments, G.Line().Comment("Options request").Line().Id("app").Dot("Options").Call(
 		G.Lit("/{url:path}"),
@@ -458,7 +491,7 @@ func GenIndexApi(p *Project) error {
 
 	go GenQueries(p, queryIndexsMap)
 
-	return Write(fmt.Sprintf("%s/%s/api_index_gen.go", p.OutPath, p.Package), Index)
+	return Write(p.Paths.Build("/%s/api_index_gen.go", p.Package), Index)
 }
 
 func GenMethod(p *Project, f *G.File, r *Resource, method *Method) error {
@@ -497,10 +530,7 @@ func GenMethod(p *Project, f *G.File, r *Resource, method *Method) error {
 
 func generateActionCommonFile(p *Project) (err error) {
 
-	path := fmt.Sprintf(
-		"%s/include/go/actions/index_gen.go",
-		CurrentDirectory,
-	)
+	path := p.Paths.Include("/go/actions/index_gen.go")
 
 	if _, fileErr := os.Stat(path); os.IsNotExist(fileErr) {
 
@@ -530,17 +560,9 @@ func generateActionsFiles(p *Project, f *G.File, r *Resource, method *Method) {
 
 	for _, action := range actions {
 
-		path := fmt.Sprintf(
-			"%s/include/go/actions/%s_gen.go",
-			CurrentDirectory,
-			action.ID,
-			// method.Entity,
-			// method.ID,
-			// hookId,
-		)
+		path := p.Paths.Include("/go/actions/%s_gen.go", action.ID)
 
 		if _, fileErr := os.Stat(path); os.IsNotExist(fileErr) {
-			// methodId := fmt.Sprintf("%s%s%s", strings.Title(hookId), method.Entity, strings.Title(method.ID))
 
 			file := G.NewFile("actions")
 			context := map[string]interface{}{
@@ -560,35 +582,6 @@ func generateActionsFiles(p *Project, f *G.File, r *Resource, method *Method) {
 			Write(path, file)
 		}
 	}
-
-	// for hookId, _ := range method.Hooks {
-
-	// 	// methodId := fmt.Sprintf("%s%s%s", strings.Title(hookId), method.Entity, strings.Title(method.ID))
-
-	// 	path := fmt.Sprintf(
-	// 		"%s/include/go/actions/%s_%s_%s_gen.go",
-	// 		CurrentDirectory,
-	// 		method.Entity,
-	// 		method.ID,
-	// 		hookId,
-	// 	)
-
-	// 	if _, fileErr := os.Stat(path); os.IsNotExist(fileErr) {
-
-	// 		file := G.NewFile(p.Package)
-
-	// 		context := map[string]interface{}{
-	// 			"imports": map[string]string{
-	// 				// "api":     "git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/api",
-	// 				"errs":    "git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/api/errs",
-	// 				"context": "github.com/kataras/iris/v12/context",
-	// 			},
-	// 		}
-	// 		out, _ := TemplateToString(hookStmtsTmpl, context)
-	// 		file.Id(out).Line()
-	// 		Write(path, file)
-	// 	}
-	// }
 }
 
 func GenFromGenericModel(p *Project, entity *EntityInfo) {
@@ -691,9 +684,7 @@ func GenFromGenericModel(p *Project, entity *EntityInfo) {
 	)
 
 	// Salva o arquivo da entidade
-	// if err := f.Save(fmt.Sprintf("%s/%s/%s_gen.go", p.OutPath, p.Package, filename)); err != nil {
-	// fmt.Printf("%s/%s/%s_gen.go", p.OutPath, p.Package, filename)
-	if err := Write(fmt.Sprintf("%s/%s/%s_gen.go", p.OutPath, p.Package, filename), file); err != nil {
+	if err := Write(p.Paths.Build("/%s/%s_gen.go", p.Package, filename), file); err != nil {
 		panic(err)
 	}
 }

+ 3 - 5
translate/got/schemas.go

@@ -585,8 +585,7 @@ func GenSchemas(p *Project) error {
 		}
 		// Salva o arquivo da entidade
 
-		// if err := f.Save(fmt.Sprintf("%s/%s/%s_gen.go", p.OutPath, p.Package, filename)); err != nil {
-		if err := Write(fmt.Sprintf("%s/%s/%s_gen.go", p.OutPath, p.Package, filename), f); err != nil {
+		if err := Write(p.Paths.Build("/%s/%s_gen.go", p.Package, filename), f); err != nil {
 			return err
 		}
 	} // Fim do for de schema
@@ -618,7 +617,7 @@ func GenModelIndex(p *Project) error {
 		G.Id("Api").Op("=").Op("&").Qual(API_URL, "Mongo").Values(),
 	).Line()
 
-	return Write(fmt.Sprintf("%s/%s/models/index_gen.go", p.OutPath, p.Package), Index)
+	return  Write(p.Paths.Build("/%s/models/index_gen.go", p.Package), Index)
 }
 
 func fill(p *Project, schema *Entity) (*Entity, error) {
@@ -774,8 +773,7 @@ func GenFilterEntityDocument(p *Project) error {
 			return err
 		}
 
-		path = fmt.Sprintf("%s/filters/%s.json", p.OutPath, strings.ToLower(s.ID))
-		// fmt.Printf("storing filter '%s'\n",path)
+		path = p.Paths.Dist("/filters/%s.json", strings.ToLower(s.ID)) 
 		if err = FilePutContents(path, content, 0777); err != nil {
 			return err
 		}

+ 36 - 87
translate/got/translate.go

@@ -12,133 +12,82 @@ import (
 )
 
 var (
-	OutputDirectory  string
-	CurrentDirectory string
+	dependenceMethodDeclared = map[string]bool{}
 )
 
 func Translate(p *Project) (err error) {
 
-	if err = initGlobalVars(p); err != nil {
-		fmt.Println("error initGlobalVars")
-		return
-	}
-	if err = CreateMainFile(p); err != nil {
-		fmt.Println("error CreateMainFile")
-		return
-	}
-	if err = createParamsFile(p); err != nil {
-		fmt.Println("error createParamsFile")
-		return
-	}
-
-	if err = CreateEnvironment(p); err != nil {
-		fmt.Println("error CreateEnvironment")
-		return
-	}
-
-	if err = CreateVariables(p); err != nil {
-		fmt.Println("error CreateVariables")
-		return
-	}
-
-	if err = GenSchemas(p); err != nil {
-		fmt.Println("error GenSchemas")
-		return
+	handlers := map[string]func(*Project) error {
+		"CreateMainFile":CreateMainFile,
+		"CreateMetricFiles":CreateMetricFiles,
+		"createParamsFile":createParamsFile,
+		"CreateEnvironment":CreateEnvironment,
+		"CreateVariables":CreateVariables,
+		"GenSchemas":GenSchemas,
+		"GenResources":GenResources,
+		"GenMiddlewares":GenMiddlewares,
 	}
 
-	if err = GenResources(p); err != nil {
-		fmt.Println("error GenResources")
-		return
-	}
-
-	if err = GenMiddlewares(p); err != nil {
-		fmt.Println("error GenMiddlewares")
-		return
+	for stage, fn := range handlers {
+		if err = fn(p); err != nil {
+			return fmt.Errorf("[%s] %s",stage,err.Error())
+		}
 	}
-
 	return include(p)
 }
 
-func createSymbolicLinks(basedir string) func(string, os.FileInfo, error) error {
+func createSymbolicLinks(p *Project) func(string, os.FileInfo, error) error {
 	var (
-		callback func(string, os.FileInfo, error) error
-		input    []byte
-		relative = func(path string) string {
-			return fmt.Sprintf("%s/%s%s", OutputDirectory, "v1", strings.Replace(filepath.Dir(path), basedir, "", 1))
-		}
+		basedir  = p.Paths.Include("/go")
+		fileContent    []byte
 	)
 
-	callback = func(pathX string, infoX os.FileInfo, errX error) (err error) {
+	return  func(sourcePath string, fileInfo os.FileInfo, errX error) (err error) {
 
 		if errX != nil {
-			fmt.Printf("error 「%v」 at a path 「%q」\n", errX, pathX)
+			fmt.Printf("error 「%v」 at a path 「%q」\n", errX, sourcePath)
 			return errX
 		}
+		
+		relativePath := strings.Replace(sourcePath, basedir, "", 1)
+		
+		if relativePath == "" {
+			return
+		}
 
-		if infoX.IsDir() {
-			relativedir := strings.Replace(pathX, basedir, "", 1)
-			if relativedir != "" {
-
-				// fmt.Println("crinado diretorio", fmt.Sprintf("%s/%s%s", OutputDirectory, "v1", relativedir))
-
-				os.MkdirAll(fmt.Sprintf("%s/%s%s", OutputDirectory, "v1", relativedir), 0777)
-			}
+		if fileInfo.IsDir() {
+			os.MkdirAll(p.Paths.Build("/%s/%s", p.Package, relativePath), 0777)
 
 		} else {
-			// fmt.Println("crinado link symbolico aqui", relative(pathX))
-			// os.Symlink(pathX, filepath.Join(relative(pathX), infoX.Name()))
 
-			if input, err = ioutil.ReadFile(pathX); err != nil {
+			if fileContent, err = ioutil.ReadFile(sourcePath); err != nil {
 				return
 			}
 
-			// fmt.Println("READ FILE", pathX, filepath.Join(relative(pathX), infoX.Name()))
-
 			if err = ioutil.WriteFile(
-				filepath.Join(relative(pathX), infoX.Name()),
-				input,
-				0644,
+				p.Paths.Build("/%s/%s", p.Package, relativePath),
+				fileContent,
+				0777,
 			); err != nil {
 				return
 			}
-
-			// fmt.Printf("  dir ------ : 「%v」\n", pathX)
-			// fmt.Printf("  dir: 「%v」\n", strings.Replace(filepath.Dir(pathX), basedir, "", 1))
-			// fmt.Printf("  file name 「%v」\n", infoX.Name())
-			// fmt.Printf("  extenion: 「%v」\n", filepath.Ext(pathX))
-			// fmt.Printf("  target: 「%v」\n", relative(pathX))
-			// fmt.Sprintf("%s/%s%s", OutputDirectory, "v1", strings.Replace(filepath.Dir(pathX), basedir, "", 1)),
 		}
 
 		return nil
 	}
-	return callback
+	
 }
 
 func include(p *Project) error {
 	var err error
-
-	if err = exec.Command("sh", "-c", fmt.Sprintf("find %s -type l -delete", OutputDirectory)).Run(); err != nil {
+	
+	delete := fmt.Sprintf("find %s -type l -delete", p.Paths.Build(""))
+	if err = exec.Command("sh", "-c", delete).Run(); err != nil {
 		fmt.Println("include error ", err)
 	}
 
-	basedir := fmt.Sprintf("%s/include/go", CurrentDirectory)
-
-	if err = filepath.Walk(basedir, createSymbolicLinks(basedir)); err != nil {
+	if err = filepath.Walk(p.Paths.Include("/go"), createSymbolicLinks(p)); err != nil {
 		return err
 	}
 	return err
 }
-
-func initGlobalVars(p *Project) error {
-	var err error
-
-	if CurrentDirectory, err = os.Getwd(); err != nil {
-		return err
-	}
-
-	if OutputDirectory, err = filepath.Abs(CurrentDirectory + "/" + p.OutPath); err != nil {
-		return err
-	}
-	return nil
-}

+ 94 - 85
translate/tst/auth.go

@@ -29,6 +29,8 @@ func createAuthClass(p *Project, file *TS.File) {
     };
     
     protected oauthURI: string;
+    protected AuthorizeRequest: Subscription;
+    protected authorizeStatus = new EventEmitter<boolean>();
 
     // constructor(protected api: `).Id(ApiClassName(p)).Raw(`) {
     constructor(protected api: ApiInterface) {
@@ -64,32 +66,37 @@ func createAuthClass(p *Project, file *TS.File) {
             );
     }
     Authorize(): Observable<any> {
-        return this.getAuthCode().pipe(
-            take(1),
-            switchMap(code => {
-                // console.log('(get code)', code);
-                return this.getAccessToken({ code });
-            }),
-            catchError(err => {
-                console.log('(catch erro grant)', err);
-                switch (err) {
-                case '':
-                  return this.getAccessToken({
-                    request_type: 'refreshToken',
-                    refresh_token: this.grant.refresh_token
-                  });
-                case '':
-                  err = { type: err };
-                }
-                throw err;
-            }),
-            tap(grant => {
-                // console.log('(set grant )', grant);
-                this.setGrant(grant);
-                // this.api.poolReady.map(callback => callback());
-                this.onAuthorize$.next(grant);
-            }),
-        );
+        if (!this.AuthorizeRequest) {
+            this.AuthorizeRequest = this.getAuthCode().pipe(
+                take(1),
+                switchMap(code => {
+                    return this.getAccessToken({ code });
+                }),
+                catchError(err => {
+                    console.log('(catch erro grant)', err);
+                    switch (err) {
+                        case '':
+                            return this.getAccessToken({
+                                request_type: 'refreshToken',
+                                refresh_token: this.grant.refresh_token
+                            });
+                        case '':
+                            err = { type: err };
+                    }
+                    throw err;
+                }),
+                take(1),
+            ).subscribe(
+                grant => {
+                    this.AuthorizeRequest = null;
+                    this.setGrant(grant);
+                    this.onAuthorize$.next(grant);
+                    this.authorizeStatus.next(grant);
+                },
+                this.authorizeStatus.error
+            );
+        }
+        return this.authorizeStatus.pipe(take(1));
     }
     Token() {
         const g = this.grant;
@@ -121,7 +128,7 @@ func createAuthClass(p *Project, file *TS.File) {
     protected setGrant(grant) {
         this.grant = grant;
         // recupera os dados do usuario
-        setTimeout(() => this.getProfile().subscribe(data => this.profile$.next(data)));
+        // setTimeout(() => this.getProfile().subscribe(data => this.profile$.next(data)));
     }
     protected location(path = '/oauth2/authorize'): URL {
         // Solicita autorização par ao servidor de autenticacao caso não exista um token e nem um codigo
@@ -135,9 +142,11 @@ func createAuthClass(p *Project, file *TS.File) {
         return new Observable<string>(ob => {
             const oauth2 = document.createElement('iframe'),
                 url = this.location();
-
             oauth2.id = `).Raw("`iframe-${Math.random().toString(36)}`").Raw(`;
-
+            Object.assign(oauth2.style, {
+                position:'fixed',
+                top:'-10000px',
+            })
             url.searchParams.set('redirect_uri', oauth2.id);
             
             function listenAccessCode(event) {
@@ -161,66 +170,66 @@ func createAuthClass(p *Project, file *TS.File) {
 
               oauth2.onload = () => {
                 if (!oauth2.contentDocument) {
-                  window.postMessage({ 'type': 'access_code', 'error': 'unauthorized' }, '*');
+                  window.postMessage({ type: 'access_code', error: 'unauthorized' }, '*');
                 }
-              }
+              };
             
         });
     }
 	`))
 }
 
-        // return new Observable<any>(observer => {
-        //     // Verifica se existe um usuario logado
-        //     // Quando o usuario não está logado ele é redirecionado para o servidor de autenticacao
-        //     if (!(`).Raw(fmt.Sprintf("/\\s%s=([^;]+);?/gm.exec(", p.Auth.AuthTokenID)).Raw("` ${document.cookie}`").Raw(`))) {
-        //         window.location.href = this.location('/signin').href;
-        //     }
-
-        //     const res = (g, success = true) => {
-        //         let f;
-        //         if (success) {
-        //             observer.next(g);
-        //             while (f = this.api.poolReady.shift()){
-        //                 f();
-        //             }
-        //         } else {
-        //             observer.error(g);
-        //         }
-        //         observer.complete();
-        //     };
-        //     // Se existe um token de authorizacao
-        //     if (this.grant) {
-        //         this.setGrant(this.grant);
-        //         res(this.grant);
-        //         return;
-        //     }
-        //     this.getAuthCode().subscribe(
-        //         code => {
-        //             const done = (grant) => {
-        //                 this.setGrant(grant);
-        //                 res(this.grant);
-        //             };
-
-        //             this.getAccessToken({
-        //                 code: code
-        //             }).subscribe(
-        //                 grant => done(grant),
-        //                 _ => {
-        //                     // Falha ao recuperar o token ( não existe ou expirou)
-        //                     this.getAccessToken({
-        //                         request_type: 'refreshToken',
-        //                         refresh_token: this.grant.refresh_token
-        //                     }).subscribe(
-        //                         grant => done(grant),
-        //                         error => res(error, false)
-        //                     );
-        //                 });
-        //         },
-        //         // Não conseguiu obter o codigo de autenticacao
-        //         // acao tomada: redirecionar para a tela de login do sistema
-        //         error => {
-        //             // window.location.href = `).Raw("`${this.oauthURI}/signout`").Raw(`;
-        //         }
-        //     );
-        // });
+// return new Observable<any>(observer => {
+//     // Verifica se existe um usuario logado
+//     // Quando o usuario não está logado ele é redirecionado para o servidor de autenticacao
+//     if (!(`).Raw(fmt.Sprintf("/\\s%s=([^;]+);?/gm.exec(", p.Auth.AuthTokenID)).Raw("` ${document.cookie}`").Raw(`))) {
+//         window.location.href = this.location('/signin').href;
+//     }
+
+//     const res = (g, success = true) => {
+//         let f;
+//         if (success) {
+//             observer.next(g);
+//             while (f = this.api.poolReady.shift()){
+//                 f();
+//             }
+//         } else {
+//             observer.error(g);
+//         }
+//         observer.complete();
+//     };
+//     // Se existe um token de authorizacao
+//     if (this.grant) {
+//         this.setGrant(this.grant);
+//         res(this.grant);
+//         return;
+//     }
+//     this.getAuthCode().subscribe(
+//         code => {
+//             const done = (grant) => {
+//                 this.setGrant(grant);
+//                 res(this.grant);
+//             };
+
+//             this.getAccessToken({
+//                 code: code
+//             }).subscribe(
+//                 grant => done(grant),
+//                 _ => {
+//                     // Falha ao recuperar o token ( não existe ou expirou)
+//                     this.getAccessToken({
+//                         request_type: 'refreshToken',
+//                         refresh_token: this.grant.refresh_token
+//                     }).subscribe(
+//                         grant => done(grant),
+//                         error => res(error, false)
+//                     );
+//                 });
+//         },
+//         // Não conseguiu obter o codigo de autenticacao
+//         // acao tomada: redirecionar para a tela de login do sistema
+//         error => {
+//             // window.location.href = `).Raw("`${this.oauthURI}/signout`").Raw(`;
+//         }
+//     );
+// });

+ 65 - 33
translate/tst/resources.go

@@ -53,8 +53,17 @@ func GenResources(p *Project) {
 	export class ServiceStmt {
 		
 		// constructor(protected api: `).Id(ApiClassName(p)).Raw(`) {}
-		constructor(protected api: ApiInterface) {}
-	
+		constructor(protected api: ApiInterface) {
+
+		}
+		
+		get authorized$(){ 
+			// return this.api.Auth.Authorize()
+			return this.api.Auth.grant
+			? of(true)
+			: this.api.Auth.Authorize().pipe(map(() => true))
+		}
+
 		public Url(u: string, opts: {}): string {
 			
 			(u.match(/{(\w+)}/gm)||[]).map(argExpression => {
@@ -66,6 +75,7 @@ func GenResources(p *Project) {
 			});
 			return u;
 		}
+
 	
 		_event<T = any>(url, opt: HttpOptions): Observable<EventSourcePolyfill> {
 			opt = this.api.options(opt);
@@ -183,7 +193,7 @@ func GenResources(p *Project) {
 		module.Line().Export().Class().Id(
 			angularResourceName,
 		// ).Extends().Id(fmt.Sprintf("%s<%s>",ServiceStmt, resource.Entity )).Block(
-		).Extends().Id(fmt.Sprintf("%s",ServiceStmt )).Block(
+		).Extends().Id(fmt.Sprintf("%s", ServiceStmt)).Block(
 			angularServiceStmtMethods...,
 		).Line()
 
@@ -492,7 +502,6 @@ func createClientClass(p *Project, file *TS.File) {
 
 }
 
-
 func GenAngularMethodStmt(p *Project, r *Resource, method *Method, methods *[]TS.CodeInterface, angularResourceName string) {
 
 	var (
@@ -501,10 +510,11 @@ func GenAngularMethodStmt(p *Project, r *Resource, method *Method, methods *[]TS
 		paramsHttp = []TS.CodeInterface{}
 		// id         = method.ID
 		// ret        = TS.Id("Observable")
-		param         = "entity"
-		template      string
-		templateValue interface{}
-		defined       bool
+		param          = "entity"
+		returnTemplate *TS.Group
+		template       string
+		templateValue  interface{}
+		defined        bool
 	)
 
 	if templateValue, defined = method.Custom["ts.template.method"]; defined {
@@ -514,12 +524,16 @@ func GenAngularMethodStmt(p *Project, r *Resource, method *Method, methods *[]TS
 	}
 
 	template = strings.ToLower(template)
+	entityType := method.Entity
+	if entityType == "" {
+		entityType = "any"
+	}
 
 	switch template {
 
 	case "post":
 		typ = "post"
-		params = append(params, TS.Id(param).Op(":").Id(method.Entity))
+		params = append(params, TS.Id(param).Op(":").Id(entityType))
 		// ret.TypeAliase(method.Entity)
 	case "filter":
 		typ = "get"
@@ -533,14 +547,14 @@ func GenAngularMethodStmt(p *Project, r *Resource, method *Method, methods *[]TS
 	case "put":
 		typ = "put"
 		// ret.TypeAliase(method.Entity)
-		params = append(params, TS.Id(param).Op(":").Id(method.Entity).Op("|").String())
+		params = append(params, TS.Id(param).Op(":").Id(entityType).Op("|").String())
 	case "delete":
 		typ = "delete"
 		// ret.TypeAliase(method.Entity)
 		// params = append(params, TS.Id(param).Op(":").Id(method.Entity).Op("|").String())
 	case "patch":
 		typ = "patch"
-		params = append(params, TS.Id(param).Op(":").Id(method.Entity).Op("|").String())
+		params = append(params, TS.Id(param).Op(":").Id(entityType).Op("|").String())
 		// ret.TypeAliase(method.Entity)
 		// params = append(params, TS.Id(param).Op(":").Id(method.Entity).Op("|").String())
 	case "sse":
@@ -552,17 +566,17 @@ func GenAngularMethodStmt(p *Project, r *Resource, method *Method, methods *[]TS
 
 	path := method.Path
 	for _, parameter := range method.Parameters {
-		
-	 alias := getCustom(parameter.Custom, "ts.api.alias")
-	 if aliasString, ok := alias.(string);ok {
-		path = strings.ReplaceAll(
-			path,
-			fmt.Sprintf("{%s}", parameter.ID),
-			fmt.Sprintf("{%s}", aliasString),
-		)
-	 }
+
+		alias := getCustom(parameter.Custom, "ts.api.alias")
+		if aliasString, ok := alias.(string); ok {
+			path = strings.ReplaceAll(
+				path,
+				fmt.Sprintf("{%s}", parameter.ID),
+				fmt.Sprintf("{%s}", aliasString),
+			)
+		}
 	}
-	
+
 	// paramsHttp = append(paramsHttp, TS.Raw("this.Url(url, opt.params)"))
 	paramsHttp = append(paramsHttp, TS.Raw(fmt.Sprintf("`${this.api.apiOptions.BASE_URL}%s`", path)))
 
@@ -574,26 +588,44 @@ func GenAngularMethodStmt(p *Project, r *Resource, method *Method, methods *[]TS
 
 	paramsHttp = append(paramsHttp, TS.Id("opt"))
 
-	response := strings.Replace(method.Response, "*", "",-1)
-	
-	if response == ""  {
+	response := strings.Replace(method.Response, "*", "", -1)
+
+	if response == "" {
 		response = method.Entity
 	}
+	if response == "" {
+		response = "any"
+	}
 
-	// *methods = append(*methods, TS.Id(method.ID).Params(params...).Op(":").Id("Observable<ServiceResponse>").Block(
-	*methods = append(*methods, TS.Id(method.ID).Params(params...).Block(
-		// TS.Raw("let opt = this.api.Options(this.options)").Endl(),
-		// TS.Raw("let url = ").Lit(p.GetUrlFromMethod(method)).Endl(),
-		// TS.Raw("let url = ").Raw(fmt.Sprintf("`${this.api.BASE_URL}%s`", method.Path)).Endl(),
-		TS.Line().Raw(
+	if getCustom(method.Custom, "client.authorization.required", true).(bool) {
+		returnTemplate = TS.Line().Raw(
+			fmt.Sprintf(`return this.authorized$.pipe(
+				switchMap(() => this._%s<%s>`,
+				typ,
+				response,
+			),
+		).Call(paramsHttp...).
+			Raw(")\n)").
+			Endl()
+	} else {
+		returnTemplate = TS.Line().Raw(
 			fmt.Sprintf(
 				"return this._%s<%s>",
-				 typ,
+				typ,
 				response,
 			),
-		).Call(paramsHttp...).Endl(),
-		// TS.Line().Raw(fmt.Sprintf("return this._%s", typ )).Call(paramsHttp...).Endl(),
+		).Call(paramsHttp...).
+			Endl()
+	}
+	// *methods = append(*methods, TS.Id(method.ID).Params(params...).Op(":").Id("Observable<ServiceResponse>").Block(
+	*methods = append(*methods, TS.Id(method.ID).Params(params...).Block(
+		returnTemplate,
 	).Line())
+	// TS.Raw("let opt = this.api.Options(this.options)").Endl(),
+	// TS.Raw("let url = ").Lit(p.GetUrlFromMethod(method)).Endl(),
+	// TS.Raw("let url = ").Raw(fmt.Sprintf("`${this.api.BASE_URL}%s`", method.Path)).Endl(),
+
+	// TS.Line().Raw(fmt.Sprintf("return this._%s", typ )).Call(paramsHttp...).Endl(),
 }
 
 // func GenAngularMethod(p *Project, r *Resource, method *Method, methods *[]TS.CodeInterface, angularResourceName string) {

+ 16 - 4
translate/tst/translate.go

@@ -16,7 +16,6 @@ func Translate(project *Project) (err error) {
 	ts := project.Client("angular6")
 
 	path := fmt.Sprintf("%s/%s.module.ts", ts.OutputDir, project.ID)
-	// Write(fmt.Sprintf("%s/%s/params.go", p.OutPath, p.Package), file)
 	module = TS.NewFile(path)
 
 	// Adiciona os importes necessarios
@@ -40,7 +39,7 @@ func imports(project *Project, file *TS.File) {
 	// import { BrowserModule } from '@angular/platform-browser';
 	import { CommonModule } from '@angular/common';
 	import { HttpClientModule, HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';
-	import { Observable, of, Subject, BehaviorSubject} from 'rxjs';
+	import { Observable, of, Subject, BehaviorSubject, Subscription} from 'rxjs';
 	// import { ActivatedRoute, Router } from '@angular/router';
 	import { catchError, map, switchMap, tap, take, filter } from 'rxjs/operators';
 	import { EventSourcePolyfill } from 'event-source-polyfill';
@@ -90,9 +89,22 @@ func imports(project *Project, file *TS.File) {
 	`).Line()
 }
 
-func getCustom(options map[string]interface{}, path string) (resp interface{}) {
+func getCustom(options map[string]interface{}, path string, fallback ...interface{}) (resp interface{}) {
+	found := false
 	if options != nil {
-		resp = options[path]
+		if resp, found = options[path]; found {
+			return
+		}
+	}
+	for _, value := range fallback {
+		resp = value
 	}
 	return
 }
+
+// func getCustom(options map[string]interface{}, path string) (resp interface{}) {
+// 	if options != nil {
+// 		resp = options[path]
+// 	}
+// 	return
+// }