|
@@ -0,0 +1,855 @@
|
|
|
+package common
|
|
|
+
|
|
|
+import (
|
|
|
+ "bytes"
|
|
|
+ "encoding/json"
|
|
|
+ "fmt"
|
|
|
+ "regexp"
|
|
|
+ "strconv"
|
|
|
+ "strings"
|
|
|
+ "text/template"
|
|
|
+
|
|
|
+ "git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/api"
|
|
|
+ "git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/api/errs"
|
|
|
+ ts "git.eugeniocarvalho.dev/eugeniucarvalho/gg/generators/typescript"
|
|
|
+ "github.com/kataras/iris/v12/context"
|
|
|
+ "go.mongodb.org/mongo-driver/bson/primitive"
|
|
|
+)
|
|
|
+
|
|
|
+const (
|
|
|
+ BSON = "go.mongodb.org/mongo-driver/bson"
|
|
|
+ BSONX = "go.mongodb.org/mongo-driver/x/bsonx"
|
|
|
+ MONGO = "go.mongodb.org/mongo-driver/mongo"
|
|
|
+ BSON_PRIMITIVE = "go.mongodb.org/mongo-driver/bson/primitive"
|
|
|
+ IRIS_CTX = "github.com/kataras/iris/v12/context"
|
|
|
+ IRIS = "github.com/kataras/iris/v12"
|
|
|
+ UPDATE_RELATION = "UpdateRelation"
|
|
|
+ BASE_HAS_DEPENDE = "HasDep"
|
|
|
+)
|
|
|
+
|
|
|
+var (
|
|
|
+ API_URL = "git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/api"
|
|
|
+ API_ERROR = "git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/api/errs"
|
|
|
+ CODE_GEN_V2_COMMON = "git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/common"
|
|
|
+ CODE_GEN_V2_AUTHORIZATION = "git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/authorization"
|
|
|
+
|
|
|
+ // Variavel de controle de acesso aos models da API.
|
|
|
+ Models = &api.Mongo{}
|
|
|
+
|
|
|
+ camelToUnderRegex = regexp.MustCompile(`([^[:lower:]])`)
|
|
|
+ //Generic e
|
|
|
+ Generic = regexp.MustCompile("(?P<type>[\\w-_]+)<(?P<dtype>[\\w\\*]+)>")
|
|
|
+ //GenericPart e
|
|
|
+ GenericPart = regexp.MustCompile("<(?P<id>[\\w\\*]+)>")
|
|
|
+ //ImportMap e
|
|
|
+ importMap = map[string]string{
|
|
|
+ "bson": BSON,
|
|
|
+ "primitive": BSON_PRIMITIVE,
|
|
|
+ }
|
|
|
+
|
|
|
+ SR = SchemasRelations{
|
|
|
+ R: map[string][]*Relation{},
|
|
|
+ }
|
|
|
+)
|
|
|
+
|
|
|
+type BuildOptions struct {
|
|
|
+ Mode string
|
|
|
+ IgnoreBuildSteps string
|
|
|
+ IgnoreBuildStepsValues map[int]bool
|
|
|
+}
|
|
|
+
|
|
|
+func (b *BuildOptions) IgnoreStep(step int) bool {
|
|
|
+ _, ok := b.IgnoreBuildStepsValues[step]
|
|
|
+ return ok
|
|
|
+}
|
|
|
+
|
|
|
+func (b *BuildOptions) Parse() error {
|
|
|
+ var (
|
|
|
+ value int
|
|
|
+ err error
|
|
|
+ )
|
|
|
+ if b.IgnoreBuildStepsValues == nil {
|
|
|
+ b.IgnoreBuildStepsValues = map[int]bool{}
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, v := range strings.Split(b.IgnoreBuildSteps, ",") {
|
|
|
+ if value, err = strconv.Atoi(v); err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ b.IgnoreBuildStepsValues[value] = true
|
|
|
+ }
|
|
|
+
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+func ImportMap(base string) string {
|
|
|
+ if v, ok := importMap[base]; ok {
|
|
|
+ return v
|
|
|
+ }
|
|
|
+ panic(fmt.Sprintf("Import %s não definido", base))
|
|
|
+}
|
|
|
+
|
|
|
+type Project struct {
|
|
|
+ OutPath string `json:"outPath"`
|
|
|
+ Package string `json:"package"`
|
|
|
+ Kind string `json:"kind"`
|
|
|
+ Etag string `json:"etag"`
|
|
|
+ Version string `json:"version"`
|
|
|
+ BuildVersion string `json:"buildVersion"`
|
|
|
+ ID string `json:"id"`
|
|
|
+ Name string `json:"name"`
|
|
|
+ DataBaseSufix string `json:"dataBaseSufix"`
|
|
|
+ Mode string `json:"mode"`
|
|
|
+ Revision string `json:"revision"`
|
|
|
+ Title string `json:"title"`
|
|
|
+ Description string `json:"description"`
|
|
|
+ OwnerDomain string `json:"ownerDomain"`
|
|
|
+ OwnerName string `json:"ownerName"`
|
|
|
+ DocumentationLink string `json:"documentationLink"`
|
|
|
+ Protocol string `json:"protocol"`
|
|
|
+ BaseURL string `json:"baseUrl"`
|
|
|
+ BasePath string `json:"basePath"`
|
|
|
+ Middlewares []string `json:"middlewares"`
|
|
|
+ ServicePath string `json:"servicePath"`
|
|
|
+ GitRepository string `json:"git.repository"`
|
|
|
+ Environment Environment `json:"environment"`
|
|
|
+ Variables map[string]interface{} `json:"variables"`
|
|
|
+ Resource *Resource `json:"-"`
|
|
|
+ Schemas []*Entity `json:"schemas"`
|
|
|
+ SchemasRef map[string]*Entity `json:"-"`
|
|
|
+ Resources []*Resource `json:"resources"`
|
|
|
+ Auth Auth `json:"auth"`
|
|
|
+ TypeScriptSource *ts.File `json:"-"`
|
|
|
+ Icons map[string]string `json:"icons"`
|
|
|
+ ReplaceWhenEmpty map[string]bool `json:"ReplaceWhenEmpty"`
|
|
|
+ OmitEmpty map[string]bool `json:"omitempty"`
|
|
|
+ Clients []*Client `json:"clients,omitempty"`
|
|
|
+ Translators map[string]TranslationFn `json:"-"`
|
|
|
+ FormatMap map[string]string `json:"-"`
|
|
|
+ Queries *QueryDef `json:"queries"`
|
|
|
+ ACL *ACL `json:"acl"`
|
|
|
+ Custom map[string]interface{} `json:"custom"`
|
|
|
+}
|
|
|
+type ACL struct {
|
|
|
+ Roles []*Role `json:"roles"`
|
|
|
+ Permissions []*Permission `json:"permissions"`
|
|
|
+}
|
|
|
+type QueryDef struct {
|
|
|
+ Blacklistwords map[string][]string `json:"blacklistwords"`
|
|
|
+ Queries map[string]string `json:"queries"`
|
|
|
+ Common map[string]string `json:"common"`
|
|
|
+}
|
|
|
+type Role struct {
|
|
|
+ Title string `json:"title"`
|
|
|
+ Description string `json:"description"`
|
|
|
+ ID string `json:"id"`
|
|
|
+ AllowRemove bool `json:"allowRemove,omitempty"`
|
|
|
+ Permissions []string `json:"permissions"`
|
|
|
+}
|
|
|
+type Permission struct {
|
|
|
+ Title string `json:"title"`
|
|
|
+ Description string `json:"description"`
|
|
|
+ ID string `json:"id"`
|
|
|
+}
|
|
|
+type Client struct {
|
|
|
+ Id string `json:"id,omitempty"`
|
|
|
+ OutputDir string `json:"outputDir,omitempty"`
|
|
|
+}
|
|
|
+
|
|
|
+type Auth struct {
|
|
|
+ AuthCookieDomain string `json:"authCookieDomain"`
|
|
|
+ AuthTokenID string `json:"authTokenId"`
|
|
|
+ Oauth2 Oauth2 `json:"oauth2"`
|
|
|
+}
|
|
|
+
|
|
|
+type Oauth2 struct {
|
|
|
+ URI string `json:"uri"`
|
|
|
+ Client Oauth2Client `json:"client"`
|
|
|
+ Scopes []Scope `json:"scopes"`
|
|
|
+}
|
|
|
+
|
|
|
+type Oauth2Client struct {
|
|
|
+ RedirectURI string `json:"redirect_uri"`
|
|
|
+ ClientID string `json:"client_id"`
|
|
|
+ ClientSecret string `json:"client_secret"`
|
|
|
+ Scope []string `json:"scope"`
|
|
|
+}
|
|
|
+
|
|
|
+type Scope struct {
|
|
|
+ ID string `json:"id"`
|
|
|
+ PromptToUser []string `json:"promptToUser"`
|
|
|
+ Description string `json:"description"`
|
|
|
+}
|
|
|
+
|
|
|
+type EnvironmentVariable struct {
|
|
|
+ ID string `json:"id"`
|
|
|
+ CamelID string `json:"-"`
|
|
|
+ Default string `json:"default"`
|
|
|
+ Required bool `json:"required,omitempty"`
|
|
|
+ Description string `json:"description"`
|
|
|
+}
|
|
|
+
|
|
|
+type Environment map[string]*EnvironmentVariable
|
|
|
+
|
|
|
+type Entity struct {
|
|
|
+ HasMode bool `json:"hasMode"`
|
|
|
+ ID string `json:"id"`
|
|
|
+ Type string `json:"type"`
|
|
|
+ Description string `json:"description"`
|
|
|
+ Collection string `json:"collection"`
|
|
|
+ DB string `json:"db"`
|
|
|
+ Extends []string `json:"extends"`
|
|
|
+ Properties []*Propertie `json:"properties"`
|
|
|
+ Representations map[string][]string `json:"representations"`
|
|
|
+ Custom map[string]interface{} `json:"custom"`
|
|
|
+}
|
|
|
+
|
|
|
+type Resource struct {
|
|
|
+ ID string `json:"id"`
|
|
|
+ Description string `json:"description"`
|
|
|
+ Entity string `json:"entity"`
|
|
|
+ Formats []*Value `json:"formats"`
|
|
|
+ Methods []*Method `json:"methods"`
|
|
|
+ CommonParams map[string]*Parameter `json:"commonParams"`
|
|
|
+ Custom map[string]interface{} `json:"custom"`
|
|
|
+}
|
|
|
+
|
|
|
+type Method struct {
|
|
|
+ ID string `json:"id"`
|
|
|
+ Entity string `json:"entity"`
|
|
|
+ Type string `json:"type"` // Assume valores {one, list, implement}
|
|
|
+ Path string `json:"path"`
|
|
|
+ Template string `json:"template"`
|
|
|
+ BeforePersistAction bool `json:"beforePersistAction"`
|
|
|
+ HttpMethod string `json:"httpMethod"`
|
|
|
+ Description string `json:"description"`
|
|
|
+ Response string `json:"response"`
|
|
|
+ Request string `json:"request"`
|
|
|
+ Scopes []string `json:"scopes"`
|
|
|
+ Middlewares []string `json:"middlewares"`
|
|
|
+ Postresponse []string `json:"postresponse"`
|
|
|
+ ParameterOrder []string `json:"parameterOrder"`
|
|
|
+ ParametersString []string `json:"parameters"`
|
|
|
+ Resource *Resource `json:"-"`
|
|
|
+ Hooks map[string]bool `json:"hooks"`
|
|
|
+ Parameters map[string]*Parameter `json:"parametersmap"`
|
|
|
+ Preconditions []Action `json:"preconditions"`
|
|
|
+ BeforeResponse []Action `json:"beforeResponse"`
|
|
|
+ Custom map[string]interface{} `json:"custom"`
|
|
|
+ // Parameters map[string]*Parameter `json:"parameters"`
|
|
|
+}
|
|
|
+
|
|
|
+type Action struct {
|
|
|
+ ID string `json:"id"`
|
|
|
+ Context map[string]interface{} `json:"context"`
|
|
|
+}
|
|
|
+
|
|
|
+type Parameter struct {
|
|
|
+ ID string `json:"id"`
|
|
|
+ Type string `json:"type"`
|
|
|
+ Required bool `json:"required"`
|
|
|
+ Description string `json:"description"`
|
|
|
+ Default string `json:"default"`
|
|
|
+ Location string `json:"location"`
|
|
|
+ ConvertTo string `json:"convertTo"`
|
|
|
+ Custom map[string]interface{} `json:"custom"`
|
|
|
+ // Validation *ValidationRule `json:"validation"`
|
|
|
+ Validation map[string]interface{} `json:"validation"`
|
|
|
+}
|
|
|
+
|
|
|
+// type ValidationRule struct {
|
|
|
+// Accept []*Value `json:"-"`
|
|
|
+// AcceptRef []string `json:"accept"`
|
|
|
+// Reject []*Value `json:"reject"`
|
|
|
+// RejectRef []string `json:"-"`
|
|
|
+// In []string `json:"in"`
|
|
|
+// Contains string `json:"contains"`
|
|
|
+// Regex string `json:"regex"`
|
|
|
+// Min string `json:"min"`
|
|
|
+// Max string `json:"max"`
|
|
|
+// Type string `json:"type"`
|
|
|
+// }
|
|
|
+
|
|
|
+type Value struct {
|
|
|
+ Id string `json:"id"`
|
|
|
+ Value string `json:"value"`
|
|
|
+ Default bool `json:"default"`
|
|
|
+ Fields string `json:"fields"`
|
|
|
+ Description string `json:"description"`
|
|
|
+}
|
|
|
+
|
|
|
+type Propertie struct {
|
|
|
+ ID string `json:"id"`
|
|
|
+ Name string `json:"name"`
|
|
|
+ Type string `json:"type"`
|
|
|
+ Description string `json:"description"`
|
|
|
+ AutogenerateInput string `json:"autogenerate"`
|
|
|
+ Autogenerate map[string]AutoGenDef `json:"-"`
|
|
|
+ Targets string `json:"targets"`
|
|
|
+ Array bool `json:"array"`
|
|
|
+ Relation bool `json:"relation"`
|
|
|
+ TagVisited bool `json:"-"`
|
|
|
+ Reference bool `json:"reference"`
|
|
|
+ Readonly bool `json:"readonly"`
|
|
|
+ Unique bool `json:"uniq"`
|
|
|
+ Default interface{} `json:"default"`
|
|
|
+ Enum []string `json:"enum"`
|
|
|
+ Values []interface{} `json:"values"`
|
|
|
+ EnumDescriptions []string `json:"enumDescriptions"`
|
|
|
+ Tags map[string]string `json:"tags"`
|
|
|
+ Filter []*Filter `json:"filter"`
|
|
|
+ Custom map[string]interface{} `json:"custom"`
|
|
|
+}
|
|
|
+
|
|
|
+type AutoGenDef struct {
|
|
|
+ Type string
|
|
|
+ Args []string
|
|
|
+}
|
|
|
+
|
|
|
+type Filter struct {
|
|
|
+ Path string `json:"path"`
|
|
|
+ Type string `json:"type"`
|
|
|
+ Label string `json:"label"`
|
|
|
+ UserEnumAsOptions bool `json:"userEnumAsOptions"`
|
|
|
+ Multiples bool `json:"multiples"`
|
|
|
+ Options []FilterOption `json:"options,omitempty"`
|
|
|
+}
|
|
|
+
|
|
|
+type FilterOption struct {
|
|
|
+ Value interface{} `json:"value"`
|
|
|
+ Label string `json:"label"`
|
|
|
+}
|
|
|
+
|
|
|
+type ApiFilter struct {
|
|
|
+ Id string `json:"id"`
|
|
|
+ Date int64 `json:"date"`
|
|
|
+ Fields []*Filter `json:"fields"`
|
|
|
+}
|
|
|
+
|
|
|
+func NewApiFilter(id string) *ApiFilter {
|
|
|
+ return &ApiFilter{
|
|
|
+ Id: id,
|
|
|
+ Fields: []*Filter{},
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func RequestParams(args string, params map[string]*Parameter) func(ctx context.Context) (resp interface{}, err *errs.Error) {
|
|
|
+ argsList := strings.Split(args, ",")
|
|
|
+
|
|
|
+ return func(ctx context.Context) (resp interface{}, err *errs.Error) {
|
|
|
+ var (
|
|
|
+ values = ctx.Values()
|
|
|
+ id string
|
|
|
+ value interface{}
|
|
|
+ sourceValue interface{}
|
|
|
+ param *Parameter
|
|
|
+ paramsMap = map[string]interface{}{}
|
|
|
+ )
|
|
|
+
|
|
|
+ values.Set("$params", paramsMap)
|
|
|
+
|
|
|
+ for _, arg := range argsList {
|
|
|
+ param = params[arg]
|
|
|
+
|
|
|
+ switch param.Location {
|
|
|
+
|
|
|
+ case "query":
|
|
|
+ id = "q." + arg
|
|
|
+ value = api.Q(ctx, arg, param.Default)
|
|
|
+ case "path":
|
|
|
+ id = "p." + arg
|
|
|
+ value = api.P(ctx, arg, param.Default)
|
|
|
+ }
|
|
|
+ sourceValue = value
|
|
|
+
|
|
|
+ if param.Required && (value == "" || value == nil) {
|
|
|
+ invalidArgument := errs.InvalidArgument()
|
|
|
+ invalidArgument.Message = fmt.Sprintf("ParamRequired:'%s'", param.ID)
|
|
|
+ return nil, invalidArgument
|
|
|
+ }
|
|
|
+
|
|
|
+ if param.ConvertTo != "" {
|
|
|
+ if value, err = convertValueByType(param.ConvertTo, value); err != nil {
|
|
|
+ invalidArgument := errs.InvalidArgument()
|
|
|
+ invalidArgument.Message = fmt.Sprintf("TypeConversionError:'%v'. Waiting a %s ", value, param.ConvertTo)
|
|
|
+ return nil, invalidArgument
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if param.Validation != nil {
|
|
|
+ for validator, args := range param.Validation {
|
|
|
+ if fn, found := validationParamFunctions[validator]; found {
|
|
|
+ if err = fn(value, args); err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ values.Set(id, value)
|
|
|
+ paramsMap[fmt.Sprintf("%s_conv", arg)] = value
|
|
|
+ paramsMap[arg] = sourceValue
|
|
|
+ }
|
|
|
+ ctx.Next()
|
|
|
+ return
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+var (
|
|
|
+ convertionTypeFunctions = map[string]func(interface{}) (interface{}, *errs.Error){
|
|
|
+ "ObjectID": stringToObjectId,
|
|
|
+ "bool": stringToBool,
|
|
|
+ "int": stringToInt,
|
|
|
+ "number": stringToFloat,
|
|
|
+ }
|
|
|
+
|
|
|
+ validationParamFunctions = map[string]func(interface{}, interface{}) *errs.Error{
|
|
|
+ "min": func(value interface{}, minString interface{}) *errs.Error {
|
|
|
+ min, err := strconv.Atoi(minString.(string))
|
|
|
+ if err != nil || value.(int) < min {
|
|
|
+ invalidArgument := errs.InvalidArgument()
|
|
|
+ invalidArgument.Message = fmt.Sprintf("ValueRestriction: value > %s. Received (%d)", minString, value)
|
|
|
+ return invalidArgument
|
|
|
+ }
|
|
|
+ return nil
|
|
|
+ },
|
|
|
+ "max": func(value interface{}, maxString interface{}) *errs.Error {
|
|
|
+ max, err := strconv.Atoi(maxString.(string))
|
|
|
+ if err != nil || value.(int) > max {
|
|
|
+ invalidArgument := errs.InvalidArgument()
|
|
|
+ invalidArgument.Message = fmt.Sprintf("ValueRestriction: value < %s. Received (%d)", maxString, value)
|
|
|
+ return invalidArgument
|
|
|
+ }
|
|
|
+ return nil
|
|
|
+ },
|
|
|
+ "accept": func(input interface{}, accept interface{}) *errs.Error {
|
|
|
+ var (
|
|
|
+ acceptValues = accept.([]string)
|
|
|
+ value = input.(string)
|
|
|
+ )
|
|
|
+
|
|
|
+ for _, acceptValue := range acceptValues {
|
|
|
+ if value == acceptValue {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ invalidArgument := errs.InvalidArgument()
|
|
|
+ invalidArgument.Message = fmt.Sprintf(
|
|
|
+ "ValueRestriction: '%s' isn't accept. Accept [%s]",
|
|
|
+ value,
|
|
|
+ strings.Join(acceptValues, ","),
|
|
|
+ )
|
|
|
+ return invalidArgument
|
|
|
+ },
|
|
|
+ "reject": func(input interface{}, reject interface{}) *errs.Error {
|
|
|
+ var (
|
|
|
+ rejectValues = reject.([]string)
|
|
|
+ value = input.(string)
|
|
|
+ )
|
|
|
+
|
|
|
+ for _, rejectValue := range rejectValues {
|
|
|
+ if value == rejectValue {
|
|
|
+ invalidArgument := errs.InvalidArgument()
|
|
|
+ invalidArgument.Message = fmt.Sprintf(
|
|
|
+ "ValueRestriction: '%s' isn't accept. Rejected terms [%s]",
|
|
|
+ value,
|
|
|
+ strings.Join(rejectValues, ","),
|
|
|
+ )
|
|
|
+ return invalidArgument
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return nil
|
|
|
+ },
|
|
|
+ "regex": func(input interface{}, regex interface{}) *errs.Error {
|
|
|
+ var (
|
|
|
+ regexString = regex.(string)
|
|
|
+ value = input.(string)
|
|
|
+ )
|
|
|
+
|
|
|
+ regexInstance := regexp.MustCompile(regexString)
|
|
|
+
|
|
|
+ if !regexInstance.Match([]byte(value)) {
|
|
|
+
|
|
|
+ invalidArgument := errs.InvalidArgument()
|
|
|
+ invalidArgument.Message = fmt.Sprintf(
|
|
|
+ "ValueRestriction: '%s' isn't accept",
|
|
|
+ value,
|
|
|
+ )
|
|
|
+
|
|
|
+ return invalidArgument
|
|
|
+ }
|
|
|
+
|
|
|
+ return nil
|
|
|
+ },
|
|
|
+ }
|
|
|
+)
|
|
|
+
|
|
|
+func stringToObjectId(value interface{}) (interface{}, *errs.Error) {
|
|
|
+ var (
|
|
|
+ valueString = value.(string)
|
|
|
+ valueObjectID primitive.ObjectID
|
|
|
+ err error
|
|
|
+ )
|
|
|
+
|
|
|
+ if valueObjectID, err = primitive.ObjectIDFromHex(valueString); err != nil {
|
|
|
+ invalidArgument := errs.InvalidArgument()
|
|
|
+ invalidArgument.Message = fmt.Sprintf("The value '%s' is'nt a valid ObjectId", valueString)
|
|
|
+ return nil, invalidArgument
|
|
|
+ }
|
|
|
+
|
|
|
+ return valueObjectID, nil
|
|
|
+}
|
|
|
+
|
|
|
+func stringToBool(value interface{}) (interface{}, *errs.Error) {
|
|
|
+
|
|
|
+ var (
|
|
|
+ valueBool bool
|
|
|
+ err error
|
|
|
+ )
|
|
|
+
|
|
|
+ if valueBool, err = strconv.ParseBool(value.(string)); err != nil {
|
|
|
+ invalidArgument := errs.InvalidArgument()
|
|
|
+ invalidArgument.Message = fmt.Sprintf("The value '%s' is'nt a valid boolean. Accept [true,1,T,false,0,F]", valueBool)
|
|
|
+ return nil, invalidArgument
|
|
|
+ }
|
|
|
+
|
|
|
+ return valueBool, nil
|
|
|
+}
|
|
|
+
|
|
|
+func stringToInt(value interface{}) (interface{}, *errs.Error) {
|
|
|
+
|
|
|
+ var (
|
|
|
+ valueInt int64
|
|
|
+ err error
|
|
|
+ )
|
|
|
+
|
|
|
+ if valueInt, err = strconv.ParseInt(value.(string), 10, 64); err != nil {
|
|
|
+ invalidArgument := errs.InvalidArgument()
|
|
|
+ invalidArgument.Message = fmt.Sprintf("The value '%s' is'nt a valid int", valueInt)
|
|
|
+ return nil, invalidArgument
|
|
|
+ }
|
|
|
+
|
|
|
+ return valueInt, nil
|
|
|
+}
|
|
|
+
|
|
|
+func stringToFloat(value interface{}) (interface{}, *errs.Error) {
|
|
|
+
|
|
|
+ var (
|
|
|
+ valueFloat float64
|
|
|
+ err error
|
|
|
+ )
|
|
|
+
|
|
|
+ if valueFloat, err = strconv.ParseFloat(value.(string), 64); err != nil {
|
|
|
+ invalidArgument := errs.InvalidArgument()
|
|
|
+ invalidArgument.Message = fmt.Sprintf("The value '%s' is'nt a valid number", valueFloat)
|
|
|
+ return nil, invalidArgument
|
|
|
+ }
|
|
|
+
|
|
|
+ return valueFloat, nil
|
|
|
+}
|
|
|
+
|
|
|
+func convertValueByType(typ string, value interface{}) (interface{}, *errs.Error) {
|
|
|
+ var err *errs.Error
|
|
|
+ if fn, found := convertionTypeFunctions[typ]; found {
|
|
|
+ if value, err = fn(value); err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return value, nil
|
|
|
+}
|
|
|
+
|
|
|
+// func validateParam(param *Parameter, value interface{}) (interface{}, *errs.Error) {
|
|
|
+// var err *errs.Error
|
|
|
+
|
|
|
+// return value, nil
|
|
|
+// }
|
|
|
+
|
|
|
+func (t *Method) Hook(id string) bool {
|
|
|
+ // active := t.Hooks[id]
|
|
|
+ // return active
|
|
|
+ return t.Hooks[id]
|
|
|
+}
|
|
|
+
|
|
|
+func (t *Propertie) ParseAutogenerate() error {
|
|
|
+ if t.AutogenerateInput != "" {
|
|
|
+ parts := strings.Split(t.AutogenerateInput, ":")
|
|
|
+ if len(parts) < 2 {
|
|
|
+ return fmt.Errorf("Invalid autogenerate input '%s' in attribute '%s'.", t.AutogenerateInput, t.ID)
|
|
|
+ }
|
|
|
+
|
|
|
+ if t.Autogenerate == nil {
|
|
|
+ t.Autogenerate = map[string]AutoGenDef{}
|
|
|
+ }
|
|
|
+
|
|
|
+ args := strings.Split(parts[1], "#")
|
|
|
+
|
|
|
+ for _, k := range strings.Split(parts[0], ",") {
|
|
|
+ t.Autogenerate[k] = AutoGenDef{
|
|
|
+ Type: args[0],
|
|
|
+ Args: args[1:],
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+type SchemasRelations struct {
|
|
|
+ R map[string][]*Relation
|
|
|
+}
|
|
|
+
|
|
|
+type Relation struct {
|
|
|
+ Source string
|
|
|
+ Target string
|
|
|
+ Attr string
|
|
|
+ Collection string
|
|
|
+ DB string
|
|
|
+ IsArray bool
|
|
|
+}
|
|
|
+
|
|
|
+type EntityInfo struct {
|
|
|
+ Name string
|
|
|
+ Origin string
|
|
|
+ NewName string
|
|
|
+ DynamicType string
|
|
|
+ DynamicTypeId string
|
|
|
+ IsGeneric bool
|
|
|
+}
|
|
|
+
|
|
|
+type TranslationFn func(p *Project) error
|
|
|
+
|
|
|
+func (p *Project) Build(b *BuildOptions) error {
|
|
|
+ var err error
|
|
|
+
|
|
|
+ for _, c := range p.Clients {
|
|
|
+ if fn, found := p.Translators[c.Id]; found {
|
|
|
+ if err = fn(p); err != nil {
|
|
|
+ fmt.Println("error on ", c.Id)
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ return fmt.Errorf("Middleware '%s' not defined!", c.Id)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // fmt.Println("--- RunBuildCommads")
|
|
|
+ return RunBuildCommads(p, b)
|
|
|
+}
|
|
|
+
|
|
|
+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 {
|
|
|
+ return c
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+func (p *Project) Save(path string) error {
|
|
|
+ data, err := json.MarshalIndent(p, "", " ")
|
|
|
+ if err == nil {
|
|
|
+ err = FilePutContentsBytes(path, data, 0777)
|
|
|
+ }
|
|
|
+ return err
|
|
|
+}
|
|
|
+
|
|
|
+func (p *Project) GetCollection(entity string) string {
|
|
|
+ for _, e := range p.Schemas {
|
|
|
+ if e.ID == entity {
|
|
|
+ return e.Collection
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return "undefined"
|
|
|
+}
|
|
|
+
|
|
|
+func (p *Project) GetEntityDB(entity string) string {
|
|
|
+ if en, found := p.SchemasRef[entity]; found {
|
|
|
+ return en.DB + p.DataBaseSufix
|
|
|
+ }
|
|
|
+ panic(fmt.Sprintf("DB attribute is empty in entity '%s'", entity))
|
|
|
+}
|
|
|
+
|
|
|
+func (p *Project) EntityDesc(ID string) *Entity {
|
|
|
+ if _, y := p.SchemasRef[ID]; !y {
|
|
|
+ fmt.Println("EntityDesc(ID)", ID)
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ return p.SchemasRef[ID]
|
|
|
+}
|
|
|
+
|
|
|
+func (m *Method) HasPathParams() bool {
|
|
|
+ return len(m.ParameterOrder) > 0
|
|
|
+}
|
|
|
+
|
|
|
+func (m *Method) HasFormatParam() (bool, *Parameter) {
|
|
|
+
|
|
|
+ for id, param := range m.Parameters {
|
|
|
+ // param = m.Parameters[id]
|
|
|
+ // fmt.Println("param:", param.ID)
|
|
|
+ if id == "format" {
|
|
|
+ return true, param
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return false, nil
|
|
|
+}
|
|
|
+
|
|
|
+func (p *Project) GetUrlFromMethod(method *Method) string {
|
|
|
+ return p.BaseURL + method.Path
|
|
|
+}
|
|
|
+
|
|
|
+func (p *Project) ResponseEntity(property string) *EntityInfo {
|
|
|
+ var (
|
|
|
+ pi = &EntityInfo{
|
|
|
+ Origin: property,
|
|
|
+ }
|
|
|
+ )
|
|
|
+ match := Generic.FindStringSubmatch(property)
|
|
|
+
|
|
|
+ if len(match) == 0 {
|
|
|
+ return pi
|
|
|
+ }
|
|
|
+
|
|
|
+ for i, name := range Generic.SubexpNames() {
|
|
|
+ switch name {
|
|
|
+ case "type":
|
|
|
+ pi.Name = match[i]
|
|
|
+ case "dtype":
|
|
|
+ pi.DynamicType = match[i]
|
|
|
+ pi.IsGeneric = true
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if pi.IsGeneric {
|
|
|
+ entity := p.GetSchema(pi.Name)
|
|
|
+
|
|
|
+ match = GenericPart.FindStringSubmatch(entity.ID)
|
|
|
+
|
|
|
+ for i, name := range GenericPart.SubexpNames() {
|
|
|
+ switch name {
|
|
|
+ case "id":
|
|
|
+ pi.DynamicTypeId = match[i]
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ pi.NewName = pi.Name + UpFirst(strings.Replace(pi.DynamicType, "*", "", -1))
|
|
|
+
|
|
|
+ return pi
|
|
|
+}
|
|
|
+
|
|
|
+func (p *Project) GetPath(m *Method) string {
|
|
|
+
|
|
|
+ path := []byte(p.BasePath + m.Path)
|
|
|
+
|
|
|
+ for attr, param := range m.Parameters {
|
|
|
+ path = regexp.MustCompile("{"+attr+"}").ReplaceAll(path, []byte("{"+attr+":"+param.Type+"}"))
|
|
|
+ }
|
|
|
+
|
|
|
+ return string(path)
|
|
|
+}
|
|
|
+func (p *Project) GetSchema(id string) *Entity {
|
|
|
+ id = strings.Replace(id, "*", "", -1)
|
|
|
+ if model, ok := p.SchemasRef[id]; ok {
|
|
|
+ return model
|
|
|
+ }
|
|
|
+ panic(fmt.Sprintf("Entity '%s' not defined!", id))
|
|
|
+}
|
|
|
+
|
|
|
+// Metodos das propriedades
|
|
|
+
|
|
|
+func (p *Propertie) FillTags(project *Project, propName string) {
|
|
|
+ if p.TagVisited {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if propName == "Id" {
|
|
|
+
|
|
|
+ }
|
|
|
+ if p.Tags != nil {
|
|
|
+ for k, v := range p.Tags {
|
|
|
+
|
|
|
+ if _, found := project.ReplaceWhenEmpty[k]; found && v == "" {
|
|
|
+ p.Tags[k] = LcFirst(p.ID)
|
|
|
+ }
|
|
|
+
|
|
|
+ if _, found := project.OmitEmpty[k]; found {
|
|
|
+ if p.Tags[k] != "-" {
|
|
|
+ p.Tags[k] += ",omitempty"
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ p.TagVisited = true
|
|
|
+}
|
|
|
+
|
|
|
+func (p *Propertie) GetType() string {
|
|
|
+ return strings.Replace(p.Type, "*", "", 1)
|
|
|
+}
|
|
|
+
|
|
|
+// Metodos das informacoes da entidade
|
|
|
+
|
|
|
+func (p *EntityInfo) TranslateType(typ string) string {
|
|
|
+
|
|
|
+ if typ == p.DynamicTypeId {
|
|
|
+ return p.DynamicType
|
|
|
+ }
|
|
|
+ return typ
|
|
|
+}
|
|
|
+
|
|
|
+// Metodos do esquema de relacoes
|
|
|
+
|
|
|
+// Add adiciona uma relação ao esquema
|
|
|
+func (s *SchemasRelations) Has(entity string) bool {
|
|
|
+ // spew.Dump(s)
|
|
|
+ _, found := s.R[entity]
|
|
|
+ return found
|
|
|
+}
|
|
|
+
|
|
|
+// Add adiciona uma relação ao esquema
|
|
|
+func (s *SchemasRelations) Get(entity string) []*Relation {
|
|
|
+ if e, found := s.R[entity]; found {
|
|
|
+ return e
|
|
|
+ }
|
|
|
+ return []*Relation{}
|
|
|
+}
|
|
|
+
|
|
|
+// Add adiciona uma relação ao esquema
|
|
|
+func (s *SchemasRelations) Add(r *Relation) {
|
|
|
+ if _, found := s.R[r.Source]; !found {
|
|
|
+ s.R[r.Source] = []*Relation{}
|
|
|
+ }
|
|
|
+
|
|
|
+ s.R[r.Source] = append(s.R[r.Source], r)
|
|
|
+}
|
|
|
+
|
|
|
+func ParseTemplate(input string, name ...string) (*template.Template, error) {
|
|
|
+ var tmpl, err = template.New(strings.Join(name, "")).Parse(input)
|
|
|
+ return tmpl, err
|
|
|
+}
|
|
|
+
|
|
|
+func TemplateToString(template *template.Template, data interface{}) (string, error) {
|
|
|
+ var result bytes.Buffer
|
|
|
+
|
|
|
+ if err := template.Execute(&result, data); err != nil {
|
|
|
+ return "", err
|
|
|
+ }
|
|
|
+
|
|
|
+ return result.String(), nil
|
|
|
+}
|
|
|
+
|
|
|
+func NewProject() *Project {
|
|
|
+ return &Project{
|
|
|
+ Mode: "",
|
|
|
+ SchemasRef: map[string]*Entity{},
|
|
|
+ Icons: map[string]string{},
|
|
|
+ ReplaceWhenEmpty: map[string]bool{},
|
|
|
+ OmitEmpty: map[string]bool{},
|
|
|
+ FormatMap: map[string]string{},
|
|
|
+ Queries: &QueryDef{},
|
|
|
+ Schemas: []*Entity{},
|
|
|
+ Resources: []*Resource{},
|
|
|
+ Translators: map[string]TranslationFn{},
|
|
|
+ }
|
|
|
+}
|