From 3681bfa49967084b8ac0c711df79acaa7bdc26b4 Mon Sep 17 00:00:00 2001 From: wsfuyibing Date: Mon, 19 Aug 2024 11:04:57 +0800 Subject: [PATCH 01/11] new version --- db/commands2/base/table_column.go | 53 ++++ db/commands2/base/table_type.go | 311 ++++++++++++++++++++++ db/commands2/common.go | 364 ++++++++++++++++++++++++++ db/commands2/gen_model/generator.tpl | 64 +++++ db/commands2/gen_model/provider.go | 90 +++++++ db/commands2/gen_service/generator.go | 64 +++++ 6 files changed, 946 insertions(+) create mode 100644 db/commands2/base/table_column.go create mode 100644 db/commands2/base/table_type.go create mode 100644 db/commands2/common.go create mode 100644 db/commands2/gen_model/generator.tpl create mode 100644 db/commands2/gen_model/provider.go create mode 100644 db/commands2/gen_service/generator.go diff --git a/db/commands2/base/table_column.go b/db/commands2/base/table_column.go new file mode 100644 index 0000000..9c8ab1a --- /dev/null +++ b/db/commands2/base/table_column.go @@ -0,0 +1,53 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Author: wsfuyibing <682805@qq.com> +// Date: 2024-08-02 + +package base + +import ( + "html/template" +) + +// Column +// is a component for table definition (DDL). +type Column struct { + Field ItemName `xorm:"Field"` + Collation ItemCollation `xorm:"Collation"` + Comment ItemComment `xorm:"Comment"` + Type ColumnType `xorm:"Type"` + Default ColumnDefault `xorm:"Default"` + Key ColumnKey `xorm:"Key"` + Null ColumnNull `xorm:"Null"` + Extra ColumnExtra `xorm:"Extra"` + + // Related on table. + Table *Table `xorm:"-"` + + // Info fields. + CommentList []template.HTML `xorm:"-"` + Datetime template.HTML `xorm:"-"` + Script template.HTML `xorm:"-"` + + // Name and type fields. + ExportName string `xorm:"-"` // for field name. e.g. Id, UserId etc + ExportType string `xorm:"-"` // for field type. e.g. int, db.Date, db.Datetime etc + ExportJson string `xorm:"-"` // for field tag. e.g. id, user_id etc + ExportOrm string `xorm:"-"` // for field tag. e.g. id pk autoincr, user_id etc + ExportPkg string `xorm:"-"` // for field tag. e.g. models, services etc + + IsDate bool `xorm:"-"` + IsDatetime bool `xorm:"-"` + IsDatetimeOnUpdate bool `xorm:"-"` + IsPrimaryKey bool `xorm:"-"` +} diff --git a/db/commands2/base/table_type.go b/db/commands2/base/table_type.go new file mode 100644 index 0000000..0e22e85 --- /dev/null +++ b/db/commands2/base/table_type.go @@ -0,0 +1,311 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Author: wsfuyibing <682805@qq.com> +// Date: 2024-08-02 + +package base + +import ( + "fmt" + "gitee.com/go-libs/console" + "regexp" + "strings" +) + +var ( + RegexStartLetter = regexp.MustCompile(`^(\S)`) + RegexStartWithUnderline = regexp.MustCompile(`^_+`) + RegexMiddleWithUnderline = regexp.MustCompile(`_+(\S)`) + RegexMatchUpperLetter = regexp.MustCompile(`([A-Z])`) + RegexMatchManyUnderlines = regexp.MustCompile(`_+`) + + RegexMatchColumnExtraAutoIncrement = regexp.MustCompile(`auto_increment`) + RegexMatchColumnType = regexp.MustCompile(`^([_a-zA-Z0-9]+)`) +) + +// ColumnDefault +// is a type for field name of a table. +type ColumnDefault string + +func (o ColumnDefault) String() string { + return strings.TrimSpace(strings.ToLower(string(o))) +} + +// +---------------------------------------------------------------------------+ +// | Type for table column extra | +// +---------------------------------------------------------------------------+ + +// ColumnExtra +// is a type for field name of a table. +type ColumnExtra string + +// Convert +// field name to exported orm name. +// +// .Convert("id") // return "id pk autoincr" +// .Convert("user_id") // return "user_id" +func (o ColumnExtra) Convert(field ItemName) string { + if RegexMatchColumnExtraAutoIncrement.MatchString(o.String()) { + return fmt.Sprintf(`%s pk autoincr`, field.String()) + } + return field.String() +} + +func (o ColumnExtra) IsDatetimeOnUpdate() bool { + return o.String() == "on update current_timestamp" +} + +func (o ColumnExtra) String() string { + return strings.TrimSpace(strings.ToLower(string(o))) +} + +// +---------------------------------------------------------------------------+ +// | Type for key of a table | +// +---------------------------------------------------------------------------+ + +// ColumnKey +// is a type for field name of a table. +type ColumnKey string + +func (o ColumnKey) IsPrimary() bool { + return strings.ToUpper(o.String()) == "PRI" +} + +func (o ColumnKey) String() string { + return string(o) +} + +// +---------------------------------------------------------------------------+ +// | Type for table column nullable | +// +---------------------------------------------------------------------------+ + +// ColumnNull +// is a type for field name of a table. +type ColumnNull string + +// +---------------------------------------------------------------------------+ +// | Type for table column | +// +---------------------------------------------------------------------------+ + +// ColumnType +// is a type for field name of a table. +type ColumnType string + +func (o ColumnType) Convert(command *console.Command) (pkg, name string) { + return +} + +func (o ColumnType) IsDate() bool { + if m := RegexMatchColumnType.FindStringSubmatch(o.String()); len(m) > 0 { + return strings.ToLower(m[1]) == "date" + } + return false +} + +func (o ColumnType) IsDatetime() bool { + if m := RegexMatchColumnType.FindStringSubmatch(o.String()); len(m) > 0 { + s := strings.ToLower(m[1]) + return s == "datetime" || s == "timestamp" + } + return false +} + +func (o ColumnType) Origin() string { + if m := RegexMatchColumnType.FindStringSubmatch(o.String()); len(m) > 0 { + return m[1] + } + return "" +} + +func (o ColumnType) String() string { + return string(o) +} + +// +---------------------------------------------------------------------------+ +// | Collation for table and columns | +// +---------------------------------------------------------------------------+ + +// ItemCollation +// is a type for table and field name. +type ItemCollation string + +// +---------------------------------------------------------------------------+ +// | Comment for table and columns | +// +---------------------------------------------------------------------------+ + +// ItemComment +// is a type for table and field name. +type ItemComment string + +// String +// returns a comment string without new line. +func (o ItemComment) String() string { + return strings.TrimSpace(string(o)) +} + +// Strings +// returns a comment string list with new line. +func (o ItemComment) Strings() []string { + return strings.Split(o.String(), "\n") +} + +// +---------------------------------------------------------------------------+ +// | Name for table and columns | +// +---------------------------------------------------------------------------+ + +// ItemName +// is a type for table and field name. +type ItemName string + +// Allow +// return true if start with an a-z letter. +// +// Output: +// +// return true // user +// return false // _user +func (o ItemName) Allow() bool { + return regexp.MustCompile(`^[a-zA-Z][_a-zA-Z0-9]*$`).MatchString(o.String()) +} + +// String +// returns the origin name with any formats. +// +// Output: +// +// return "user_info" +// return "UserInfo" +// return "userInfo" +func (o ItemName) String() string { + return string(o) +} + +// FileName +// convert to file name without extension name. +// +// Rule: +// - table name : `cdb_user_info` +// - prefix : `cdb_` +// - file name : `user_info` +// +// Output: +// +// return "user_info" +func (o ItemName) FileName(prefix string) (name string) { + // Use + // origin name as default. + name = o.String() + + // Remove + // prefix name. + // + // Convert `cdb_user_info` as `user_info` with a prefix `cdb_`. + if prefix != "" { + name = strings.TrimPrefix(name, prefix) + } + + // Convert + // upper-case letter as underline with a lower-case letter. + // + // Convert `UserInfo` as `_user_info` + name = RegexMatchUpperLetter.ReplaceAllStringFunc(name, func(s string) string { + return fmt.Sprintf(`_%s`, strings.ToLower(s)) + }) + + // Remove + // starts with underline. + // + // Convert `_user_info` as `user_info`. + name = RegexStartWithUnderline.ReplaceAllString(name, "") + name = RegexMatchManyUnderlines.ReplaceAllString(name, "_") + return +} + +// StructName +// convert to struct name that starts with an upper-case letter. +// +// Rule: +// - table name : `cdb_user_info` +// - prefix : `cdb_` +// - struct name : `UserInfo` +// +// Output: +// +// return "UserInfo" +func (o ItemName) StructName(prefix string) (name string) { + // Use + // origin name as default. + name = o.String() + + // Remove + // prefix name. + // + // Example : cdb_user + // Prefix : cdb_ + // Replaced : user + if prefix != "" { + name = strings.TrimPrefix(name, prefix) + } + + // Remove + // underline start of name. + name = RegexStartWithUnderline.ReplaceAllString(name, "") + + // Convert + // underline with any letter as upper-case letter. + name = RegexMiddleWithUnderline.ReplaceAllStringFunc(name, func(s string) string { + if m := RegexMiddleWithUnderline.FindStringSubmatch(s); len(m) > 0 { + return strings.ToUpper(m[1]) + } + return s + }) + + // Convert + // first letter as upper-case letter. + name = RegexStartLetter.ReplaceAllStringFunc(name, func(s string) string { + return strings.ToUpper(s) + }) + return +} + +// ToLargeCamel +// returns a large camel that equals to struct name. +// +// Output: +// +// return "UserInfo" +func (o ItemName) ToLargeCamel() string { + return o.StructName("") +} + +// ToSmallCamel +// returns a small-camel format name. +// +// Output: +// +// return "userInfo" +func (o ItemName) ToSmallCamel() string { + return RegexStartLetter.ReplaceAllStringFunc(o.StructName(""), func(s string) string { + return strings.ToLower(s) + }) +} + +// ToSnake +// returns a snake format name. +// +// Output: +// +// return "user_info" +func (o ItemName) ToSnake() string { + return o.FileName("") +} diff --git a/db/commands2/common.go b/db/commands2/common.go new file mode 100644 index 0000000..335e89f --- /dev/null +++ b/db/commands2/common.go @@ -0,0 +1,364 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Author: wsfuyibing <682805@qq.com> +// Date: 2024-08-02 + +package commands2 + +import ( + "context" + _ "embed" + "fmt" + "gitee.com/go-libs/console" + "gitee.com/go-libs/db-xorm/db" + "gitee.com/go-libs/db-xorm/db/commands2/base" + "gitee.com/go-libs/db-xorm/db/commands2/conf" + "html/template" + "path/filepath" + "regexp" + "strings" + "time" +) + +const DsnKey = "_gen:commands_" + +var RegexMatchPkg = regexp.MustCompile(`([_a-zA-Z0-9]+)$`) + +type Common struct { + BaseDir string + Dsn string + Export, Prefix string + ModelPath, ModelPkg string + Override bool + TargetPath, TargetPkg string + ModuleName, ModuleFolder string +} + +// BuildModule +// build module name and working relative folder. +func (o *Common) BuildModule(command *console.Command) (err error) { + if o.ModuleName, o.ModuleFolder = command.GenerateModule(o.BaseDir); o.ModuleName == "" { + err = fmt.Errorf(`can not parse module name from go.mod`) + return + } + if o.ModuleFolder != "" { + o.ModuleFolder = fmt.Sprintf(`/%s`, strings.TrimPrefix(o.ModuleFolder, "/")) + } + return +} + +// BuildScript +// build command runner script. +func (o *Common) BuildScript(command *console.Command) string { + return fmt.Sprintf(`go run main.go %s`, command.ToScript()) +} + +// ListTable +// returns a list for tables in a database. +func (o *Common) ListTable(ctx context.Context, command *console.Command) (tables []*base.Table, err error) { + var ( + all bool + list []*base.Table + names = make(map[string]string) + named = make(map[string]bool) + session *db.Session + ) + + // Prepare + // export names. + if o.Export == "*" { + all = true + } else { + for _, s := range strings.Split(o.Export, ",") { + if s = strings.TrimSpace(s); s != "" { + names[fmt.Sprintf(`%s%s`, o.Prefix, s)] = s + } + } + } + + // Open + // a connect session with exporter key. + if session, err = db.Config.GetMaster(ctx, DsnKey); err != nil { + return + } + + // Prepare + // table list. + tables = make([]*base.Table, 0) + + // Select + // all tables in database and columns of the table. + if err = session.NoCascade().SQL("SHOW TABLE STATUS").Find(&list); err == nil { + // Iterate + // table in database. + for _, table := range list { + // Ignore + // not allowed table. + if !table.Name.Allow() { + continue + } + + // Ignore + // not matched on names. + if !all { + if _, ok := names[table.Name.String()]; !ok { + continue + } + } + + // Select + // columns from a table. + if err = session.NoCascade().SQL(fmt.Sprintf("SHOW FULL COLUMNS FROM `%s`", table.Name)).Find(&table.Columns); err != nil { + break + } + + // Format + // table fields. + o.formatTable(command, table) + for _, column := range table.Columns { + o.formatColumn(command, table, column) + } + + // Append + // to list. + named[table.Name.String()] = true + tables = append(tables, table) + } + } + + // Exported + // name in command argument not found. + for k := range names { + if _, ok := named[k]; !ok { + err = fmt.Errorf(`table not found: %s`, k) + return + } + } + + // Empty result. + if len(tables) == 0 { + err = fmt.Errorf(`table not found in database`) + } + return +} + +// ReadBaseDir +// read absolute path of the application. +func (o *Common) ReadBaseDir(command *console.Command, key, value string) (err error) { + // Read + // from command options. + if opt, has := command.GetOption(key); has { + if s := opt.ToString(); s != "" { + value = s + } + } + + // Return error + // if base dir is blank. + if value == "" { + err = fmt.Errorf(`base dir can not be blank`) + return + } + + // Convert + // to absolute path. + o.BaseDir, err = filepath.Abs(value) + return +} + +// ReadDsn +// read database source name. +func (o *Common) ReadDsn(command *console.Command, key string) (err error) { + // Read dsn + // from command options. + if opt, has := command.GetOption(key); has { + if s := opt.ToString(); s != "" { + o.Dsn = s + return + } + } + + // Use default + // configuration of config files. + if cfg, ok := db.Config.Get(); ok && len(cfg.Dsn) > 0 { + o.Dsn = cfg.Dsn[0] + return + } + + // Error read. + err = fmt.Errorf(`dsn can not be blank`) + return +} + +// ReadExport +// read export names. +func (o *Common) ReadExport(command *console.Command, key string) (err error) { + if opt, has := command.GetOption(key); has { + if s := opt.ToString(); s != "" { + o.Export = s + } + } + return +} + +// ReadModelPath +// read path for model files location. +func (o *Common) ReadModelPath(command *console.Command, key, value string) (err error) { + // Read + // from command options. + if opt, has := command.GetOption(key); has { + if s := opt.ToString(); s != "" { + value = s + } + } + + // Return error + // if base dir is blank. + if value == "" { + err = fmt.Errorf(`model path can not be blank`) + return + } + + // Convert + // to absolute path. + o.ModelPath = value + + // Read package name for model. + if m := RegexMatchPkg.FindStringSubmatch(value); len(m) > 0 { + o.ModelPkg = m[1] + return + } + + // Error read. + err = fmt.Errorf(`can not parse package name for target`) + return +} + +// ReadOverride +// read override state for existing files. +func (o *Common) ReadOverride(command *console.Command, key string) (err error) { + if opt, has := command.GetOption(key); has { + o.Override = opt.GetSpecified() + } + return +} + +// ReadPrefix +// read prefix for table name. +func (o *Common) ReadPrefix(command *console.Command, key string) (err error) { + if opt, has := command.GetOption(key); has { + if s := opt.ToString(); s != "" { + o.Prefix = s + } + } + return +} + +// ReadTargetPath +// read path for generated files save to. +func (o *Common) ReadTargetPath(command *console.Command, key, value string) (err error) { + // Read + // from command options. + if opt, has := command.GetOption(key); has { + if s := opt.ToString(); s != "" { + value = s + } + } + + // Return error + // if base dir is blank. + if value == "" { + err = fmt.Errorf(`target path can not be blank`) + return + } + + // Convert + // to absolute path. + o.TargetPath = value + + // Read package for generated files save to. + if m := RegexMatchPkg.FindStringSubmatch(value); len(m) > 0 { + o.TargetPkg = m[1] + return + } + + // Error read. + err = fmt.Errorf(`can not parse package name for target`) + return +} + +// RegisterDatabase +// adds a database connect configuration. +func (o *Common) RegisterDatabase() error { + return db.Config.Add(DsnKey, &db.Database{ + Dsn: []string{o.Dsn}, + Mapper: "snake", + }) +} + +func (o *Common) formatColumn(command *console.Command, table *base.Table, column *base.Column) { + // Bind relation of a table. + column.Table = table + + // Build comment list of a table. + if len(column.Comment.Strings()) > 0 { + column.CommentList = make([]template.HTML, 0) + for _, s := range column.Comment.Strings() { + if s = strings.TrimSpace(s); s != "" { + column.CommentList = append(column.CommentList, template.HTML(s)) + } + } + } + + // Parse info fields. + column.Datetime = template.HTML(time.Now().Format(time.RFC3339)) + column.Script = template.HTML(o.BuildScript(command)) + + // Parse name fields. + column.ExportName = column.Field.StructName(o.Prefix) + column.ExportJson = column.Field.ToSnake() + column.ExportOrm = column.Extra.Convert(column.Field) + + // Type convert. + if convert := conf.Model.Get(fmt.Sprintf(`%s.%s`, table.Name, column.Field), column.Type.Origin()); convert != nil { + column.ExportPkg = convert.Pkg + column.ExportType = convert.Type + + // Append package. + if column.ExportPkg != "" { + table.Add(column.ExportPkg) + } + // column.ExportPkg, column.ExportType = column.Type.Convert(command) + } + + column.IsDate = column.Type.IsDate() + column.IsDatetime = column.Type.IsDatetime() + column.IsDatetimeOnUpdate = column.Extra.IsDatetimeOnUpdate() + column.IsPrimaryKey = column.Key.IsPrimary() +} + +func (o *Common) formatTable(command *console.Command, table *base.Table) { + // Build comment list of a table. + if len(table.Comment.Strings()) > 0 { + table.CommentList = make([]template.HTML, 0) + for _, s := range table.Comment.Strings() { + if s = strings.TrimSpace(s); s != "" { + table.CommentList = append(table.CommentList, template.HTML(s)) + } + } + } + + // Parse info fields. + table.Datetime = template.HTML(time.Now().Format(time.RFC3339)) + table.Script = template.HTML(o.BuildScript(command)) +} diff --git a/db/commands2/gen_model/generator.tpl b/db/commands2/gen_model/generator.tpl new file mode 100644 index 0000000..a1b0800 --- /dev/null +++ b/db/commands2/gen_model/generator.tpl @@ -0,0 +1,64 @@ +// Do not edit this file. +// It's generated by console command at {{.Datetime}}. You can +// enter follow script on terminal like follow: +// +// cd /data/sketch +// {{.Script}} + +package {{.ModelPkg}} + +{{- if gt (len .PackageList) 0}} + +import ( + {{- range .PackageList}} + "{{.}}" + {{- end}} +) +{{- end}} + +// {{.ModelName}} +// is a model for table. +{{- if gt (len .CommentList) 0}} +// +{{- range .CommentList}} +// {{.}} +{{- end}} +{{- end}} +// +// Property: +// +// Collation : {{.Collation}} +// Engine : {{.Engine}} +// Format : {{.Format}} +// Table : {{.Name}} +type {{.ModelName}} struct { + {{- range .Columns}} + + {{- if gt (len .CommentList) 0}} + // {{.ExportName}} + {{- range .CommentList}} + // {{.}} + {{- end}} + // + {{- end}} + // Property: + {{- if .Collation}} + // Collation: {{.Collation}} + {{- end}} + {{- if .Default}} + // Default: {{.Default}} + {{- end}} + {{- if .Extra}} + // Extra: {{.Extra}} + {{- end}} + // Null: {{.Null}} + // Type: {{.Type}} + {{.ExportName}} {{.ExportType}} `xorm:"{{.ExportOrm}}" json:"{{.ExportJson}}"` + {{- end}} +} + +// TableName +// returns a table name. It's an optional function. +func (o *{{.ModelName}}) TableName() string { + return "{{.Name}}" +} diff --git a/db/commands2/gen_model/provider.go b/db/commands2/gen_model/provider.go new file mode 100644 index 0000000..d248a07 --- /dev/null +++ b/db/commands2/gen_model/provider.go @@ -0,0 +1,90 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Author: wsfuyibing <682805@qq.com> +// Date: 2024-08-02 + +package gen_model + +import ( + "context" + "gitee.com/go-libs/console" + "gitee.com/go-libs/db-xorm/db/commands2" + "gitee.com/go-libs/db-xorm/db/commands2/base" + "gitee.com/go-wares/log" +) + +const ( + Name = base.CommandNameModel + Description = "Generate model files" + DefaultTargetPath = "app/models" +) + +// Provider +// is a component used to generate model files. +type Provider struct { + common *commands2.Common + command *console.Command +} + +// Before +// is a before runner hook handler for command. +func (o *Provider) Before(_ context.Context, _ *console.Container, command *console.Command) (err error) { + log.Config().SetLevel("error") + + // Read and validate + // options value. + // + // --base-dir + // --dsn + for _, fn := range []func() error{ + func() error { return o.common.ReadBaseDir(command, base.OptBaseDir, base.OptBaseDirDefault) }, + func() error { return o.common.BuildModule(command) }, + func() error { return o.common.ReadDsn(command, base.OptDsn) }, + func() error { return o.common.ReadExport(command, base.OptExport) }, + func() error { return o.common.ReadOverride(command, base.OptOverride) }, + func() error { return o.common.ReadPrefix(command, base.OptPrefix) }, + func() error { return o.common.ReadTargetPath(command, base.OptTargetPath, DefaultTargetPath) }, + func() error { return o.common.RegisterDatabase() }, + } { + if err = fn(); err != nil { + break + } + } + return +} + +// Run +// is a runner hook handler for command. +func (o *Provider) Run(ctx context.Context, container *console.Container, command *console.Command) (err error) { + var tables []*base.Table + + // Return error + // if tables list failed. + if tables, err = o.common.ListTable(ctx, command); err != nil { + return + } + + // Iterate + // tables and generate it. + for _, table := range tables { + if err = (&Generator{ + Common: o.common, + Command: command, + Container: container, + Table: table, + }).Run(ctx); err != nil { + break + } + } + return +} diff --git a/db/commands2/gen_service/generator.go b/db/commands2/gen_service/generator.go new file mode 100644 index 0000000..73662d2 --- /dev/null +++ b/db/commands2/gen_service/generator.go @@ -0,0 +1,64 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Author: wsfuyibing <682805@qq.com> +// Date: 2024-08-16 + +package gen_service + +import ( + "context" + "fmt" + "gitee.com/go-libs/console" + "gitee.com/go-libs/db-xorm/db/commands2" + "gitee.com/go-libs/db-xorm/db/commands2/base" +) + +// Generator +// is a component for generate model files. +type Generator struct { + Common *commands2.Common + Command *console.Command + Container *console.Container + Table *base.Table + Target base.Target // /data/sketch/app/service/example_service.go +} + +func (o *Generator) Run(ctx context.Context) (err error) { + var can bool + + // Build + // a path for service file. + o.Target = base.Target( + fmt.Sprintf(`%s/%s/%s_service.go`, + o.Common.BaseDir, + o.Common.TargetPath, + o.Table.Name.FileName(o.Common.Prefix), + ), + ) + + // Override + // state check for target file. + if can, err = o.Target.Can(o.Common.Override); err != nil { + return err + } + + // Return + // for service file existing and not allow override. + if !can { + o.Container.GetOutput().Info(`generate service: %s`, o.Target) + return + } + + o.Container.GetOutput().Info(`generate service: %s`, o.Target) + return +} -- Gitee From 7a5e43fd67bfbb4ba3e972bed4196cb8f8a2f608 Mon Sep 17 00:00:00 2001 From: wsfuyibing Date: Mon, 19 Aug 2024 11:05:14 +0800 Subject: [PATCH 02/11] new version --- db/commands/gen/model_command.go | 21 +++++ db/commands/gen/model_config.go | 83 +++++++++++++++++ db/commands/gen/model_convert.go | 23 +++++ db/commands/model/command.go | 117 ++++++++++++------------ db/commands/service/command.go | 131 ++++++++++++++------------- db/commands2/base/constants.go | 51 +++++++++++ db/commands2/base/convertor.go | 23 +++++ db/commands2/base/table.go | 62 +++++++++++++ db/commands2/base/target.go | 117 ++++++++++++++++++++++++ db/commands2/conf/init.go | 35 +++++++ db/commands2/conf/mapping.go | 75 +++++++++++++++ db/commands2/conf/model_command.go | 25 +++++ db/commands2/conf/model_config.go | 110 ++++++++++++++++++++++ db/commands2/gen_model/command.go | 88 ++++++++++++++++++ db/commands2/gen_model/generator.go | 79 ++++++++++++++++ db/commands2/gen_service/command.go | 97 ++++++++++++++++++++ db/commands2/gen_service/provider.go | 91 +++++++++++++++++++ 17 files changed, 1107 insertions(+), 121 deletions(-) create mode 100644 db/commands/gen/model_command.go create mode 100644 db/commands/gen/model_config.go create mode 100644 db/commands/gen/model_convert.go create mode 100644 db/commands2/base/constants.go create mode 100644 db/commands2/base/convertor.go create mode 100644 db/commands2/base/table.go create mode 100644 db/commands2/base/target.go create mode 100644 db/commands2/conf/init.go create mode 100644 db/commands2/conf/mapping.go create mode 100644 db/commands2/conf/model_command.go create mode 100644 db/commands2/conf/model_config.go create mode 100644 db/commands2/gen_model/command.go create mode 100644 db/commands2/gen_model/generator.go create mode 100644 db/commands2/gen_service/command.go create mode 100644 db/commands2/gen_service/provider.go diff --git a/db/commands/gen/model_command.go b/db/commands/gen/model_command.go new file mode 100644 index 0000000..adb68c9 --- /dev/null +++ b/db/commands/gen/model_command.go @@ -0,0 +1,21 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Author: wsfuyibing <682805@qq.com> +// Date: 2024-08-16 + +package gen + +type ModelCommand struct { + Fields map[string]*ModelConvert `yaml:"fields"` + Types map[string]*ModelConvert `yaml:"types"` +} diff --git a/db/commands/gen/model_config.go b/db/commands/gen/model_config.go new file mode 100644 index 0000000..a420609 --- /dev/null +++ b/db/commands/gen/model_config.go @@ -0,0 +1,83 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Author: wsfuyibing <682805@qq.com> +// Date: 2024-08-16 + +package gen + +import "gitee.com/go-libs/config" + +var singletonModelConfig *ModelConfig + +// ModelConfig +// is a config component for generate model file. +// +// Path: +// +// config/console.yaml +// +// Example: +// +// commands: +// gen:model: +// fields: +// table.status: +// type: app.Status +// pkg: sketch/app +// types: +// date: +// type: db.Date +// pkg: gitee.com/go-libs/db-xorm/db +// datetime: +// type: db.Datetime +// pkg: gitee.com/go-libs/db-xorm/db +type ModelConfig struct { + err error + Commands map[string]*ModelCommand `yaml:"commands"` +} + +// NewModelConfig +// creates singleton config instance for model generator. +func NewModelConfig() *ModelConfig { + if singletonModelConfig == nil { + singletonModelConfig = (&ModelConfig{}).init() + } + return singletonModelConfig +} + +// GetConvert +// returns a convert definition if configured in yaml. +// +// gen.NewModelConfig().GetConvert("gen:model", "task.status", "int") +// gen.NewModelConfig().GetConvert("gen:model", "task.created_at", "datetime") +func (o *ModelConfig) GetConvert(cmd, field, typ string) *ModelConvert { + if c, ok := o.Commands[cmd]; ok { + if cvt, has := c.Fields[field]; has { + return cvt + } + if cvt, has := c.Types[typ]; has { + return cvt + } + } + return nil +} + +func (o *ModelConfig) After() { + if o.Commands == nil { + } +} + +func (o *ModelConfig) init() *ModelConfig { + o.err = config.Seek("console.yml", "console.yaml").ScanYaml(o) + return o +} diff --git a/db/commands/gen/model_convert.go b/db/commands/gen/model_convert.go new file mode 100644 index 0000000..d8ccb41 --- /dev/null +++ b/db/commands/gen/model_convert.go @@ -0,0 +1,23 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Author: wsfuyibing <682805@qq.com> +// Date: 2024-08-16 + +package gen + +// ModelConvert +// is a component used to define exported type and package. +type ModelConvert struct { + Pkg string `yaml:"pkg"` + Type string `yaml:"type"` +} diff --git a/db/commands/model/command.go b/db/commands/model/command.go index 0faf54d..ab3b681 100644 --- a/db/commands/model/command.go +++ b/db/commands/model/command.go @@ -16,73 +16,76 @@ package model import ( - "gitee.com/go-libs/console" - "gitee.com/go-libs/db-xorm/db/commands" + "gitee.com/go-libs/console" + "gitee.com/go-libs/db-xorm/db/commands" + "gitee.com/go-libs/db-xorm/db/commands2/gen_model" ) -// New +var New = gen_model.New + +// New2 // creates a console command. -func New() *console.Command { - // Creates - // a provider instance. - provider := &Provider{common: &commands.Common{}} +func New2() *console.Command { + // Creates + // a provider instance. + provider := &Provider{common: &commands.Common{}} - // Creates - // a command for provider. - provider.command = console.NewCommand(Name). - SetDescription(Description) + // Creates + // a command for provider. + provider.command = console.NewCommand(Name). + SetDescription(Description) - // Append options on command. - provider.command.Add( - // Working directory. - // - // go run main.go gen:model --base-dir=/data/sketch - console.NewOption(OptBaseDir). - SetShortName(OptBaseDirShort). - SetDescription(OptBaseDirDesc). - SetDefaultValue(OptBaseDirDefault), + // Append options on command. + provider.command.Add( + // Working directory. + // + // go run main.go gen:model --base-dir=/data/sketch + console.NewOption(OptBaseDir). + SetShortName(OptBaseDirShort). + SetDescription(OptBaseDirDesc). + SetDefaultValue(OptBaseDirDefault), - // Data source name. - // - // go run main.go gen:model --dsn="root:pass@tcp(127.0.0.1:3306)/test" - console.NewOption(OptDsn). - SetDescription(OptDsnDesc), + // Data source name. + // + // go run main.go gen:model --dsn="root:pass@tcp(127.0.0.1:3306)/test" + console.NewOption(OptDsn). + SetDescription(OptDsnDesc), - // Which table will be exported. - // - // go run main.go gen:model --export="user" - console.NewOption(OptExport). - SetShortName(OptExportShort). - SetDescription(OptExportDesc). - SetRequired(true), + // Which table will be exported. + // + // go run main.go gen:model --export="user" + console.NewOption(OptExport). + SetShortName(OptExportShort). + SetDescription(OptExportDesc). + SetRequired(true), - // Override existing files. - // - // go run main.go gen:model --override - console.NewNullOption(OptOverride). - SetDescription(OptOverrideDesc), + // Override existing files. + // + // go run main.go gen:model --override + console.NewNullOption(OptOverride). + SetDescription(OptOverrideDesc), - // Which table will be exported. - // - // go run main.go gen:model --prefix="cdb_" - console.NewOption(OptPrefix). - SetShortName(OptPrefixShort). - SetDescription(OptPrefixDesc), + // Which table will be exported. + // + // go run main.go gen:model --prefix="cdb_" + console.NewOption(OptPrefix). + SetShortName(OptPrefixShort). + SetDescription(OptPrefixDesc), - // Target path. - // - // go run main.go gen:model --target-path=app/models - console.NewOption(OptTargetPath). - SetShortName(OptTargetPathShort). - SetDescription(OptTargetPathDesc). - SetDefaultValue(OptTargetPathDefault), - ) + // Target path. + // + // go run main.go gen:model --target-path=app/models + console.NewOption(OptTargetPath). + SetShortName(OptTargetPathShort). + SetDescription(OptTargetPathDesc). + SetDefaultValue(OptTargetPathDefault), + ) - // Bind - // provider to command. - provider.command.SetProvider(provider) + // Bind + // provider to command. + provider.command.SetProvider(provider) - // Returns - // a command of the provider. - return provider.command + // Returns + // a command of the provider. + return provider.command } diff --git a/db/commands/service/command.go b/db/commands/service/command.go index d4bc786..7cfbc34 100644 --- a/db/commands/service/command.go +++ b/db/commands/service/command.go @@ -16,81 +16,84 @@ package service import ( - "gitee.com/go-libs/console" - "gitee.com/go-libs/db-xorm/db/commands" + "gitee.com/go-libs/console" + "gitee.com/go-libs/db-xorm/db/commands" + "gitee.com/go-libs/db-xorm/db/commands2/gen_service" ) -// New +var New = gen_service.New + +// New2 // creates a console command. -func New() *console.Command { - // Creates - // a provider instance. - provider := &Provider{common: &commands.Common{}} +func New2() *console.Command { + // Creates + // a provider instance. + provider := &Provider{common: &commands.Common{}} - // Creates - // a command for provider. - provider.command = console.NewCommand(Name). - SetDescription(Description) + // Creates + // a command for provider. + provider.command = console.NewCommand(Name). + SetDescription(Description) - // Append options on command. - provider.command.Add( - // Working directory. - // - // go run main.go gen:service --base-dir=/data/sketch - console.NewOption(OptBaseDir). - SetShortName(OptBaseDirShort). - SetDescription(OptBaseDirDesc). - SetDefaultValue(OptBaseDirDefault), + // Append options on command. + provider.command.Add( + // Working directory. + // + // go run main.go gen:service --base-dir=/data/sketch + console.NewOption(OptBaseDir). + SetShortName(OptBaseDirShort). + SetDescription(OptBaseDirDesc). + SetDefaultValue(OptBaseDirDefault), - // Data source name. - // - // go run main.go gen:service --dsn="root:pass@tcp(127.0.0.1:3306)/test" - console.NewOption(OptDsn). - SetDescription(OptDsnDesc), + // Data source name. + // + // go run main.go gen:service --dsn="root:pass@tcp(127.0.0.1:3306)/test" + console.NewOption(OptDsn). + SetDescription(OptDsnDesc), - // Which table will be exported. - // - // go run main.go gen:service --export="user" - console.NewOption(OptExport). - SetShortName(OptExportShort). - SetDescription(OptExportDesc). - SetRequired(true), + // Which table will be exported. + // + // go run main.go gen:service --export="user" + console.NewOption(OptExport). + SetShortName(OptExportShort). + SetDescription(OptExportDesc). + SetRequired(true), - // Model path. - // - // go run main.go gen:service --model-path=app/models - console.NewOption(OptModelPath). - SetShortName(OptModelPathShort). - SetDescription(OptModelPathDesc). - SetDefaultValue(OptModelPathDefault), + // Model path. + // + // go run main.go gen:service --model-path=app/models + console.NewOption(OptModelPath). + SetShortName(OptModelPathShort). + SetDescription(OptModelPathDesc). + SetDefaultValue(OptModelPathDefault), - // Override existing files. - // - // go run main.go gen:service --override - console.NewNullOption(OptOverride). - SetDescription(OptOverrideDesc), + // Override existing files. + // + // go run main.go gen:service --override + console.NewNullOption(OptOverride). + SetDescription(OptOverrideDesc), - // Which table will be exported. - // - // go run main.go gen:service --prefix="cdb_" - console.NewOption(OptPrefix). - SetShortName(OptPrefixShort). - SetDescription(OptPrefixDesc), + // Which table will be exported. + // + // go run main.go gen:service --prefix="cdb_" + console.NewOption(OptPrefix). + SetShortName(OptPrefixShort). + SetDescription(OptPrefixDesc), - // Target path. - // - // go run main.go gen:service --target-path=app/services - console.NewOption(OptTargetPath). - SetShortName(OptTargetPathShort). - SetDescription(OptTargetPathDesc). - SetDefaultValue(OptTargetPathDefault), - ) + // Target path. + // + // go run main.go gen:service --target-path=app/services + console.NewOption(OptTargetPath). + SetShortName(OptTargetPathShort). + SetDescription(OptTargetPathDesc). + SetDefaultValue(OptTargetPathDefault), + ) - // Bind - // provider to command. - provider.command.SetProvider(provider) + // Bind + // provider to command. + provider.command.SetProvider(provider) - // Returns - // a command of the provider. - return provider.command + // Returns + // a command of the provider. + return provider.command } diff --git a/db/commands2/base/constants.go b/db/commands2/base/constants.go new file mode 100644 index 0000000..7d4b01a --- /dev/null +++ b/db/commands2/base/constants.go @@ -0,0 +1,51 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Author: wsfuyibing <682805@qq.com> +// Date: 2024-08-16 + +package base + +const ( + CommandNameModel = "gen:model" + CommandNameService = "gen:service" +) + +const ( + OptBaseDir = "base-dir" + OptBaseDirDefault = "./" + OptBaseDirDesc = "Application working directory" + OptBaseDirShort = 'b' + + OptDsn = "dsn" + OptDsnDesc = "Database source name for connection, e.g. root:pass@tcp(127.0.0.1:3306)/test" + + OptExport = "export" + OptExportDesc = "Specify export names, split with comma" + OptExportShort = 'e' + + OptModelPath = "model-path" + OptModelPathDefault = "app/models" + OptModelPathDesc = "Generated model files location" + OptModelPathShort = 'm' + + OptOverride = "override" + OptOverrideDesc = "Override existing files" + + OptPrefix = "prefix" + OptPrefixDesc = "Prefix name for table" + OptPrefixShort = 'p' + + OptTargetPath = "target-path" + OptTargetPathDesc = "Generated files saved to" + OptTargetPathShort = 't' +) diff --git a/db/commands2/base/convertor.go b/db/commands2/base/convertor.go new file mode 100644 index 0000000..83cf8cf --- /dev/null +++ b/db/commands2/base/convertor.go @@ -0,0 +1,23 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Author: wsfuyibing <682805@qq.com> +// Date: 2024-08-16 + +package base + +// Convertor +// is a component used to defined exported type for model generator. +type Convertor struct { + Pkg string `yaml:"pkg"` + Type string `yaml:"type"` +} diff --git a/db/commands2/base/table.go b/db/commands2/base/table.go new file mode 100644 index 0000000..e53ee75 --- /dev/null +++ b/db/commands2/base/table.go @@ -0,0 +1,62 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Author: wsfuyibing <682805@qq.com> +// Date: 2024-08-02 + +package base + +import ( + "html/template" + "sort" +) + +// Table +// is a component for table definition (DDL). +type Table struct { + // Normal fields. + Engine string `xorm:"Engine"` + Format string `xorm:"Row_format"` + Name ItemName `xorm:"Name"` + Comment ItemComment `xorm:"Comment"` + Collation ItemCollation `xorm:"Collation"` + + // Belongs to. + Columns []*Column `xorm:"-"` + PackageList []string + PackageMapper map[string]bool + + // Info fields. + CommentList []template.HTML `xorm:"-"` + Datetime template.HTML `xorm:"-"` + Script template.HTML `xorm:"-"` + + // Execution fields. + ModelName string `xorm:"-"` + ModelPkg string `xorm:"-"` +} + +func (o *Table) Add(pkg string) { + if o.PackageList == nil || o.PackageMapper == nil { + o.PackageList = make([]string, 0) + o.PackageMapper = make(map[string]bool) + } + + if _, ok := o.PackageMapper[pkg]; ok { + return + } + + o.PackageList = append(o.PackageList, pkg) + o.PackageMapper[pkg] = true + + sort.Strings(o.PackageList) +} diff --git a/db/commands2/base/target.go b/db/commands2/base/target.go new file mode 100644 index 0000000..49c2467 --- /dev/null +++ b/db/commands2/base/target.go @@ -0,0 +1,117 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Author: wsfuyibing <682805@qq.com> +// Date: 2024-08-07 + +package base + +import ( + "context" + "errors" + "fmt" + "html/template" + "os" + "regexp" +) + +// Target +// is a type name for generated file path. +// +// Example: +// +// Target("/data/sketch/app/models/example.go") +// Target("/data/sketch/app/services/example_service.go") +type Target string + +// Can +// return true if target file can be saved. +func (o Target) Can(override bool) (bool, error) { + // Return true + // if override enabled. + if override { + return true, nil + } + + // Stat + // target file. + _, err := os.Stat(o.String()) + + // Return false + // if target file is existed. + if err == nil { + return false, nil + } + + // Return true + // if target file is not exists. + if errors.Is(err, os.ErrNotExist) { + return true, nil + } + + // Unknown + // error. + return false, err +} + +// Save +// template text to target file. +func (o Target) Save(_ context.Context, text string, result any) (err error) { + var ( + file *os.File + info os.FileInfo + target = o.String() + tpl *template.Template + ) + + // Make directory. + if path := regexp.MustCompile(`/([^/]+)$`).ReplaceAllString(target, ""); path != target { + if info, err = os.Stat(path); err != nil { + if errors.Is(err, os.ErrNotExist) { + err = nil + } else { + return + } + } else if !info.IsDir() { + err = fmt.Errorf(`invalid directory`) + return + } + } + + // Open + // a file, Create new file if not exists. + if file, err = os.OpenFile(target, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm); err != nil { + return + } + + // Close + // file resource when done. + defer func() { _ = file.Close() }() + + // Execute + // template variables with given data. + if tpl, err = template.New("template").Parse(text); err == nil { + err = tpl.Execute(file, result) + } + return +} + +// String +// returns a path string. +// +// Output: +// +// /data/sketch/app/models/example.go +// /data/sketch/app/services/example_service.go +func (o Target) String() string { + return string(o) +} diff --git a/db/commands2/conf/init.go b/db/commands2/conf/init.go new file mode 100644 index 0000000..f397015 --- /dev/null +++ b/db/commands2/conf/init.go @@ -0,0 +1,35 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Author: wsfuyibing <682805@qq.com> +// Date: 2024-08-16 + +package conf + +import ( + "gitee.com/go-libs/db-xorm/db/commands2/base" + "sync" +) + +var ( + builtinMapping Mapping + builtinUndefined *base.Convertor + once = new(sync.Once) +) + +func init() { + once.Do(func() { + builtinMapping = make(Mapping).builtin() + builtinUndefined = &base.Convertor{Type: "any"} + Model = (&model{}).init() + }) +} diff --git a/db/commands2/conf/mapping.go b/db/commands2/conf/mapping.go new file mode 100644 index 0000000..e38a45a --- /dev/null +++ b/db/commands2/conf/mapping.go @@ -0,0 +1,75 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Author: wsfuyibing <682805@qq.com> +// Date: 2024-08-16 + +package conf + +import "gitee.com/go-libs/db-xorm/db/commands2/base" + +// Mapping +// is a field type mapping to convertor. +type Mapping map[string]*base.Convertor + +// Add +// adds a convertor for name into mapping. +func (o Mapping) Add(name string, convertor *base.Convertor) { + o[name] = convertor +} + +// Get +// gets a convertor with given name from mapping. +func (o Mapping) Get(name string) *base.Convertor { + if convertor, ok := o[name]; ok { + return convertor + } + return nil +} + +// +---------------------------------------------------------------------------+ +// | Hook methods | +// +---------------------------------------------------------------------------+ + +func (o Mapping) builtin() Mapping { + for name, convertor := range map[string]*base.Convertor{ + // Int + "tinyint": {Type: "int"}, + "smallint": {Type: "int"}, + "mediumint": {Type: "int"}, + "int": {Type: "int"}, + "integer": {Type: "int"}, + "bigint": {Type: "int64"}, + + // Float64 + "decimal": {Type: "float64"}, + "double": {Type: "float64"}, + "float": {Type: "float64"}, + + // String + "char": {Type: "string"}, + "varchar": {Type: "string"}, + "text": {Type: "string"}, + "longtext": {Type: "string"}, + "enum": {Type: "string"}, + + // Blob. + "blob": {Type: "[]byte"}, + + // Date & time + "date": {Pkg: "gitee.com/go-libs/db-xorm/db", Type: "db.Date"}, + "datetime": {Pkg: "gitee.com/go-libs/db-xorm/db", Type: "db.Datetime"}, + } { + o.Add(name, convertor) + } + return o +} diff --git a/db/commands2/conf/model_command.go b/db/commands2/conf/model_command.go new file mode 100644 index 0000000..ebf3b39 --- /dev/null +++ b/db/commands2/conf/model_command.go @@ -0,0 +1,25 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Author: wsfuyibing <682805@qq.com> +// Date: 2024-08-16 + +package conf + +import "gitee.com/go-libs/db-xorm/db/commands2/base" + +// ModelCommand +// is a component for each command. +type ModelCommand struct { + Fields map[string]*base.Convertor `yaml:"fields"` + Types map[string]*base.Convertor `yaml:"types"` +} diff --git a/db/commands2/conf/model_config.go b/db/commands2/conf/model_config.go new file mode 100644 index 0000000..594f492 --- /dev/null +++ b/db/commands2/conf/model_config.go @@ -0,0 +1,110 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Author: wsfuyibing <682805@qq.com> +// Date: 2024-08-16 + +package conf + +import ( + "gitee.com/go-libs/config" + "gitee.com/go-libs/db-xorm/db/commands2/base" +) + +var Model ModelConfig + +type ( + // ModelConfig + // is an interface for configuration operate. + // + // Path: + // + // config/console.yaml + // + // Example: + // + // commands: + // gen:model: + // fields: + // task.status: + // pkg: sketch/app + // type: app.Status + // task.concurrency: + // type: int32 + // task.created_at: + // pkg: gitee.com/go-libs/db-xorm/db + // type: db.Datetime + // types: + // date: + // pkg: gitee.com/go-libs/db-xorm/db + // type: db.Date + // datetime: + // pkg: gitee.com/go-libs/db-xorm/db + // type: db.Datetime + ModelConfig interface { + // Get + // returns a configured convertor in console.yaml. + Get(field, typ string) *base.Convertor + + // Mapping + // returns the builtin mapping. + Mapping() Mapping + } + + model struct { + err error + Commands map[string]*ModelCommand `yaml:"commands"` + } +) + +// Get +// returns a configured convertor in console.yaml. +func (o *model) Get(field, typ string) (convertor *base.Convertor) { + var has bool + + defer func() { + println("type input(<", field, "><", typ, ">) & output(<", convertor.Type, "><", convertor.Pkg, ">)") + }() + + // Use configured convertor. + if c, ok := o.Commands[base.CommandNameModel]; ok { + // Primary for field. + if convertor, has = c.Fields[field]; has { + return + } + + // Secondary for type. + if convertor, has = c.Types[typ]; has { + return + } + } + + // For builtin mapping. + if convertor = builtinMapping.Get(typ); convertor != nil { + return + } + + // For undefined. + convertor = builtinUndefined + return +} + +// Mapping +// returns the builtin mapping. +func (o *model) Mapping() Mapping { + return builtinMapping +} + +func (o *model) init() *model { + o.err = config.Seek("console.yml", "console.yaml").ScanYaml(o) + return o +} diff --git a/db/commands2/gen_model/command.go b/db/commands2/gen_model/command.go new file mode 100644 index 0000000..c3027f5 --- /dev/null +++ b/db/commands2/gen_model/command.go @@ -0,0 +1,88 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Author: wsfuyibing <682805@qq.com> +// Date: 2024-08-02 + +package gen_model + +import ( + "gitee.com/go-libs/console" + "gitee.com/go-libs/db-xorm/db/commands2" + "gitee.com/go-libs/db-xorm/db/commands2/base" +) + +// New +// creates a console command. +func New() *console.Command { + // Creates + // a provider instance. + provider := &Provider{common: &commands2.Common{}} + + // Creates + // a command for provider. + provider.command = console.NewCommand(Name).SetDescription(Description) + + // Append options on command. + provider.command.Add( + // Working directory. + // + // go run main.go gen:model --base-dir=/data/sketch + console.NewOption(base.OptBaseDir). + SetShortName(base.OptBaseDirShort). + SetDescription(base.OptBaseDirDesc). + SetDefaultValue(base.OptBaseDirDefault), + + // Data source name. + // + // go run main.go gen:model --dsn="root:pass@tcp(127.0.0.1:3306)/test" + console.NewOption(base.OptDsn). + SetDescription(base.OptDsnDesc), + + // Which table will be exported. + // + // go run main.go gen:model --export="user" + console.NewOption(base.OptExport). + SetShortName(base.OptExportShort). + SetDescription(base.OptExportDesc). + SetRequired(true), + + // Override existing files. + // + // go run main.go gen:model --override + console.NewNullOption(base.OptOverride). + SetDescription(base.OptOverrideDesc), + + // Which table will be exported. + // + // go run main.go gen:model --prefix="cdb_" + console.NewOption(base.OptPrefix). + SetShortName(base.OptPrefixShort). + SetDescription(base.OptPrefixDesc), + + // Target path. + // + // go run main.go gen:model --target-path=app/models + console.NewOption(base.OptTargetPath). + SetShortName(base.OptTargetPathShort). + SetDescription(base.OptTargetPathDesc). + SetDefaultValue(DefaultTargetPath), + ) + + // Bind + // provider to command. + provider.command.SetProvider(provider) + + // Returns + // a command of the provider. + return provider.command +} diff --git a/db/commands2/gen_model/generator.go b/db/commands2/gen_model/generator.go new file mode 100644 index 0000000..d2f8e29 --- /dev/null +++ b/db/commands2/gen_model/generator.go @@ -0,0 +1,79 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Author: wsfuyibing <682805@qq.com> +// Date: 2024-08-16 + +package gen_model + +import ( + "context" + _ "embed" + "fmt" + "gitee.com/go-libs/console" + "gitee.com/go-libs/db-xorm/db/commands2" + "gitee.com/go-libs/db-xorm/db/commands2/base" +) + +//go:embed generator.tpl +var template string + +// Generator +// is a component for generate model files. +type Generator struct { + Common *commands2.Common + Command *console.Command + Container *console.Container + Table *base.Table + Target base.Target +} + +func (o *Generator) Run(ctx context.Context) (err error) { + var can bool + + // Build + // a path for service file. + o.Target = base.Target( + fmt.Sprintf(`%s/%s/%s.go`, + o.Common.BaseDir, + o.Common.TargetPath, + o.Table.Name.FileName(o.Common.Prefix), + ), + ) + + // Override + // state check for target file. + if can, err = o.Target.Can(o.Common.Override); err != nil { + return err + } + + // Return + // for service file existing and not allow override. + if !can { + o.Container.GetOutput().Info(` [ignored] %s`, o.Target) + return + } + + // Generate related fields. + o.Table.ModelName = o.Table.Name.StructName(o.Common.Prefix) + o.Table.ModelPkg = o.Common.TargetPkg + + // Save + // generated result. + if err = o.Target.Save(ctx, template, o.Table); err != nil { + return + } + + // Generate success. + o.Container.GetOutput().Info(` [succeed] %s`, o.Target) + return +} diff --git a/db/commands2/gen_service/command.go b/db/commands2/gen_service/command.go new file mode 100644 index 0000000..726bdd3 --- /dev/null +++ b/db/commands2/gen_service/command.go @@ -0,0 +1,97 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Author: wsfuyibing <682805@qq.com> +// Date: 2024-08-02 + +package gen_service + +import ( + "gitee.com/go-libs/console" + "gitee.com/go-libs/db-xorm/db/commands2" + "gitee.com/go-libs/db-xorm/db/commands2/base" +) + +// New +// creates a console command. +func New() *console.Command { + // Creates + // a provider instance. + provider := &Provider{common: &commands2.Common{}} + + // Creates + // a command for provider. + provider.command = console.NewCommand(Name). + SetDescription(Description) + + // Append options on command. + provider.command.Add( + // Working directory. + // + // go run main.go gen:service --base-dir=/data/sketch + console.NewOption(base.OptBaseDir). + SetShortName(base.OptBaseDirShort). + SetDescription(base.OptBaseDirDesc). + SetDefaultValue(base.OptBaseDirDefault), + + // Data source name. + // + // go run main.go gen:service --dsn="root:pass@tcp(127.0.0.1:3306)/test" + console.NewOption(base.OptDsn). + SetDescription(base.OptDsnDesc), + + // Which table will be exported. + // + // go run main.go gen:service --export="user" + console.NewOption(base.OptExport). + SetShortName(base.OptExportShort). + SetDescription(base.OptExportDesc). + SetRequired(true), + + // Model path. + // + // go run main.go gen:service --model-path=app/models + console.NewOption(base.OptModelPath). + SetShortName(base.OptModelPathShort). + SetDescription(base.OptModelPathDesc). + SetDefaultValue(base.OptModelPathDefault), + + // Override existing files. + // + // go run main.go gen:service --override + console.NewNullOption(base.OptOverride). + SetDescription(base.OptOverrideDesc), + + // Which table will be exported. + // + // go run main.go gen:service --prefix="cdb_" + console.NewOption(base.OptPrefix). + SetShortName(base.OptPrefixShort). + SetDescription(base.OptPrefixDesc), + + // Target path. + // + // go run main.go gen:service --target-path=app/services + console.NewOption(base.OptTargetPath). + SetShortName(base.OptTargetPathShort). + SetDescription(base.OptTargetPathDesc). + SetDefaultValue(DefaultTargetPath), + ) + + // Bind + // provider to command. + provider.command.SetProvider(provider) + + // Returns + // a command of the provider. + return provider.command +} diff --git a/db/commands2/gen_service/provider.go b/db/commands2/gen_service/provider.go new file mode 100644 index 0000000..8080159 --- /dev/null +++ b/db/commands2/gen_service/provider.go @@ -0,0 +1,91 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Author: wsfuyibing <682805@qq.com> +// Date: 2024-08-02 + +package gen_service + +import ( + "context" + "gitee.com/go-libs/console" + "gitee.com/go-libs/db-xorm/db/commands2" + "gitee.com/go-libs/db-xorm/db/commands2/base" + "gitee.com/go-wares/log" +) + +const ( + Name = base.CommandNameService + Description = "Generate service files" + DefaultTargetPath = "app/services" +) + +// Provider +// is a component used to generate service files. +type Provider struct { + common *commands2.Common + command *console.Command +} + +// Before +// is a before runner hook handler for command. +func (o *Provider) Before(_ context.Context, _ *console.Container, command *console.Command) (err error) { + log.Config().SetLevel("error") + + // Read and validate + // options value. + // + // --base-dir + // --dsn + for _, fn := range []func() error{ + func() error { return o.common.ReadBaseDir(command, base.OptBaseDir, base.OptBaseDirDefault) }, + func() error { return o.common.BuildModule(command) }, + func() error { return o.common.ReadDsn(command, base.OptDsn) }, + func() error { return o.common.ReadExport(command, base.OptExport) }, + func() error { return o.common.ReadModelPath(command, base.OptModelPath, base.OptModelPathDefault) }, + func() error { return o.common.ReadOverride(command, base.OptOverride) }, + func() error { return o.common.ReadPrefix(command, base.OptPrefix) }, + func() error { return o.common.ReadTargetPath(command, base.OptTargetPath, DefaultTargetPath) }, + func() error { return o.common.RegisterDatabase() }, + } { + if err = fn(); err != nil { + break + } + } + return +} + +// Run +// is a runner hook handler for command. +func (o *Provider) Run(ctx context.Context, container *console.Container, command *console.Command) (err error) { + var tables []*base.Table + + // Return error + // if tables list failed. + if tables, err = o.common.ListTable(ctx, command); err != nil { + return + } + + // Iterate + // tables and generate it. + for _, table := range tables { + if err = (&Generator{ + Common: o.common, + Command: command, + Container: container, + Table: table, + }).Run(ctx); err != nil { + break + } + } + return +} -- Gitee From e54ccd075abe3daae80f258290587c828738cfae Mon Sep 17 00:00:00 2001 From: wsfuyibing Date: Mon, 19 Aug 2024 11:06:25 +0800 Subject: [PATCH 03/11] new version --- db/commands2/conf/model_config.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/db/commands2/conf/model_config.go b/db/commands2/conf/model_config.go index 594f492..12fffaf 100644 --- a/db/commands2/conf/model_config.go +++ b/db/commands2/conf/model_config.go @@ -71,10 +71,6 @@ type ( func (o *model) Get(field, typ string) (convertor *base.Convertor) { var has bool - defer func() { - println("type input(<", field, "><", typ, ">) & output(<", convertor.Type, "><", convertor.Pkg, ">)") - }() - // Use configured convertor. if c, ok := o.Commands[base.CommandNameModel]; ok { // Primary for field. -- Gitee From d4581cc5633fba9ef1c6fa396651fd44f6458d2a Mon Sep 17 00:00:00 2001 From: wsfuyibing Date: Mon, 19 Aug 2024 13:55:18 +0800 Subject: [PATCH 04/11] new version --- db/commands2/base/table.go | 4 ++-- db/commands2/common.go | 22 ++++++++++++++++++---- db/commands2/gen_model/generator.go | 3 +-- db/commands2/gen_service/generator.go | 18 ++++++++++++++++-- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/db/commands2/base/table.go b/db/commands2/base/table.go index e53ee75..127006d 100644 --- a/db/commands2/base/table.go +++ b/db/commands2/base/table.go @@ -41,8 +41,8 @@ type Table struct { Script template.HTML `xorm:"-"` // Execution fields. - ModelName string `xorm:"-"` - ModelPkg string `xorm:"-"` + ModelName, ServiceName string `xorm:"-"` + ModelPkg, ServicePkg string `xorm:"-"` } func (o *Table) Add(pkg string) { diff --git a/db/commands2/common.go b/db/commands2/common.go index 335e89f..9c060d9 100644 --- a/db/commands2/common.go +++ b/db/commands2/common.go @@ -124,9 +124,9 @@ func (o *Common) ListTable(ctx context.Context, command *console.Command) (table // Format // table fields. - o.formatTable(command, table) + o.FormatTable(command, table) for _, column := range table.Columns { - o.formatColumn(command, table, column) + o.FormatColumn(command, table, column) } // Append @@ -306,7 +306,7 @@ func (o *Common) RegisterDatabase() error { }) } -func (o *Common) formatColumn(command *console.Command, table *base.Table, column *base.Column) { +func (o *Common) FormatColumn(command *console.Command, table *base.Table, column *base.Column) { // Bind relation of a table. column.Table = table @@ -347,7 +347,7 @@ func (o *Common) formatColumn(command *console.Command, table *base.Table, colum column.IsPrimaryKey = column.Key.IsPrimary() } -func (o *Common) formatTable(command *console.Command, table *base.Table) { +func (o *Common) FormatTable(command *console.Command, table *base.Table) { // Build comment list of a table. if len(table.Comment.Strings()) > 0 { table.CommentList = make([]template.HTML, 0) @@ -362,3 +362,17 @@ func (o *Common) formatTable(command *console.Command, table *base.Table) { table.Datetime = template.HTML(time.Now().Format(time.RFC3339)) table.Script = template.HTML(o.BuildScript(command)) } + +func (o *Common) FormatTableAsModel(command *console.Command, table *base.Table) { + table.ModelName = table.Name.StructName(o.Prefix) + table.ModelPkg = o.TargetPkg +} + +func (o *Common) FormatTableAsService(command *console.Command, table *base.Table) { + table.ModelName = table.Name.StructName(o.Prefix) + table.ServiceName = fmt.Sprintf(`%sService`, table.ModelName) + + table.ModelPkg = o.ModelPkg + table.ServicePkg = o.TargetPkg + table.Add(`gitee.com/go-libs/db-xorm/db`) +} diff --git a/db/commands2/gen_model/generator.go b/db/commands2/gen_model/generator.go index d2f8e29..0d0cb3b 100644 --- a/db/commands2/gen_model/generator.go +++ b/db/commands2/gen_model/generator.go @@ -64,8 +64,7 @@ func (o *Generator) Run(ctx context.Context) (err error) { } // Generate related fields. - o.Table.ModelName = o.Table.Name.StructName(o.Common.Prefix) - o.Table.ModelPkg = o.Common.TargetPkg + o.Common.FormatTableAsModel(o.Command, o.Table) // Save // generated result. diff --git a/db/commands2/gen_service/generator.go b/db/commands2/gen_service/generator.go index 73662d2..a2e7a67 100644 --- a/db/commands2/gen_service/generator.go +++ b/db/commands2/gen_service/generator.go @@ -17,12 +17,16 @@ package gen_service import ( "context" + _ "embed" "fmt" "gitee.com/go-libs/console" "gitee.com/go-libs/db-xorm/db/commands2" "gitee.com/go-libs/db-xorm/db/commands2/base" ) +//go:embed generator.tpl +var template string + // Generator // is a component for generate model files. type Generator struct { @@ -55,10 +59,20 @@ func (o *Generator) Run(ctx context.Context) (err error) { // Return // for service file existing and not allow override. if !can { - o.Container.GetOutput().Info(`generate service: %s`, o.Target) + o.Container.GetOutput().Info(` [ignored] %s`, o.Target) + return + } + + // Generate related fields. + o.Common.FormatTableAsService(o.Command, o.Table) + + // Save + // generated result. + if err = o.Target.Save(ctx, template, o.Table); err != nil { return } - o.Container.GetOutput().Info(`generate service: %s`, o.Target) + // Generate success. + o.Container.GetOutput().Info(` [succeed] %s`, o.Target) return } -- Gitee From 69912dc3b816817a98ba24fc61a233d0cb561240 Mon Sep 17 00:00:00 2001 From: wsfuyibing Date: Mon, 19 Aug 2024 13:55:27 +0800 Subject: [PATCH 05/11] new version --- db/commands2/gen_service/generator.tpl | 31 ++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 db/commands2/gen_service/generator.tpl diff --git a/db/commands2/gen_service/generator.tpl b/db/commands2/gen_service/generator.tpl new file mode 100644 index 0000000..e42c704 --- /dev/null +++ b/db/commands2/gen_service/generator.tpl @@ -0,0 +1,31 @@ +// Do not edit this file. +// It's generated by console command at {{.Datetime}}. You can +// enter follow script on terminal like follow: +// +// cd /data/sketch +// {{.Script}} + +package {{.ServicePkg}} + +{{- if gt (len .PackageList) 0}} + +import ( + {{- range .PackageList}} + "{{.}}" + {{- end}} +) +{{- end}} + +// {{.ServiceName}} +// is a database operator for {{.Name}} table. +type {{.ServiceName}} struct { + db.Service +} + +// New{{.ServiceName}} +// creates a database operator service for {{.Name}} table. +func New{{.ServiceName}}(sess ... *db.Session) *{{.ServiceName}}{ + o := &{{.ServiceName}}{} + o.With(sess...) + return o +} -- Gitee From 40c462447a17b3a09df88b63ab87a6b6d69f7ba3 Mon Sep 17 00:00:00 2001 From: wsfuyibing Date: Mon, 19 Aug 2024 14:03:38 +0800 Subject: [PATCH 06/11] new version --- db/commands2/common.go | 4 +++- db/commands2/gen_service/generator.tpl | 29 ++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/db/commands2/common.go b/db/commands2/common.go index 9c060d9..e94c7be 100644 --- a/db/commands2/common.go +++ b/db/commands2/common.go @@ -127,6 +127,9 @@ func (o *Common) ListTable(ctx context.Context, command *console.Command) (table o.FormatTable(command, table) for _, column := range table.Columns { o.FormatColumn(command, table, column) + + // if column.IsPrimaryKey { + // } } // Append @@ -338,7 +341,6 @@ func (o *Common) FormatColumn(command *console.Command, table *base.Table, colum if column.ExportPkg != "" { table.Add(column.ExportPkg) } - // column.ExportPkg, column.ExportType = column.Type.Convert(command) } column.IsDate = column.Type.IsDate() diff --git a/db/commands2/gen_service/generator.tpl b/db/commands2/gen_service/generator.tpl index e42c704..7ebad36 100644 --- a/db/commands2/gen_service/generator.tpl +++ b/db/commands2/gen_service/generator.tpl @@ -29,3 +29,32 @@ func New{{.ServiceName}}(sess ... *db.Session) *{{.ServiceName}}{ o.With(sess...) return o } +{{- if .PrimaryName}} + +// GetBy{{.PrimaryName}} +// method is generated by console command. It's return a model struct +// if exists otherwise nil returned. +func (o *{{.ServiceName}}) GetBy{{.PrimaryName}}(ctx context.Context, val {{.PrimaryType}}) (model *{{.ModelPkg}}.{{.ModelName}}, err error){ + var ( + has bool + sess *db.Session + ) + + // Open + // a connect session from slave server. + if sess, err = o.Slave(ctx); err != nil { + return + } + + // Prepare + // an empty result model. + model = &{{.ModelPkg}}.{{.ModelName}}{} + + // Send data + // to slave session and get one result. + if has, err = sess.Where("`{{.PrimaryFieldName}}` = ?", val).Get(model); err != nil || !has { + model = nil + } + return +} +{{- end}} \ No newline at end of file -- Gitee From 0248676d2b06bd184fce77fa962b4e845b82c1b5 Mon Sep 17 00:00:00 2001 From: wsfuyibing Date: Mon, 19 Aug 2024 14:20:36 +0800 Subject: [PATCH 07/11] new version --- db/commands2/base/table.go | 11 ++++- db/commands2/common.go | 14 +++++- db/commands2/gen_service/generator.tpl | 59 ++++++++++++++++++++++++++ 3 files changed, 80 insertions(+), 4 deletions(-) diff --git a/db/commands2/base/table.go b/db/commands2/base/table.go index 127006d..ffb09f1 100644 --- a/db/commands2/base/table.go +++ b/db/commands2/base/table.go @@ -41,8 +41,15 @@ type Table struct { Script template.HTML `xorm:"-"` // Execution fields. - ModelName, ServiceName string `xorm:"-"` - ModelPkg, ServicePkg string `xorm:"-"` + ModelName string `xorm:"-"` + ModelPkg string `xorm:"-"` + ServiceName string `xorm:"-"` + ServicePkg string `xorm:"-"` + + // Primary prop. + PrimaryName string `xorm:"-"` + PrimaryFieldName string `xorm:"-"` + PrimaryType string `xorm:"-"` } func (o *Table) Add(pkg string) { diff --git a/db/commands2/common.go b/db/commands2/common.go index e94c7be..0866c6b 100644 --- a/db/commands2/common.go +++ b/db/commands2/common.go @@ -128,8 +128,16 @@ func (o *Common) ListTable(ctx context.Context, command *console.Command) (table for _, column := range table.Columns { o.FormatColumn(command, table, column) - // if column.IsPrimaryKey { - // } + // Bind primary on table. + if column.IsPrimaryKey { + if convertor := conf.Model.Get(fmt.Sprintf(`%s.%s`, table.Name, column.Field), column.Type.Origin()); convertor != nil { + table.PrimaryName = column.Field.ToLargeCamel() + table.PrimaryFieldName = column.Field.String() + table.PrimaryType = convertor.Type + } else { + column.IsPrimaryKey = false + } + } } // Append @@ -376,5 +384,7 @@ func (o *Common) FormatTableAsService(command *console.Command, table *base.Tabl table.ModelPkg = o.ModelPkg table.ServicePkg = o.TargetPkg + + table.Add(`context`) table.Add(`gitee.com/go-libs/db-xorm/db`) } diff --git a/db/commands2/gen_service/generator.tpl b/db/commands2/gen_service/generator.tpl index 7ebad36..63ffaf1 100644 --- a/db/commands2/gen_service/generator.tpl +++ b/db/commands2/gen_service/generator.tpl @@ -29,8 +29,67 @@ func New{{.ServiceName}}(sess ... *db.Session) *{{.ServiceName}}{ o.With(sess...) return o } + +// Add +// adds a new record with given param. +func (o *{{.ServiceName}}) Add(ctx context.Context, req *{{.ModelPkg}}.{{.ModelName}}) (model *{{.ModelPkg}}.{{.ModelName}}, err error) { + var ( + affects int64 + sess *db.Session + ) + + // Open + // a connect session from master server. + if sess, err = o.Master(ctx); err != nil { + return + } + + // Prepare + // model fields for insert without primary key. Datetime use builtin + // methods. + model = &{{.ModelPkg}}.{{.ModelName}}{ + {{- range .Columns}} + {{- if not .IsPrimaryKey}} + {{- if .IsDate}} + {{.ExportName}}: db.NewDate(), + {{- else if or .IsDatetime .IsDatetimeOnUpdate}} + {{.ExportName}}: db.NewDatetime(), + {{- else}} + {{.ExportName}}: req.{{.ExportName}}, + {{- end}} + {{- end}} + {{- end}} + } + + // Send data + // to master session and parse result. + if affects, err = sess.Insert(model); err != nil || affects == 0 { + model = nil + } + return +} {{- if .PrimaryName}} +// DelBy{{.PrimaryName}} +// method is generated by console command. It's deletes a record by primary key. +func (o *{{.ServiceName}}) DelBy{{.PrimaryName}}(ctx context.Context, val {{.PrimaryType}}) (affects int64, err error) { + var ( + sess *db.Session + model = &{{.ModelPkg}}.{{.ModelName}}{} + ) + + // Open + // a connect session from master server. + if sess, err = o.Master(ctx); err != nil { + return + } + + // Send data + // to master session and return affect count. + affects, err = sess.Where("`{{.PrimaryFieldName}}` = ?", val).Delete(model) + return +} + // GetBy{{.PrimaryName}} // method is generated by console command. It's return a model struct // if exists otherwise nil returned. -- Gitee From 506e192f2fb929e5580a8e2178b08ca2835424d2 Mon Sep 17 00:00:00 2001 From: wsfuyibing Date: Mon, 19 Aug 2024 14:29:01 +0800 Subject: [PATCH 08/11] new version --- db/{commands2 => commands}/base/constants.go | 0 db/{commands2 => commands}/base/convertor.go | 0 db/{commands2 => commands}/base/table.go | 0 .../base/table_column.go | 0 db/{commands2 => commands}/base/table_type.go | 0 db/{commands2 => commands}/base/target.go | 0 db/commands/column.go | 57 --- db/commands/common.go | 140 ++++++- db/{commands2 => commands}/conf/init.go | 2 +- db/{commands2 => commands}/conf/mapping.go | 2 +- .../conf/model_command.go | 2 +- .../conf/model_config.go | 2 +- db/commands/gen/model_config.go | 83 ---- .../gen_model/command.go | 6 +- .../gen_model/generator.go | 8 +- .../gen_model/generator.tpl | 0 .../gen_model/provider.go | 6 +- .../gen_service/command.go | 6 +- .../gen_service/generator.go | 8 +- .../gen_service/generator.tpl | 0 .../gen_service/provider.go | 6 +- db/commands/generator.go | 54 --- db/commands/generator_common.go | 68 --- db/commands/generator_model.go | 51 --- db/commands/generator_service.go | 63 --- db/commands/mapping.go | 95 ----- db/commands/model/command.go | 91 ---- db/commands/model/provider.go | 143 ------- db/commands/service/command.go | 99 ----- db/commands/service/provider.go | 149 ------- db/commands/table.go | 28 -- db/commands/target.go | 117 ------ db/commands/templates/model.tpl | 60 --- db/commands/templates/service.tpl | 123 ------ db/commands/types.go | 360 ---------------- .../model/command.go} | 13 +- .../service/command.go} | 15 +- db/commands2/common.go | 390 ------------------ 38 files changed, 158 insertions(+), 2089 deletions(-) rename db/{commands2 => commands}/base/constants.go (100%) rename db/{commands2 => commands}/base/convertor.go (100%) rename db/{commands2 => commands}/base/table.go (100%) rename db/{commands2 => commands}/base/table_column.go (100%) rename db/{commands2 => commands}/base/table_type.go (100%) rename db/{commands2 => commands}/base/target.go (100%) delete mode 100644 db/commands/column.go rename db/{commands2 => commands}/conf/init.go (95%) rename db/{commands2 => commands}/conf/mapping.go (97%) rename db/{commands2 => commands}/conf/model_command.go (93%) rename db/{commands2 => commands}/conf/model_config.go (98%) delete mode 100644 db/commands/gen/model_config.go rename db/{commands2 => commands}/gen_model/command.go (94%) rename db/{commands2 => commands}/gen_model/generator.go (91%) rename db/{commands2 => commands}/gen_model/generator.tpl (100%) rename db/{commands2 => commands}/gen_model/provider.go (95%) rename db/{commands2 => commands}/gen_service/command.go (94%) rename db/{commands2 => commands}/gen_service/generator.go (91%) rename db/{commands2 => commands}/gen_service/generator.tpl (100%) rename db/{commands2 => commands}/gen_service/provider.go (95%) delete mode 100644 db/commands/generator.go delete mode 100644 db/commands/generator_common.go delete mode 100644 db/commands/generator_model.go delete mode 100644 db/commands/generator_service.go delete mode 100644 db/commands/mapping.go delete mode 100644 db/commands/model/command.go delete mode 100644 db/commands/model/provider.go delete mode 100644 db/commands/service/command.go delete mode 100644 db/commands/service/provider.go delete mode 100644 db/commands/table.go delete mode 100644 db/commands/target.go delete mode 100644 db/commands/templates/model.tpl delete mode 100644 db/commands/templates/service.tpl delete mode 100644 db/commands/types.go rename db/{commands/gen/model_command.go => commands1/model/command.go} (79%) rename db/{commands/gen/model_convert.go => commands1/service/command.go} (75%) delete mode 100644 db/commands2/common.go diff --git a/db/commands2/base/constants.go b/db/commands/base/constants.go similarity index 100% rename from db/commands2/base/constants.go rename to db/commands/base/constants.go diff --git a/db/commands2/base/convertor.go b/db/commands/base/convertor.go similarity index 100% rename from db/commands2/base/convertor.go rename to db/commands/base/convertor.go diff --git a/db/commands2/base/table.go b/db/commands/base/table.go similarity index 100% rename from db/commands2/base/table.go rename to db/commands/base/table.go diff --git a/db/commands2/base/table_column.go b/db/commands/base/table_column.go similarity index 100% rename from db/commands2/base/table_column.go rename to db/commands/base/table_column.go diff --git a/db/commands2/base/table_type.go b/db/commands/base/table_type.go similarity index 100% rename from db/commands2/base/table_type.go rename to db/commands/base/table_type.go diff --git a/db/commands2/base/target.go b/db/commands/base/target.go similarity index 100% rename from db/commands2/base/target.go rename to db/commands/base/target.go diff --git a/db/commands/column.go b/db/commands/column.go deleted file mode 100644 index 7c24b20..0000000 --- a/db/commands/column.go +++ /dev/null @@ -1,57 +0,0 @@ -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Author: wsfuyibing <682805@qq.com> -// Date: 2024-08-02 - -package commands - -import "gitee.com/go-libs/console" - -// Column -// is a component for table definition (DDL). -type Column struct { - Field ItemName `xorm:"Field"` - Collation ItemCollation `xorm:"Collation"` - Comment ItemComment `xorm:"Comment"` - Type ColumnType `xorm:"Type"` - Default ColumnDefault `xorm:"Default"` - Key ColumnKey `xorm:"Key"` - Null ColumnNull `xorm:"Null"` - Extra ColumnExtra `xorm:"Extra"` - - ExportName string `xorm:"-"` // for field name. e.g. Id, UserId etc - ExportType string `xorm:"-"` // for field type. e.g. int, db.Date, db.Datetime etc - - ExportJson string `xorm:"-"` // for field tag. e.g. id, user_id etc - ExportOrm string `xorm:"-"` // for field tag. e.g. id pk autoincr, user_id etc - ExportPkg string `xorm:"-"` // for field tag. e.g. models, services etc - - IsDate bool `xorm:"-"` - IsDatetime bool `xorm:"-"` - IsDatetimeOnUpdate bool `xorm:"-"` - IsPrimaryKey bool `xorm:"-"` -} - -// Parse -// parses the result field to usage fields. -func (o *Column) Parse(command *console.Command) { - o.ExportName = o.Field.ToSame() - o.ExportPkg, o.ExportType = o.Type.Convert(command) - o.ExportOrm = o.Extra.Convert(o.Field.String()) - o.ExportJson = o.Field.ToSnake() - - o.IsDate = o.Type.IsDate() - o.IsDatetime = o.Type.IsDatetime() - o.IsDatetimeOnUpdate = o.Extra.IsDatetimeOnUpdate() - o.IsPrimaryKey = o.Key.IsPrimary() -} diff --git a/db/commands/common.go b/db/commands/common.go index ec563eb..4cc6e28 100644 --- a/db/commands/common.go +++ b/db/commands/common.go @@ -21,19 +21,18 @@ import ( "fmt" "gitee.com/go-libs/console" "gitee.com/go-libs/db-xorm/db" + "gitee.com/go-libs/db-xorm/db/commands/base" + "gitee.com/go-libs/db-xorm/db/commands/conf" "html/template" "path/filepath" "regexp" "strings" + "time" ) -const ( - DsnKey = "_gen:commands_" -) +const DsnKey = "_gen:commands_" -var ( - RegexMatchPkg = regexp.MustCompile(`([_a-zA-Z0-9]+)$`) -) +var RegexMatchPkg = regexp.MustCompile(`([_a-zA-Z0-9]+)$`) type Common struct { BaseDir string @@ -52,27 +51,24 @@ func (o *Common) BuildModule(command *console.Command) (err error) { err = fmt.Errorf(`can not parse module name from go.mod`) return } - if o.ModuleFolder != "" { - o.ModuleFolder = fmt.Sprintf(`/%s`, - strings.TrimPrefix(o.ModuleFolder, "/"), - ) + o.ModuleFolder = fmt.Sprintf(`/%s`, strings.TrimPrefix(o.ModuleFolder, "/")) } return } // BuildScript // build command runner script. -func (o *Common) BuildScript(command *console.Command) template.HTML { - return template.HTML(fmt.Sprintf(`go run main.go %s`, command.ToScript())) +func (o *Common) BuildScript(command *console.Command) string { + return fmt.Sprintf(`go run main.go %s`, command.ToScript()) } // ListTable // returns a list for tables in a database. -func (o *Common) ListTable(ctx context.Context, command *console.Command) (tables []*Table, err error) { +func (o *Common) ListTable(ctx context.Context, command *console.Command) (tables []*base.Table, err error) { var ( all bool - list []*Table + list []*base.Table names = make(map[string]string) named = make(map[string]bool) session *db.Session @@ -98,7 +94,7 @@ func (o *Common) ListTable(ctx context.Context, command *console.Command) (table // Prepare // table list. - tables = make([]*Table, 0) + tables = make([]*base.Table, 0) // Select // all tables in database and columns of the table. @@ -126,9 +122,22 @@ func (o *Common) ListTable(ctx context.Context, command *console.Command) (table break } - // Init fields. - for _, x := range table.Columns { - x.Parse(command) + // Format + // table fields. + o.FormatTable(command, table) + for _, column := range table.Columns { + o.FormatColumn(command, table, column) + + // Bind primary on table. + if column.IsPrimaryKey { + if convertor := conf.Model.Get(fmt.Sprintf(`%s.%s`, table.Name, column.Field), column.Type.Origin()); convertor != nil { + table.PrimaryName = column.Field.ToLargeCamel() + table.PrimaryFieldName = column.Field.String() + table.PrimaryType = convertor.Type + } else { + column.IsPrimaryKey = false + } + } } // Append @@ -140,7 +149,7 @@ func (o *Common) ListTable(ctx context.Context, command *console.Command) (table // Exported // name in command argument not found. - for k, _ := range names { + for k := range names { if _, ok := named[k]; !ok { err = fmt.Errorf(`table not found: %s`, k) return @@ -154,6 +163,8 @@ func (o *Common) ListTable(ctx context.Context, command *console.Command) (table return } +// ReadBaseDir +// read absolute path of the application. func (o *Common) ReadBaseDir(command *console.Command, key, value string) (err error) { // Read // from command options. @@ -176,6 +187,8 @@ func (o *Common) ReadBaseDir(command *console.Command, key, value string) (err e return } +// ReadDsn +// read database source name. func (o *Common) ReadDsn(command *console.Command, key string) (err error) { // Read dsn // from command options. @@ -193,10 +206,13 @@ func (o *Common) ReadDsn(command *console.Command, key string) (err error) { return } + // Error read. err = fmt.Errorf(`dsn can not be blank`) return } +// ReadExport +// read export names. func (o *Common) ReadExport(command *console.Command, key string) (err error) { if opt, has := command.GetOption(key); has { if s := opt.ToString(); s != "" { @@ -206,6 +222,8 @@ func (o *Common) ReadExport(command *console.Command, key string) (err error) { return } +// ReadModelPath +// read path for model files location. func (o *Common) ReadModelPath(command *console.Command, key, value string) (err error) { // Read // from command options. @@ -226,15 +244,19 @@ func (o *Common) ReadModelPath(command *console.Command, key, value string) (err // to absolute path. o.ModelPath = value + // Read package name for model. if m := RegexMatchPkg.FindStringSubmatch(value); len(m) > 0 { o.ModelPkg = m[1] return } + // Error read. err = fmt.Errorf(`can not parse package name for target`) return } +// ReadOverride +// read override state for existing files. func (o *Common) ReadOverride(command *console.Command, key string) (err error) { if opt, has := command.GetOption(key); has { o.Override = opt.GetSpecified() @@ -242,6 +264,8 @@ func (o *Common) ReadOverride(command *console.Command, key string) (err error) return } +// ReadPrefix +// read prefix for table name. func (o *Common) ReadPrefix(command *console.Command, key string) (err error) { if opt, has := command.GetOption(key); has { if s := opt.ToString(); s != "" { @@ -251,6 +275,8 @@ func (o *Common) ReadPrefix(command *console.Command, key string) (err error) { return } +// ReadTargetPath +// read path for generated files save to. func (o *Common) ReadTargetPath(command *console.Command, key, value string) (err error) { // Read // from command options. @@ -271,20 +297,94 @@ func (o *Common) ReadTargetPath(command *console.Command, key, value string) (er // to absolute path. o.TargetPath = value + // Read package for generated files save to. if m := RegexMatchPkg.FindStringSubmatch(value); len(m) > 0 { o.TargetPkg = m[1] return } + // Error read. err = fmt.Errorf(`can not parse package name for target`) return } // RegisterDatabase -// adds a database connect configurations. +// adds a database connect configuration. func (o *Common) RegisterDatabase() error { return db.Config.Add(DsnKey, &db.Database{ Dsn: []string{o.Dsn}, Mapper: "snake", }) } + +func (o *Common) FormatColumn(command *console.Command, table *base.Table, column *base.Column) { + // Bind relation of a table. + column.Table = table + + // Build comment list of a table. + if len(column.Comment.Strings()) > 0 { + column.CommentList = make([]template.HTML, 0) + for _, s := range column.Comment.Strings() { + if s = strings.TrimSpace(s); s != "" { + column.CommentList = append(column.CommentList, template.HTML(s)) + } + } + } + + // Parse info fields. + column.Datetime = template.HTML(time.Now().Format(time.RFC3339)) + column.Script = template.HTML(o.BuildScript(command)) + + // Parse name fields. + column.ExportName = column.Field.StructName(o.Prefix) + column.ExportJson = column.Field.ToSnake() + column.ExportOrm = column.Extra.Convert(column.Field) + + // Type convert. + if convert := conf.Model.Get(fmt.Sprintf(`%s.%s`, table.Name, column.Field), column.Type.Origin()); convert != nil { + column.ExportPkg = convert.Pkg + column.ExportType = convert.Type + + // Append package. + if column.ExportPkg != "" { + table.Add(column.ExportPkg) + } + } + + column.IsDate = column.Type.IsDate() + column.IsDatetime = column.Type.IsDatetime() + column.IsDatetimeOnUpdate = column.Extra.IsDatetimeOnUpdate() + column.IsPrimaryKey = column.Key.IsPrimary() +} + +func (o *Common) FormatTable(command *console.Command, table *base.Table) { + // Build comment list of a table. + if len(table.Comment.Strings()) > 0 { + table.CommentList = make([]template.HTML, 0) + for _, s := range table.Comment.Strings() { + if s = strings.TrimSpace(s); s != "" { + table.CommentList = append(table.CommentList, template.HTML(s)) + } + } + } + + // Parse info fields. + table.Datetime = template.HTML(time.Now().Format(time.RFC3339)) + table.Script = template.HTML(o.BuildScript(command)) +} + +func (o *Common) FormatTableAsModel(table *base.Table) { + table.ModelName = table.Name.StructName(o.Prefix) + table.ModelPkg = o.TargetPkg +} + +func (o *Common) FormatTableAsService(table *base.Table) { + table.ModelName = table.Name.StructName(o.Prefix) + table.ServiceName = fmt.Sprintf(`%sService`, table.ModelName) + + table.ModelPkg = o.ModelPkg + table.ServicePkg = o.TargetPkg + + table.Add(`context`) + table.Add(`gitee.com/go-libs/db-xorm/db`) +} diff --git a/db/commands2/conf/init.go b/db/commands/conf/init.go similarity index 95% rename from db/commands2/conf/init.go rename to db/commands/conf/init.go index f397015..7abc8e6 100644 --- a/db/commands2/conf/init.go +++ b/db/commands/conf/init.go @@ -16,7 +16,7 @@ package conf import ( - "gitee.com/go-libs/db-xorm/db/commands2/base" + "gitee.com/go-libs/db-xorm/db/commands/base" "sync" ) diff --git a/db/commands2/conf/mapping.go b/db/commands/conf/mapping.go similarity index 97% rename from db/commands2/conf/mapping.go rename to db/commands/conf/mapping.go index e38a45a..e5e5dfb 100644 --- a/db/commands2/conf/mapping.go +++ b/db/commands/conf/mapping.go @@ -15,7 +15,7 @@ package conf -import "gitee.com/go-libs/db-xorm/db/commands2/base" +import "gitee.com/go-libs/db-xorm/db/commands/base" // Mapping // is a field type mapping to convertor. diff --git a/db/commands2/conf/model_command.go b/db/commands/conf/model_command.go similarity index 93% rename from db/commands2/conf/model_command.go rename to db/commands/conf/model_command.go index ebf3b39..9e6ac74 100644 --- a/db/commands2/conf/model_command.go +++ b/db/commands/conf/model_command.go @@ -15,7 +15,7 @@ package conf -import "gitee.com/go-libs/db-xorm/db/commands2/base" +import "gitee.com/go-libs/db-xorm/db/commands/base" // ModelCommand // is a component for each command. diff --git a/db/commands2/conf/model_config.go b/db/commands/conf/model_config.go similarity index 98% rename from db/commands2/conf/model_config.go rename to db/commands/conf/model_config.go index 12fffaf..6089326 100644 --- a/db/commands2/conf/model_config.go +++ b/db/commands/conf/model_config.go @@ -17,7 +17,7 @@ package conf import ( "gitee.com/go-libs/config" - "gitee.com/go-libs/db-xorm/db/commands2/base" + "gitee.com/go-libs/db-xorm/db/commands/base" ) var Model ModelConfig diff --git a/db/commands/gen/model_config.go b/db/commands/gen/model_config.go deleted file mode 100644 index a420609..0000000 --- a/db/commands/gen/model_config.go +++ /dev/null @@ -1,83 +0,0 @@ -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Author: wsfuyibing <682805@qq.com> -// Date: 2024-08-16 - -package gen - -import "gitee.com/go-libs/config" - -var singletonModelConfig *ModelConfig - -// ModelConfig -// is a config component for generate model file. -// -// Path: -// -// config/console.yaml -// -// Example: -// -// commands: -// gen:model: -// fields: -// table.status: -// type: app.Status -// pkg: sketch/app -// types: -// date: -// type: db.Date -// pkg: gitee.com/go-libs/db-xorm/db -// datetime: -// type: db.Datetime -// pkg: gitee.com/go-libs/db-xorm/db -type ModelConfig struct { - err error - Commands map[string]*ModelCommand `yaml:"commands"` -} - -// NewModelConfig -// creates singleton config instance for model generator. -func NewModelConfig() *ModelConfig { - if singletonModelConfig == nil { - singletonModelConfig = (&ModelConfig{}).init() - } - return singletonModelConfig -} - -// GetConvert -// returns a convert definition if configured in yaml. -// -// gen.NewModelConfig().GetConvert("gen:model", "task.status", "int") -// gen.NewModelConfig().GetConvert("gen:model", "task.created_at", "datetime") -func (o *ModelConfig) GetConvert(cmd, field, typ string) *ModelConvert { - if c, ok := o.Commands[cmd]; ok { - if cvt, has := c.Fields[field]; has { - return cvt - } - if cvt, has := c.Types[typ]; has { - return cvt - } - } - return nil -} - -func (o *ModelConfig) After() { - if o.Commands == nil { - } -} - -func (o *ModelConfig) init() *ModelConfig { - o.err = config.Seek("console.yml", "console.yaml").ScanYaml(o) - return o -} diff --git a/db/commands2/gen_model/command.go b/db/commands/gen_model/command.go similarity index 94% rename from db/commands2/gen_model/command.go rename to db/commands/gen_model/command.go index c3027f5..9161c78 100644 --- a/db/commands2/gen_model/command.go +++ b/db/commands/gen_model/command.go @@ -17,8 +17,8 @@ package gen_model import ( "gitee.com/go-libs/console" - "gitee.com/go-libs/db-xorm/db/commands2" - "gitee.com/go-libs/db-xorm/db/commands2/base" + "gitee.com/go-libs/db-xorm/db/commands" + "gitee.com/go-libs/db-xorm/db/commands/base" ) // New @@ -26,7 +26,7 @@ import ( func New() *console.Command { // Creates // a provider instance. - provider := &Provider{common: &commands2.Common{}} + provider := &Provider{common: &commands.Common{}} // Creates // a command for provider. diff --git a/db/commands2/gen_model/generator.go b/db/commands/gen_model/generator.go similarity index 91% rename from db/commands2/gen_model/generator.go rename to db/commands/gen_model/generator.go index 0d0cb3b..9ae924d 100644 --- a/db/commands2/gen_model/generator.go +++ b/db/commands/gen_model/generator.go @@ -20,8 +20,8 @@ import ( _ "embed" "fmt" "gitee.com/go-libs/console" - "gitee.com/go-libs/db-xorm/db/commands2" - "gitee.com/go-libs/db-xorm/db/commands2/base" + "gitee.com/go-libs/db-xorm/db/commands" + "gitee.com/go-libs/db-xorm/db/commands/base" ) //go:embed generator.tpl @@ -30,7 +30,7 @@ var template string // Generator // is a component for generate model files. type Generator struct { - Common *commands2.Common + Common *commands.Common Command *console.Command Container *console.Container Table *base.Table @@ -64,7 +64,7 @@ func (o *Generator) Run(ctx context.Context) (err error) { } // Generate related fields. - o.Common.FormatTableAsModel(o.Command, o.Table) + o.Common.FormatTableAsModel(o.Table) // Save // generated result. diff --git a/db/commands2/gen_model/generator.tpl b/db/commands/gen_model/generator.tpl similarity index 100% rename from db/commands2/gen_model/generator.tpl rename to db/commands/gen_model/generator.tpl diff --git a/db/commands2/gen_model/provider.go b/db/commands/gen_model/provider.go similarity index 95% rename from db/commands2/gen_model/provider.go rename to db/commands/gen_model/provider.go index d248a07..e9e9072 100644 --- a/db/commands2/gen_model/provider.go +++ b/db/commands/gen_model/provider.go @@ -18,8 +18,8 @@ package gen_model import ( "context" "gitee.com/go-libs/console" - "gitee.com/go-libs/db-xorm/db/commands2" - "gitee.com/go-libs/db-xorm/db/commands2/base" + "gitee.com/go-libs/db-xorm/db/commands" + "gitee.com/go-libs/db-xorm/db/commands/base" "gitee.com/go-wares/log" ) @@ -32,7 +32,7 @@ const ( // Provider // is a component used to generate model files. type Provider struct { - common *commands2.Common + common *commands.Common command *console.Command } diff --git a/db/commands2/gen_service/command.go b/db/commands/gen_service/command.go similarity index 94% rename from db/commands2/gen_service/command.go rename to db/commands/gen_service/command.go index 726bdd3..c05d3bb 100644 --- a/db/commands2/gen_service/command.go +++ b/db/commands/gen_service/command.go @@ -17,8 +17,8 @@ package gen_service import ( "gitee.com/go-libs/console" - "gitee.com/go-libs/db-xorm/db/commands2" - "gitee.com/go-libs/db-xorm/db/commands2/base" + "gitee.com/go-libs/db-xorm/db/commands" + "gitee.com/go-libs/db-xorm/db/commands/base" ) // New @@ -26,7 +26,7 @@ import ( func New() *console.Command { // Creates // a provider instance. - provider := &Provider{common: &commands2.Common{}} + provider := &Provider{common: &commands.Common{}} // Creates // a command for provider. diff --git a/db/commands2/gen_service/generator.go b/db/commands/gen_service/generator.go similarity index 91% rename from db/commands2/gen_service/generator.go rename to db/commands/gen_service/generator.go index a2e7a67..1d321b8 100644 --- a/db/commands2/gen_service/generator.go +++ b/db/commands/gen_service/generator.go @@ -20,8 +20,8 @@ import ( _ "embed" "fmt" "gitee.com/go-libs/console" - "gitee.com/go-libs/db-xorm/db/commands2" - "gitee.com/go-libs/db-xorm/db/commands2/base" + "gitee.com/go-libs/db-xorm/db/commands" + "gitee.com/go-libs/db-xorm/db/commands/base" ) //go:embed generator.tpl @@ -30,7 +30,7 @@ var template string // Generator // is a component for generate model files. type Generator struct { - Common *commands2.Common + Common *commands.Common Command *console.Command Container *console.Container Table *base.Table @@ -64,7 +64,7 @@ func (o *Generator) Run(ctx context.Context) (err error) { } // Generate related fields. - o.Common.FormatTableAsService(o.Command, o.Table) + o.Common.FormatTableAsService(o.Table) // Save // generated result. diff --git a/db/commands2/gen_service/generator.tpl b/db/commands/gen_service/generator.tpl similarity index 100% rename from db/commands2/gen_service/generator.tpl rename to db/commands/gen_service/generator.tpl diff --git a/db/commands2/gen_service/provider.go b/db/commands/gen_service/provider.go similarity index 95% rename from db/commands2/gen_service/provider.go rename to db/commands/gen_service/provider.go index 8080159..6226681 100644 --- a/db/commands2/gen_service/provider.go +++ b/db/commands/gen_service/provider.go @@ -18,8 +18,8 @@ package gen_service import ( "context" "gitee.com/go-libs/console" - "gitee.com/go-libs/db-xorm/db/commands2" - "gitee.com/go-libs/db-xorm/db/commands2/base" + "gitee.com/go-libs/db-xorm/db/commands" + "gitee.com/go-libs/db-xorm/db/commands/base" "gitee.com/go-wares/log" ) @@ -32,7 +32,7 @@ const ( // Provider // is a component used to generate service files. type Provider struct { - common *commands2.Common + common *commands.Common command *console.Command } diff --git a/db/commands/generator.go b/db/commands/generator.go deleted file mode 100644 index e5b154b..0000000 --- a/db/commands/generator.go +++ /dev/null @@ -1,54 +0,0 @@ -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Author: wsfuyibing <682805@qq.com> -// Date: 2024-08-08 - -package commands - -import ( - "context" - _ "embed" - "gitee.com/go-libs/console" -) - -var ( - //go:embed templates/model.tpl - TemplateModel string - - //go:embed templates/service.tpl - TemplateService string -) - -// Generator -// is a component used to generate to source files. -type Generator struct { - Common *Common - Command *console.Command - Container *console.Container - Table *Table - Target Target -} - -// Model -// generate to model source file. -func (o *Generator) Model(ctx context.Context) (err error) { - data := (&GeneratorModel{}).init(o) - return o.Target.Save(ctx, TemplateModel, data) -} - -// Service -// generate to service source file. -func (o *Generator) Service(ctx context.Context) (err error) { - data := (&GeneratorService{}).init(o) - return o.Target.Save(ctx, TemplateService, data) -} diff --git a/db/commands/generator_common.go b/db/commands/generator_common.go deleted file mode 100644 index e2c7110..0000000 --- a/db/commands/generator_common.go +++ /dev/null @@ -1,68 +0,0 @@ -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Author: wsfuyibing <682805@qq.com> -// Date: 2024-08-08 - -package commands - -import ( - "html/template" - "sort" - "time" -) - -// +---------------------------------------------------------------------------+ -// | Common generator result | -// +---------------------------------------------------------------------------+ - -// GeneratorCommon -// is a common component for generator. -type GeneratorCommon struct { - Datetime template.HTML - Script template.HTML - Package string - StructName string - - Packages []string - Table *Table - - packagesMapper map[string]bool -} - -// AddPackage -// adds a package name to list. -func (o *GeneratorCommon) AddPackage(pkg string) { - if _, ok := o.packagesMapper[pkg]; !ok { - o.packagesMapper[pkg] = true - o.Packages = append(o.Packages, pkg) - } -} - -// SortPackage -// sorts package list with alphabet. -func (o *GeneratorCommon) SortPackage() { - sort.Strings(o.Packages) -} - -// Init -// common generator fields. -func (o *GeneratorCommon) init(g *Generator) *GeneratorCommon { - o.packagesMapper = make(map[string]bool) - - o.Datetime = template.HTML(time.Now().Format(time.RFC3339)) - o.Package = g.Common.TargetPkg - o.Script = template.HTML(g.Command.ToScript()) - o.Packages = make([]string, 0) - o.Table = g.Table - return o -} diff --git a/db/commands/generator_model.go b/db/commands/generator_model.go deleted file mode 100644 index 3d1208d..0000000 --- a/db/commands/generator_model.go +++ /dev/null @@ -1,51 +0,0 @@ -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Author: wsfuyibing <682805@qq.com> -// Date: 2024-08-12 - -package commands - -// +---------------------------------------------------------------------------+ -// | Model generator result | -// +---------------------------------------------------------------------------+ - -// GeneratorModel -// is a component for generate model. -type GeneratorModel struct { - GeneratorCommon -} - -// Init -// model fields. -func (o *GeneratorModel) init(g *Generator) *GeneratorModel { - // Init - // common fields. - o.GeneratorCommon.init(g) - - // Init - // field type packages. - for _, x := range o.Table.Columns { - if x.ExportPkg != "" { - o.AddPackage(x.ExportPkg) - } - } - - // Init - // export fields. - o.StructName = g.Table.Name.StructName(g.Common.Prefix) - - // Resort - // with alphabet. - o.SortPackage() - return o -} diff --git a/db/commands/generator_service.go b/db/commands/generator_service.go deleted file mode 100644 index 32b6b06..0000000 --- a/db/commands/generator_service.go +++ /dev/null @@ -1,63 +0,0 @@ -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Author: wsfuyibing <682805@qq.com> -// Date: 2024-08-12 - -package commands - -import "fmt" - -// +---------------------------------------------------------------------------+ -// | Service generator result | -// +---------------------------------------------------------------------------+ - -// GeneratorService -// is a component for generate service. -type GeneratorService struct { - GeneratorCommon - ModelName, ModelPkg string - - PrimaryName, PrimaryType, PrimaryFieldName string -} - -func (o *GeneratorService) init(g *Generator) *GeneratorService { - // Init - // common fields. - o.GeneratorCommon.init(g) - - // Init - // field type packages. - o.AddPackage("context") - o.AddPackage("gitee.com/go-libs/db-xorm/db") - o.AddPackage(fmt.Sprintf(`%s%s/%s`, g.Common.ModuleName, g.Common.ModuleFolder, g.Common.ModelPath)) - - // Init - // export fields. - o.ModelName = g.Table.Name.StructName(g.Common.Prefix) - o.ModelPkg = g.Common.ModelPkg - o.StructName = fmt.Sprintf(`%sService`, o.ModelName) - - // Check primary key. - for _, x := range g.Table.Columns { - if x.Key.IsPrimary() { - o.PrimaryName = x.Field.ToSame() - o.PrimaryFieldName = x.Field.String() - _, o.PrimaryType = x.Type.Convert(g.Command) - } - } - - // Resort - // with alphabet. - o.SortPackage() - return o -} diff --git a/db/commands/mapping.go b/db/commands/mapping.go deleted file mode 100644 index e3b619c..0000000 --- a/db/commands/mapping.go +++ /dev/null @@ -1,95 +0,0 @@ -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Author: wsfuyibing <682805@qq.com> -// Date: 2024-08-07 - -package commands - -import ( - "gitee.com/go-libs/config" - "strings" - "sync" -) - -var ( - once = new(sync.Once) - typeMapping *TypeMapping -) - -type ( - TypeMapping struct { - err error - Commands map[string]*TypeMappingCommand `yaml:"commands"` - } - TypeMappingCommand struct { - Packages map[string]string `yaml:"packages"` - Types map[string]string `yaml:"types"` - } -) - -func NewMapping() *TypeMapping { - return typeMapping -} - -func (o *TypeMapping) After() { - if o.Commands == nil { - o.Commands = make(map[string]*TypeMappingCommand) - } -} - -// Get -// returns library package and type name for field type if defined by config file. -// -// Config in console.yml: -// -// commands: -// gen:model: -// packages: -// datetime: "gitee.com/go-libs/db-xorm" -// types: -// datetime: "db.Datetime" -// -// Example: -// -// pkg, name, exists := NewMapping().Get("gen:model", "datetime") -// // Output: "xorm", "Time", true -// // "gitee.com/go-libs/db-xorm", "db.Datetime", true -func (o *TypeMapping) Get(cn, tn string) (pkg, name string, exists bool) { - if c, cok := o.Commands[cn]; cok { - if t, tok := c.Types[tn]; tok { - if t = strings.TrimSpace(t); t != "" { - exists = true - name = t - - // Custom package. - if k, kok := c.Packages[tn]; kok { - if k = strings.TrimSpace(k); k != "" { - pkg = k - } - } - } - } - } - return -} - -func (o *TypeMapping) init() *TypeMapping { - o.err = config.Seek("console.yml", "console.yaml").ScanYaml(o) - return o -} - -func init() { - once.Do(func() { - typeMapping = (&TypeMapping{}).init() - }) -} diff --git a/db/commands/model/command.go b/db/commands/model/command.go deleted file mode 100644 index ab3b681..0000000 --- a/db/commands/model/command.go +++ /dev/null @@ -1,91 +0,0 @@ -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Author: wsfuyibing <682805@qq.com> -// Date: 2024-08-02 - -package model - -import ( - "gitee.com/go-libs/console" - "gitee.com/go-libs/db-xorm/db/commands" - "gitee.com/go-libs/db-xorm/db/commands2/gen_model" -) - -var New = gen_model.New - -// New2 -// creates a console command. -func New2() *console.Command { - // Creates - // a provider instance. - provider := &Provider{common: &commands.Common{}} - - // Creates - // a command for provider. - provider.command = console.NewCommand(Name). - SetDescription(Description) - - // Append options on command. - provider.command.Add( - // Working directory. - // - // go run main.go gen:model --base-dir=/data/sketch - console.NewOption(OptBaseDir). - SetShortName(OptBaseDirShort). - SetDescription(OptBaseDirDesc). - SetDefaultValue(OptBaseDirDefault), - - // Data source name. - // - // go run main.go gen:model --dsn="root:pass@tcp(127.0.0.1:3306)/test" - console.NewOption(OptDsn). - SetDescription(OptDsnDesc), - - // Which table will be exported. - // - // go run main.go gen:model --export="user" - console.NewOption(OptExport). - SetShortName(OptExportShort). - SetDescription(OptExportDesc). - SetRequired(true), - - // Override existing files. - // - // go run main.go gen:model --override - console.NewNullOption(OptOverride). - SetDescription(OptOverrideDesc), - - // Which table will be exported. - // - // go run main.go gen:model --prefix="cdb_" - console.NewOption(OptPrefix). - SetShortName(OptPrefixShort). - SetDescription(OptPrefixDesc), - - // Target path. - // - // go run main.go gen:model --target-path=app/models - console.NewOption(OptTargetPath). - SetShortName(OptTargetPathShort). - SetDescription(OptTargetPathDesc). - SetDefaultValue(OptTargetPathDefault), - ) - - // Bind - // provider to command. - provider.command.SetProvider(provider) - - // Returns - // a command of the provider. - return provider.command -} diff --git a/db/commands/model/provider.go b/db/commands/model/provider.go deleted file mode 100644 index 31cdc9f..0000000 --- a/db/commands/model/provider.go +++ /dev/null @@ -1,143 +0,0 @@ -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Author: wsfuyibing <682805@qq.com> -// Date: 2024-08-02 - -package model - -import ( - "context" - "fmt" - "gitee.com/go-libs/console" - "gitee.com/go-libs/db-xorm/db/commands" - "gitee.com/go-wares/log" -) - -const ( - Name = "gen:model" - Description = "Generate model files" - - OptBaseDir = "base-dir" - OptBaseDirDefault = "./" - OptBaseDirDesc = "Application working directory" - OptBaseDirShort = 'b' - - OptDsn = "dsn" - OptDsnDesc = "Database source name for connection, e.g. root:pass@tcp(127.0.0.1:3306)/test" - - OptExport = "export" - OptExportDesc = "Which tables will be exported" - OptExportShort = 'e' - - OptOverride = "override" - OptOverrideDesc = "Override existing model files" - - OptPrefix = "prefix" - OptPrefixDesc = "Prefix name for table" - OptPrefixShort = 'p' - - OptTargetPath = "target-path" - OptTargetPathDefault = "app/models" - OptTargetPathDesc = "Generated model files saved to" - OptTargetPathShort = 't' -) - -// Provider -// is a component used to generate model files. -type Provider struct { - common *commands.Common - command *console.Command -} - -// Before -// is a before runner hook handler for command. -func (o *Provider) Before(_ context.Context, _ *console.Container, command *console.Command) (err error) { - log.Config().SetLevel("error") - - // Read and validate - // options value. - // - // --base-dir - // --dsn - for _, fn := range []func() error{ - func() error { return o.common.ReadBaseDir(command, OptBaseDir, OptBaseDirDefault) }, - func() error { return o.common.BuildModule(command) }, - func() error { return o.common.ReadDsn(command, OptDsn) }, - func() error { return o.common.ReadExport(command, OptExport) }, - func() error { return o.common.ReadOverride(command, OptOverride) }, - func() error { return o.common.ReadPrefix(command, OptPrefix) }, - func() error { return o.common.ReadTargetPath(command, OptTargetPath, OptTargetPathDefault) }, - func() error { return o.common.RegisterDatabase() }, - } { - if err = fn(); err != nil { - break - } - } - return -} - -// Run -// is a runner hook handler for command. -func (o *Provider) Run(ctx context.Context, container *console.Container, command *console.Command) (err error) { - var tables []*commands.Table - - // Return error - // if tables list failed. - if tables, err = o.common.ListTable(ctx, command); err != nil { - return - } - - // Iterate - // tables and generate it. - for _, table := range tables { - if err = o.generate(ctx, container, command, table); err != nil { - break - } - } - return -} - -// generate table to target file. -func (o *Provider) generate(ctx context.Context, container *console.Container, command *console.Command, table *commands.Table) (err error) { - var ( - can bool - name = fmt.Sprintf(`%s.go`, table.Name.FileName(o.common.Prefix)) - target = commands.Target(fmt.Sprintf(`%s/%s/%s`, o.common.BaseDir, o.common.TargetPath, name)) - ) - - // Check - // target file can override or not. - if can, err = target.Can(o.common.Override); err != nil { - return - } - - // Ignore - // if target exists and override not enabled. - if !can { - container.GetOutput().Info(` [ignored] target file found: table="%s", target="%s"`, table.Name, target) - return - } - - // Store - // model file. - if err = (&commands.Generator{ - Command: command, - Container: container, - Common: o.common, - Table: table, - Target: target, - }).Model(ctx); err == nil { - container.GetOutput().Info(` [succeed] target file saved: table="%s", target="%s"`, table.Name, target) - } - return -} diff --git a/db/commands/service/command.go b/db/commands/service/command.go deleted file mode 100644 index 7cfbc34..0000000 --- a/db/commands/service/command.go +++ /dev/null @@ -1,99 +0,0 @@ -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Author: wsfuyibing <682805@qq.com> -// Date: 2024-08-02 - -package service - -import ( - "gitee.com/go-libs/console" - "gitee.com/go-libs/db-xorm/db/commands" - "gitee.com/go-libs/db-xorm/db/commands2/gen_service" -) - -var New = gen_service.New - -// New2 -// creates a console command. -func New2() *console.Command { - // Creates - // a provider instance. - provider := &Provider{common: &commands.Common{}} - - // Creates - // a command for provider. - provider.command = console.NewCommand(Name). - SetDescription(Description) - - // Append options on command. - provider.command.Add( - // Working directory. - // - // go run main.go gen:service --base-dir=/data/sketch - console.NewOption(OptBaseDir). - SetShortName(OptBaseDirShort). - SetDescription(OptBaseDirDesc). - SetDefaultValue(OptBaseDirDefault), - - // Data source name. - // - // go run main.go gen:service --dsn="root:pass@tcp(127.0.0.1:3306)/test" - console.NewOption(OptDsn). - SetDescription(OptDsnDesc), - - // Which table will be exported. - // - // go run main.go gen:service --export="user" - console.NewOption(OptExport). - SetShortName(OptExportShort). - SetDescription(OptExportDesc). - SetRequired(true), - - // Model path. - // - // go run main.go gen:service --model-path=app/models - console.NewOption(OptModelPath). - SetShortName(OptModelPathShort). - SetDescription(OptModelPathDesc). - SetDefaultValue(OptModelPathDefault), - - // Override existing files. - // - // go run main.go gen:service --override - console.NewNullOption(OptOverride). - SetDescription(OptOverrideDesc), - - // Which table will be exported. - // - // go run main.go gen:service --prefix="cdb_" - console.NewOption(OptPrefix). - SetShortName(OptPrefixShort). - SetDescription(OptPrefixDesc), - - // Target path. - // - // go run main.go gen:service --target-path=app/services - console.NewOption(OptTargetPath). - SetShortName(OptTargetPathShort). - SetDescription(OptTargetPathDesc). - SetDefaultValue(OptTargetPathDefault), - ) - - // Bind - // provider to command. - provider.command.SetProvider(provider) - - // Returns - // a command of the provider. - return provider.command -} diff --git a/db/commands/service/provider.go b/db/commands/service/provider.go deleted file mode 100644 index 72eda42..0000000 --- a/db/commands/service/provider.go +++ /dev/null @@ -1,149 +0,0 @@ -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Author: wsfuyibing <682805@qq.com> -// Date: 2024-08-02 - -package service - -import ( - "context" - "fmt" - "gitee.com/go-libs/console" - "gitee.com/go-libs/db-xorm/db/commands" - "gitee.com/go-wares/log" -) - -const ( - Name = "gen:service" - Description = "Generate service files" - - OptBaseDir = "base-dir" - OptBaseDirDefault = "./" - OptBaseDirDesc = "Application working directory" - OptBaseDirShort = 'b' - - OptDsn = "dsn" - OptDsnDesc = "Database source name for connection, e.g. root:pass@tcp(127.0.0.1:3306)/test" - - OptExport = "export" - OptExportDesc = "Which tables will be exported" - OptExportShort = 'e' - - OptModelPath = "model-path" - OptModelPathDefault = "app/models" - OptModelPathDesc = "Generated model files location" - OptModelPathShort = 'm' - - OptOverride = "override" - OptOverrideDesc = "Override existing service files" - - OptPrefix = "prefix" - OptPrefixDesc = "Prefix name for table" - OptPrefixShort = 'p' - - OptTargetPath = "target-path" - OptTargetPathDefault = "app/services" - OptTargetPathDesc = "Generated service files saved to" - OptTargetPathShort = 't' -) - -// Provider -// is a component used to generate service files. -type Provider struct { - common *commands.Common - command *console.Command -} - -// Before -// is a before runner hook handler for command. -func (o *Provider) Before(_ context.Context, _ *console.Container, command *console.Command) (err error) { - log.Config().SetLevel("error") - - // Read and validate - // options value. - // - // --base-dir - // --dsn - for _, fn := range []func() error{ - func() error { return o.common.ReadBaseDir(command, OptBaseDir, OptBaseDirDefault) }, - func() error { return o.common.BuildModule(command) }, - func() error { return o.common.ReadDsn(command, OptDsn) }, - func() error { return o.common.ReadExport(command, OptExport) }, - func() error { return o.common.ReadModelPath(command, OptModelPath, OptModelPathDefault) }, - func() error { return o.common.ReadOverride(command, OptOverride) }, - func() error { return o.common.ReadPrefix(command, OptPrefix) }, - func() error { return o.common.ReadTargetPath(command, OptTargetPath, OptTargetPathDefault) }, - func() error { return o.common.RegisterDatabase() }, - } { - if err = fn(); err != nil { - break - } - } - return -} - -// Run -// is a runner hook handler for command. -func (o *Provider) Run(ctx context.Context, container *console.Container, command *console.Command) (err error) { - var tables []*commands.Table - - // Return error - // if tables list failed. - if tables, err = o.common.ListTable(ctx, command); err != nil { - return - } - - // Iterate - // tables and generate it. - for _, table := range tables { - if err = o.generate(ctx, container, command, table); err != nil { - break - } - } - return -} - -// generate table to target file. -func (o *Provider) generate(ctx context.Context, container *console.Container, command *console.Command, table *commands.Table) (err error) { - var ( - can bool - name = fmt.Sprintf(`%s_service.go`, table.Name.FileName(o.common.Prefix)) - target = commands.Target(fmt.Sprintf(`%s/%s/%s`, o.common.BaseDir, o.common.TargetPath, name)) - ) - - // Check - // target file can override or not. - if can, err = target.Can(o.common.Override); err != nil { - return - } - - // Ignore - // if target exists and override not enabled. - if !can { - container.GetOutput().Info(` [ignored] target file found: table="%s", target="%s"`, table.Name, target) - return - } - - // Store - // model file. - if err = (&commands.Generator{ - Command: command, - Container: container, - Common: o.common, - Table: table, - Target: target, - }).Service(ctx); err == nil { - container.GetOutput().Info(` [succeed] target file saved: table="%s", target="%s"`, table.Name, target) - } - return -} diff --git a/db/commands/table.go b/db/commands/table.go deleted file mode 100644 index 9f70f2c..0000000 --- a/db/commands/table.go +++ /dev/null @@ -1,28 +0,0 @@ -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Author: wsfuyibing <682805@qq.com> -// Date: 2024-08-02 - -package commands - -// Table -// is a component for table definition (DDL). -type Table struct { - Engine string `xorm:"Engine"` - Format string `xorm:"Row_format"` - Name ItemName `xorm:"Name"` - Comment ItemComment `xorm:"Comment"` - Collation ItemCollation `xorm:"Collation"` - - Columns []*Column `xorm:"-"` -} diff --git a/db/commands/target.go b/db/commands/target.go deleted file mode 100644 index cb7320d..0000000 --- a/db/commands/target.go +++ /dev/null @@ -1,117 +0,0 @@ -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Author: wsfuyibing <682805@qq.com> -// Date: 2024-08-07 - -package commands - -import ( - "context" - "errors" - "fmt" - "html/template" - "os" - "regexp" -) - -// Target -// is a type name for generated file path. -// -// Example: -// -// Target("/data/sketch/app/models/example.go") -// Target("/data/sketch/app/services/example_service.go") -type Target string - -// Can -// return true if target file can be saved. -func (o Target) Can(override bool) (bool, error) { - // Return true - // if override enabled. - if override { - return true, nil - } - - // Stat - // target file. - _, err := os.Stat(o.String()) - - // Return false - // if target file is existed. - if err == nil { - return false, nil - } - - // Return true - // if target file is not exists. - if errors.Is(err, os.ErrNotExist) { - return true, nil - } - - // Unknown - // error. - return false, err -} - -// Save -// template text to target file. -func (o Target) Save(_ context.Context, text string, result any) (err error) { - var ( - file *os.File - info os.FileInfo - target = o.String() - tpl *template.Template - ) - - // Make directory. - if path := regexp.MustCompile(`/([^/]+)$`).ReplaceAllString(target, ""); path != target { - if info, err = os.Stat(path); err != nil { - if errors.Is(err, os.ErrNotExist) { - err = nil - } else { - return - } - } else if !info.IsDir() { - err = fmt.Errorf(`invalid directory`) - return - } - } - - // Open - // a file, Create new file if not exists. - if file, err = os.OpenFile(target, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm); err != nil { - return - } - - // Close - // file resource when done. - defer func() { _ = file.Close() }() - - // Execute - // template variables with given data. - if tpl, err = template.New("template").Parse(text); err == nil { - err = tpl.Execute(file, result) - } - return -} - -// String -// returns a path string. -// -// Output: -// -// /data/sketch/app/models/example.go -// /data/sketch/app/services/example_service.go -func (o Target) String() string { - return string(o) -} diff --git a/db/commands/templates/model.tpl b/db/commands/templates/model.tpl deleted file mode 100644 index c986de6..0000000 --- a/db/commands/templates/model.tpl +++ /dev/null @@ -1,60 +0,0 @@ -// Do not edit this file. -// It's generated by console command at {{.Datetime}}. You can -// enter follow script on terminal like follow: -// -// cd /data/sketch -// {{.Script}} - -package {{.Package}} - -{{- if gt (len .Packages) 0}} - -import ( - {{- range .Packages}} - "{{.}}" - {{- end}} -) -{{- end}} - -// {{.StructName}} -// is a model for table. -{{- if .Table.Comment}} -// -// {{.Table.Comment}} -{{- end}} -// -// Collation : {{.Table.Collation}} -// Engine : {{.Table.Engine}} -// Format : {{.Table.Format}} -// Table : {{.Table.Name}} -type {{.StructName}} struct{ - // Field count : {{len .Table.Columns}} - - {{- range .Table.Columns}} - {{if .Comment}} - // {{.ExportName}} - // {{.Comment}}. - {{- else}} - // {{.ExportName}} - {{- end}} - // - {{- if .Collation}} - // Collation : {{.Collation}} - {{- end}} - {{- if .Default}} - // Default : {{.Default}} - {{- end}} - {{- if .Extra}} - // Extra : {{.Extra}} - {{- end}} - // Null : {{.Null}} - // Type : {{.Type}} - {{.ExportName}} {{.ExportType}} `xorm:"{{.ExportOrm}}" json:"{{.ExportJson}}"` - {{- end}} -} - -// TableName -// returns a table name. It's an optional function. -func (o *{{.StructName}}) TableName() string { - return "{{.Table.Name}}" -} diff --git a/db/commands/templates/service.tpl b/db/commands/templates/service.tpl deleted file mode 100644 index 7b798dc..0000000 --- a/db/commands/templates/service.tpl +++ /dev/null @@ -1,123 +0,0 @@ -// Do not edit this file. -// It's generated by console command at {{.Datetime}}. You can -// enter follow script on terminal like follow: -// -// cd /data/sketch -// {{.Script}} - -package {{.Package}} - -{{- if gt (len .Packages) 0}} - -import ( - {{- range .Packages}} - "{{.}}" - {{- end}} -) -{{- end}} - -// {{.StructName}} -// is a service used to operate data for model. -type {{.StructName}} struct{ - db.Service -} - -// New{{.StructName}} -// creates a model operate service. -// -// {{.Script}} -func New{{.StructName}}(sess ... *db.Session) *{{.StructName}}{ - o := &{{.StructName}}{} - o.With(sess...) - return o -} - -// Add -// adds a new record with given param. -func (o *{{.StructName}}) Add(ctx context.Context, req *{{.ModelPkg}}.{{.ModelName}}) (model *{{.ModelPkg}}.{{.ModelName}}, err error) { - var ( - affects int64 - sess *db.Session - ) - - // Open - // a connect session from master server. - if sess, err = o.Master(ctx); err != nil { - return - } - - // Prepare - // model fields for insert without primary key. Datetime use builtin - // methods. - model = &{{.ModelPkg}}.{{.ModelName}}{ - {{- range .Table.Columns}} - {{- if not .IsPrimaryKey}} - {{- if .IsDate}} - {{.ExportName}}: db.NewDate(), - {{- else if or .IsDatetime .IsDatetimeOnUpdate}} - {{.ExportName}}: db.NewDatetime(), - {{- else}} - {{.ExportName}}: req.{{.ExportName}}, - {{- end}} - {{- end}} - {{- end}} - } - - // Send data - // to master session and parse result. - if affects, err = sess.Insert(model); err != nil || affects == 0 { - model = nil - } - return -} -{{- if .PrimaryName}} - -// DelBy{{.PrimaryName}} -// method is generated by console command. It's deletes a record by primary key. -func (o *{{.StructName}}) DelBy{{.PrimaryName}}(ctx context.Context, val {{.PrimaryType}}) (affects int64, err error) { - var ( - sess *db.Session - model = &{{.ModelPkg}}.{{.ModelName}}{} - ) - - // Open - // a connect session from master server. - if sess, err = o.Master(ctx); err != nil { - return - } - - // Send data - // to master session and return affect count. - affects, err = sess.Where("`id` = ?", val).Delete(model) - return -} -{{- end}} -{{- if .PrimaryName}} - -// GetBy{{.PrimaryName}} -// method is generated by console command. It's return a model struct -// if exists otherwise nil returned. -func (o *{{.StructName}}) GetBy{{.PrimaryName}}(ctx context.Context, val {{.PrimaryType}}) (model *{{.ModelPkg}}.{{.ModelName}}, err error){ - var ( - has bool - sess *db.Session - ) - - // Open - // a connect session from slave server. - if sess, err = o.Slave(ctx); err != nil { - return - } - - // Prepare - // an empty result model. - model = &{{.ModelPkg}}.{{.ModelName}}{} - - // Send data - // to slave session and get one result. - if has, err = sess.Where("`{{.PrimaryFieldName}}` = ?", val).Get(model); err != nil || !has { - model = nil - } - return -} -{{- end}} diff --git a/db/commands/types.go b/db/commands/types.go deleted file mode 100644 index 5234085..0000000 --- a/db/commands/types.go +++ /dev/null @@ -1,360 +0,0 @@ -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Author: wsfuyibing <682805@qq.com> -// Date: 2024-08-02 - -package commands - -import ( - "fmt" - "gitee.com/go-libs/console" - "regexp" - "strings" -) - -var ( - RegexStartLetter = regexp.MustCompile(`^(\S)`) - RegexStartWithUnderline = regexp.MustCompile(`^_+`) - RegexMiddleWithUnderline = regexp.MustCompile(`_+(\S)`) - RegexMatchUpperLetter = regexp.MustCompile(`([A-Z])`) - RegexMatchManyUnderlines = regexp.MustCompile(`_+`) - - RegexMatchColumnExtraAutoIncrement = regexp.MustCompile(`auto_increment`) - RegexMatchColumnType = regexp.MustCompile(`^([_a-zA-Z0-9]+)`) -) - -var ( - convertPackage = map[string]string{ - "date": "gitee.com/go-libs/db-xorm/db", - "datetime": "gitee.com/go-libs/db-xorm/db", - } - - // Builtin - // type mapping for database. - // - // Translate database type to golang type. - convertTypes = map[string]string{ - "tinyint": "int", - "smallint": "int", - "mediumint": "int", - "int": "int", - "integer": "int", - - "bigint": "int64", - - "decimal": "float64", - "double": "float64", - "float": "float64", - - "date": "db.Date", - "datetime": "db.Datetime", - - "blob": "[]byte", - - "char": "string", - "varchar": "string", - "text": "string", - "longtext": "string", - "enum": "string", - } -) - -// +---------------------------------------------------------------------------+ -// | Type for default value of column | -// +---------------------------------------------------------------------------+ - -// ColumnDefault -// is a type for field name of a table. -type ColumnDefault string - -func (o ColumnDefault) String() string { - return strings.TrimSpace(strings.ToLower(string(o))) -} - -// +---------------------------------------------------------------------------+ -// | Type for table column extra | -// +---------------------------------------------------------------------------+ - -// ColumnExtra -// is a type for field name of a table. -type ColumnExtra string - -// Convert -// field name to exported orm name. -// -// .Convert("id") // return "id pk autoincr" -// .Convert("user_id") // return "user_id" -func (o ColumnExtra) Convert(name string) string { - if RegexMatchColumnExtraAutoIncrement.MatchString(o.String()) { - return fmt.Sprintf(`%s pk autoincr`, name) - } - return name -} - -func (o ColumnExtra) IsDatetimeOnUpdate() bool { - return o.String() == "on update current_timestamp" -} - -func (o ColumnExtra) String() string { - return strings.TrimSpace(strings.ToLower(string(o))) -} - -// +---------------------------------------------------------------------------+ -// | Type for key of a table | -// +---------------------------------------------------------------------------+ - -// ColumnKey -// is a type for field name of a table. -type ColumnKey string - -func (o ColumnKey) IsPrimary() bool { - return strings.ToUpper(o.String()) == "PRI" -} - -func (o ColumnKey) String() string { - return string(o) -} - -// +---------------------------------------------------------------------------+ -// | Type for table column nullable | -// +---------------------------------------------------------------------------+ - -// ColumnNull -// is a type for field name of a table. -type ColumnNull string - -// +---------------------------------------------------------------------------+ -// | Type for table column | -// +---------------------------------------------------------------------------+ - -// ColumnType -// is a type for field name of a table. -type ColumnType string - -func (o ColumnType) Convert(command *console.Command) (pkg, name string) { - var ( - k, s string - m []string - ok bool - ) - - // Unknown type. - if m = RegexMatchColumnType.FindStringSubmatch(o.String()); len(m) > 0 { - k = strings.ToLower(m[1]) - - // Use - // configuration of console.yaml. - if pkg, name, ok = NewMapping().Get(command.GetName(), k); ok { - return - } - - // Use builtin. - if name, ok = convertTypes[k]; ok { - if s, ok = convertPackage[k]; ok { - pkg = s - } - return - } - } - - // Any - // type. - name = "any" - return -} - -func (o ColumnType) IsDate() bool { - if m := RegexMatchColumnType.FindStringSubmatch(o.String()); len(m) > 0 { - return strings.ToLower(m[1]) == "date" - } - return false -} - -func (o ColumnType) IsDatetime() bool { - if m := RegexMatchColumnType.FindStringSubmatch(o.String()); len(m) > 0 { - s := strings.ToLower(m[1]) - return s == "datetime" || s == "timestamp" - } - return false -} - -func (o ColumnType) String() string { - return string(o) -} - -// +---------------------------------------------------------------------------+ -// | Collation for table and columns | -// +---------------------------------------------------------------------------+ - -// ItemCollation -// is a type for table and field name. -type ItemCollation string - -// +---------------------------------------------------------------------------+ -// | Comment for table and columns | -// +---------------------------------------------------------------------------+ - -// ItemComment -// is a type for table and field name. -type ItemComment string - -// String -// returns a comment string without new line. -func (o ItemComment) String() string { - return strings.ReplaceAll(string(o), "\n", "") -} - -// +---------------------------------------------------------------------------+ -// | Name for table and columns | -// +---------------------------------------------------------------------------+ - -// ItemName -// is a type for table and field name. -type ItemName string - -// Allow -// return true if start with an a-z letter. -// -// Output: -// return true // user -// return false // _user -func (o ItemName) Allow() bool { - return regexp.MustCompile(`^[a-zA-Z][_a-zA-Z0-9]*$`).MatchString(o.String()) -} - -// String -// returns the origin name with any formats. -// -// Output: -// return "user_info" -// return "UserInfo" -// return "userInfo" -func (o ItemName) String() string { - return string(o) -} - -// FileName -// convert to file name without extension name. -// -// Rule: -// - table name : `cdb_user_info` -// - prefix : `cdb_` -// - file name : `user_info` -// -// Output: -// return "user_info" -func (o ItemName) FileName(prefix string) (name string) { - // Use - // origin name as default. - name = o.String() - - // Remove - // prefix name. - // - // Convert `cdb_user_info` as `user_info` with a prefix `cdb_`. - if prefix != "" { - name = strings.TrimPrefix(name, prefix) - } - - // Convert - // upper-case letter as underline with a lower-case letter. - // - // Convert `UserInfo` as `_user_info` - name = RegexMatchUpperLetter.ReplaceAllStringFunc(name, func(s string) string { - return fmt.Sprintf(`_%s`, strings.ToLower(s)) - }) - - // Remove - // starts with underline. - // - // Convert `_user_info` as `user_info`. - name = RegexStartWithUnderline.ReplaceAllString(name, "") - name = RegexMatchManyUnderlines.ReplaceAllString(name, "_") - return -} - -// StructName -// convert to struct name that starts with an upper-case letter. -// -// Rule: -// - table name : `cdb_user_info` -// - prefix : `cdb_` -// - struct name : `UserInfo` -// -// Output: -// return "UserInfo" -func (o ItemName) StructName(prefix string) (name string) { - // Use - // origin name as default. - name = o.String() - - // Remove - // prefix name. - // - // Example : cdb_user - // Prefix : cdb_ - // Replaced : user - if prefix != "" { - name = strings.TrimPrefix(name, prefix) - } - - // Remove - // underline start of name. - name = RegexStartWithUnderline.ReplaceAllString(name, "") - - // Convert - // underline with any letter as upper-case letter. - - name = RegexMiddleWithUnderline.ReplaceAllStringFunc(name, func(s string) string { - if m := RegexMiddleWithUnderline.FindStringSubmatch(s); len(m) > 0 { - return strings.ToUpper(m[1]) - } - return s - }) - - // Convert - // first letter as upper-case letter. - name = RegexStartLetter.ReplaceAllStringFunc(name, func(s string) string { - return strings.ToUpper(s) - }) - return -} - -// ToCamel -// returns a small-camel format name. -// -// Output: -// return "userInfo" -func (o ItemName) ToCamel() string { - return RegexStartLetter.ReplaceAllStringFunc(o.StructName(""), func(s string) string { - return strings.ToLower(s) - }) -} - -// ToSame -// returns a name equal to struct name. -// -// Output: -// return "UserInfo" -func (o ItemName) ToSame() string { - return o.StructName("") -} - -// ToSnake -// returns a snake format name. -// -// Output: -// return "user_info" -func (o ItemName) ToSnake() string { - return o.FileName("") -} diff --git a/db/commands/gen/model_command.go b/db/commands1/model/command.go similarity index 79% rename from db/commands/gen/model_command.go rename to db/commands1/model/command.go index adb68c9..9ca6c8c 100644 --- a/db/commands/gen/model_command.go +++ b/db/commands1/model/command.go @@ -11,11 +11,12 @@ // limitations under the License. // // Author: wsfuyibing <682805@qq.com> -// Date: 2024-08-16 +// Date: 2024-08-02 -package gen +package model -type ModelCommand struct { - Fields map[string]*ModelConvert `yaml:"fields"` - Types map[string]*ModelConvert `yaml:"types"` -} +import ( + "gitee.com/go-libs/db-xorm/db/commands/gen_model" +) + +var New = gen_model.New diff --git a/db/commands/gen/model_convert.go b/db/commands1/service/command.go similarity index 75% rename from db/commands/gen/model_convert.go rename to db/commands1/service/command.go index d8ccb41..2274d14 100644 --- a/db/commands/gen/model_convert.go +++ b/db/commands1/service/command.go @@ -11,13 +11,12 @@ // limitations under the License. // // Author: wsfuyibing <682805@qq.com> -// Date: 2024-08-16 +// Date: 2024-08-02 -package gen +package service -// ModelConvert -// is a component used to define exported type and package. -type ModelConvert struct { - Pkg string `yaml:"pkg"` - Type string `yaml:"type"` -} +import ( + "gitee.com/go-libs/db-xorm/db/commands/gen_service" +) + +var New = gen_service.New diff --git a/db/commands2/common.go b/db/commands2/common.go deleted file mode 100644 index 0866c6b..0000000 --- a/db/commands2/common.go +++ /dev/null @@ -1,390 +0,0 @@ -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Author: wsfuyibing <682805@qq.com> -// Date: 2024-08-02 - -package commands2 - -import ( - "context" - _ "embed" - "fmt" - "gitee.com/go-libs/console" - "gitee.com/go-libs/db-xorm/db" - "gitee.com/go-libs/db-xorm/db/commands2/base" - "gitee.com/go-libs/db-xorm/db/commands2/conf" - "html/template" - "path/filepath" - "regexp" - "strings" - "time" -) - -const DsnKey = "_gen:commands_" - -var RegexMatchPkg = regexp.MustCompile(`([_a-zA-Z0-9]+)$`) - -type Common struct { - BaseDir string - Dsn string - Export, Prefix string - ModelPath, ModelPkg string - Override bool - TargetPath, TargetPkg string - ModuleName, ModuleFolder string -} - -// BuildModule -// build module name and working relative folder. -func (o *Common) BuildModule(command *console.Command) (err error) { - if o.ModuleName, o.ModuleFolder = command.GenerateModule(o.BaseDir); o.ModuleName == "" { - err = fmt.Errorf(`can not parse module name from go.mod`) - return - } - if o.ModuleFolder != "" { - o.ModuleFolder = fmt.Sprintf(`/%s`, strings.TrimPrefix(o.ModuleFolder, "/")) - } - return -} - -// BuildScript -// build command runner script. -func (o *Common) BuildScript(command *console.Command) string { - return fmt.Sprintf(`go run main.go %s`, command.ToScript()) -} - -// ListTable -// returns a list for tables in a database. -func (o *Common) ListTable(ctx context.Context, command *console.Command) (tables []*base.Table, err error) { - var ( - all bool - list []*base.Table - names = make(map[string]string) - named = make(map[string]bool) - session *db.Session - ) - - // Prepare - // export names. - if o.Export == "*" { - all = true - } else { - for _, s := range strings.Split(o.Export, ",") { - if s = strings.TrimSpace(s); s != "" { - names[fmt.Sprintf(`%s%s`, o.Prefix, s)] = s - } - } - } - - // Open - // a connect session with exporter key. - if session, err = db.Config.GetMaster(ctx, DsnKey); err != nil { - return - } - - // Prepare - // table list. - tables = make([]*base.Table, 0) - - // Select - // all tables in database and columns of the table. - if err = session.NoCascade().SQL("SHOW TABLE STATUS").Find(&list); err == nil { - // Iterate - // table in database. - for _, table := range list { - // Ignore - // not allowed table. - if !table.Name.Allow() { - continue - } - - // Ignore - // not matched on names. - if !all { - if _, ok := names[table.Name.String()]; !ok { - continue - } - } - - // Select - // columns from a table. - if err = session.NoCascade().SQL(fmt.Sprintf("SHOW FULL COLUMNS FROM `%s`", table.Name)).Find(&table.Columns); err != nil { - break - } - - // Format - // table fields. - o.FormatTable(command, table) - for _, column := range table.Columns { - o.FormatColumn(command, table, column) - - // Bind primary on table. - if column.IsPrimaryKey { - if convertor := conf.Model.Get(fmt.Sprintf(`%s.%s`, table.Name, column.Field), column.Type.Origin()); convertor != nil { - table.PrimaryName = column.Field.ToLargeCamel() - table.PrimaryFieldName = column.Field.String() - table.PrimaryType = convertor.Type - } else { - column.IsPrimaryKey = false - } - } - } - - // Append - // to list. - named[table.Name.String()] = true - tables = append(tables, table) - } - } - - // Exported - // name in command argument not found. - for k := range names { - if _, ok := named[k]; !ok { - err = fmt.Errorf(`table not found: %s`, k) - return - } - } - - // Empty result. - if len(tables) == 0 { - err = fmt.Errorf(`table not found in database`) - } - return -} - -// ReadBaseDir -// read absolute path of the application. -func (o *Common) ReadBaseDir(command *console.Command, key, value string) (err error) { - // Read - // from command options. - if opt, has := command.GetOption(key); has { - if s := opt.ToString(); s != "" { - value = s - } - } - - // Return error - // if base dir is blank. - if value == "" { - err = fmt.Errorf(`base dir can not be blank`) - return - } - - // Convert - // to absolute path. - o.BaseDir, err = filepath.Abs(value) - return -} - -// ReadDsn -// read database source name. -func (o *Common) ReadDsn(command *console.Command, key string) (err error) { - // Read dsn - // from command options. - if opt, has := command.GetOption(key); has { - if s := opt.ToString(); s != "" { - o.Dsn = s - return - } - } - - // Use default - // configuration of config files. - if cfg, ok := db.Config.Get(); ok && len(cfg.Dsn) > 0 { - o.Dsn = cfg.Dsn[0] - return - } - - // Error read. - err = fmt.Errorf(`dsn can not be blank`) - return -} - -// ReadExport -// read export names. -func (o *Common) ReadExport(command *console.Command, key string) (err error) { - if opt, has := command.GetOption(key); has { - if s := opt.ToString(); s != "" { - o.Export = s - } - } - return -} - -// ReadModelPath -// read path for model files location. -func (o *Common) ReadModelPath(command *console.Command, key, value string) (err error) { - // Read - // from command options. - if opt, has := command.GetOption(key); has { - if s := opt.ToString(); s != "" { - value = s - } - } - - // Return error - // if base dir is blank. - if value == "" { - err = fmt.Errorf(`model path can not be blank`) - return - } - - // Convert - // to absolute path. - o.ModelPath = value - - // Read package name for model. - if m := RegexMatchPkg.FindStringSubmatch(value); len(m) > 0 { - o.ModelPkg = m[1] - return - } - - // Error read. - err = fmt.Errorf(`can not parse package name for target`) - return -} - -// ReadOverride -// read override state for existing files. -func (o *Common) ReadOverride(command *console.Command, key string) (err error) { - if opt, has := command.GetOption(key); has { - o.Override = opt.GetSpecified() - } - return -} - -// ReadPrefix -// read prefix for table name. -func (o *Common) ReadPrefix(command *console.Command, key string) (err error) { - if opt, has := command.GetOption(key); has { - if s := opt.ToString(); s != "" { - o.Prefix = s - } - } - return -} - -// ReadTargetPath -// read path for generated files save to. -func (o *Common) ReadTargetPath(command *console.Command, key, value string) (err error) { - // Read - // from command options. - if opt, has := command.GetOption(key); has { - if s := opt.ToString(); s != "" { - value = s - } - } - - // Return error - // if base dir is blank. - if value == "" { - err = fmt.Errorf(`target path can not be blank`) - return - } - - // Convert - // to absolute path. - o.TargetPath = value - - // Read package for generated files save to. - if m := RegexMatchPkg.FindStringSubmatch(value); len(m) > 0 { - o.TargetPkg = m[1] - return - } - - // Error read. - err = fmt.Errorf(`can not parse package name for target`) - return -} - -// RegisterDatabase -// adds a database connect configuration. -func (o *Common) RegisterDatabase() error { - return db.Config.Add(DsnKey, &db.Database{ - Dsn: []string{o.Dsn}, - Mapper: "snake", - }) -} - -func (o *Common) FormatColumn(command *console.Command, table *base.Table, column *base.Column) { - // Bind relation of a table. - column.Table = table - - // Build comment list of a table. - if len(column.Comment.Strings()) > 0 { - column.CommentList = make([]template.HTML, 0) - for _, s := range column.Comment.Strings() { - if s = strings.TrimSpace(s); s != "" { - column.CommentList = append(column.CommentList, template.HTML(s)) - } - } - } - - // Parse info fields. - column.Datetime = template.HTML(time.Now().Format(time.RFC3339)) - column.Script = template.HTML(o.BuildScript(command)) - - // Parse name fields. - column.ExportName = column.Field.StructName(o.Prefix) - column.ExportJson = column.Field.ToSnake() - column.ExportOrm = column.Extra.Convert(column.Field) - - // Type convert. - if convert := conf.Model.Get(fmt.Sprintf(`%s.%s`, table.Name, column.Field), column.Type.Origin()); convert != nil { - column.ExportPkg = convert.Pkg - column.ExportType = convert.Type - - // Append package. - if column.ExportPkg != "" { - table.Add(column.ExportPkg) - } - } - - column.IsDate = column.Type.IsDate() - column.IsDatetime = column.Type.IsDatetime() - column.IsDatetimeOnUpdate = column.Extra.IsDatetimeOnUpdate() - column.IsPrimaryKey = column.Key.IsPrimary() -} - -func (o *Common) FormatTable(command *console.Command, table *base.Table) { - // Build comment list of a table. - if len(table.Comment.Strings()) > 0 { - table.CommentList = make([]template.HTML, 0) - for _, s := range table.Comment.Strings() { - if s = strings.TrimSpace(s); s != "" { - table.CommentList = append(table.CommentList, template.HTML(s)) - } - } - } - - // Parse info fields. - table.Datetime = template.HTML(time.Now().Format(time.RFC3339)) - table.Script = template.HTML(o.BuildScript(command)) -} - -func (o *Common) FormatTableAsModel(command *console.Command, table *base.Table) { - table.ModelName = table.Name.StructName(o.Prefix) - table.ModelPkg = o.TargetPkg -} - -func (o *Common) FormatTableAsService(command *console.Command, table *base.Table) { - table.ModelName = table.Name.StructName(o.Prefix) - table.ServiceName = fmt.Sprintf(`%sService`, table.ModelName) - - table.ModelPkg = o.ModelPkg - table.ServicePkg = o.TargetPkg - - table.Add(`context`) - table.Add(`gitee.com/go-libs/db-xorm/db`) -} -- Gitee From f9e00515a8306f39006ef45e2047192fcbe899ef Mon Sep 17 00:00:00 2001 From: wsfuyibing Date: Mon, 19 Aug 2024 14:29:19 +0800 Subject: [PATCH 09/11] new version --- _examples/simple/main.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/_examples/simple/main.go b/_examples/simple/main.go index b1d2ae2..dbb3308 100644 --- a/_examples/simple/main.go +++ b/_examples/simple/main.go @@ -17,8 +17,8 @@ package main import ( "gitee.com/go-libs/console" - "gitee.com/go-libs/db-xorm/db/commands/model" - "gitee.com/go-libs/db-xorm/db/commands/service" + "gitee.com/go-libs/db-xorm/db/commands/gen_model" + "gitee.com/go-libs/db-xorm/db/commands/gen_service" "gitee.com/go-wares/log" ) @@ -26,7 +26,6 @@ func main() { defer log.Close() c := console.NewContainer() - c.Add(model.New(), service.New()) - // c.Add(db.NewGenModelCommand()) + c.Add(gen_model.New(), gen_service.New()) c.Run() } -- Gitee From 951cd8dbe1ec86b5ca7e0cd3d320584e89d91369 Mon Sep 17 00:00:00 2001 From: wsfuyibing Date: Mon, 19 Aug 2024 14:33:53 +0800 Subject: [PATCH 10/11] new version --- db/commands/base/table_type.go | 5 ----- db/commands/base/target.go | 4 ++-- db/commands1/model/command.go | 22 ---------------------- db/commands1/service/command.go | 22 ---------------------- 4 files changed, 2 insertions(+), 51 deletions(-) delete mode 100644 db/commands1/model/command.go delete mode 100644 db/commands1/service/command.go diff --git a/db/commands/base/table_type.go b/db/commands/base/table_type.go index 0e22e85..a391c5e 100644 --- a/db/commands/base/table_type.go +++ b/db/commands/base/table_type.go @@ -17,7 +17,6 @@ package base import ( "fmt" - "gitee.com/go-libs/console" "regexp" "strings" ) @@ -101,10 +100,6 @@ type ColumnNull string // is a type for field name of a table. type ColumnType string -func (o ColumnType) Convert(command *console.Command) (pkg, name string) { - return -} - func (o ColumnType) IsDate() bool { if m := RegexMatchColumnType.FindStringSubmatch(o.String()); len(m) > 0 { return strings.ToLower(m[1]) == "date" diff --git a/db/commands/base/target.go b/db/commands/base/target.go index 49c2467..52dbfca 100644 --- a/db/commands/base/target.go +++ b/db/commands/base/target.go @@ -77,7 +77,7 @@ func (o Target) Save(_ context.Context, text string, result any) (err error) { if path := regexp.MustCompile(`/([^/]+)$`).ReplaceAllString(target, ""); path != target { if info, err = os.Stat(path); err != nil { if errors.Is(err, os.ErrNotExist) { - err = nil + err = os.MkdirAll(path, os.ModePerm) } else { return } @@ -89,7 +89,7 @@ func (o Target) Save(_ context.Context, text string, result any) (err error) { // Open // a file, Create new file if not exists. - if file, err = os.OpenFile(target, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm); err != nil { + if file, err = os.OpenFile(target, os.O_CREATE|os.O_RDWR|os.O_TRUNC, os.ModePerm); err != nil { return } diff --git a/db/commands1/model/command.go b/db/commands1/model/command.go deleted file mode 100644 index 9ca6c8c..0000000 --- a/db/commands1/model/command.go +++ /dev/null @@ -1,22 +0,0 @@ -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Author: wsfuyibing <682805@qq.com> -// Date: 2024-08-02 - -package model - -import ( - "gitee.com/go-libs/db-xorm/db/commands/gen_model" -) - -var New = gen_model.New diff --git a/db/commands1/service/command.go b/db/commands1/service/command.go deleted file mode 100644 index 2274d14..0000000 --- a/db/commands1/service/command.go +++ /dev/null @@ -1,22 +0,0 @@ -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Author: wsfuyibing <682805@qq.com> -// Date: 2024-08-02 - -package service - -import ( - "gitee.com/go-libs/db-xorm/db/commands/gen_service" -) - -var New = gen_service.New -- Gitee From cf0b5f27b87d274b03bef60b84442204b3df7d0d Mon Sep 17 00:00:00 2001 From: wsfuyibing Date: Mon, 19 Aug 2024 17:30:28 +0800 Subject: [PATCH 11/11] new version --- _examples/config/console.yaml | 4 - _examples/simple/app/models/registry.go | 86 -------------- .../simple/app/services/registry_service.go | 111 ------------------ _examples/simple/config/console.yaml | 15 +++ _examples/{ => simple}/config/db.yaml | 5 +- _examples/{ => simple}/config/log.yaml | 0 _examples/tem.sh | 12 -- 7 files changed, 16 insertions(+), 217 deletions(-) delete mode 100644 _examples/config/console.yaml delete mode 100755 _examples/simple/app/models/registry.go delete mode 100755 _examples/simple/app/services/registry_service.go create mode 100644 _examples/simple/config/console.yaml rename _examples/{ => simple}/config/db.yaml (61%) rename _examples/{ => simple}/config/log.yaml (100%) delete mode 100644 _examples/tem.sh diff --git a/_examples/config/console.yaml b/_examples/config/console.yaml deleted file mode 100644 index 7b1c14f..0000000 --- a/_examples/config/console.yaml +++ /dev/null @@ -1,4 +0,0 @@ -commands: - gen:model: - options: - base-dir: "./" diff --git a/_examples/simple/app/models/registry.go b/_examples/simple/app/models/registry.go deleted file mode 100755 index 85e6306..0000000 --- a/_examples/simple/app/models/registry.go +++ /dev/null @@ -1,86 +0,0 @@ -// Do not edit this file. -// It's generated by console command at 2024-08-09T17:02:32+08:00. You can -// enter follow script on terminal like follow: -// -// cd /data/sketch -// gen:model --override --base-dir="./" --export="registry" - -package models - -import ( - "gitee.com/go-libs/db-xorm/db" -) - -// Registry -// is a model for table. -// -// Collation : utf8_general_ci -// Engine : InnoDB -// Format : Dynamic -// Table : registry -type Registry struct { - // Field count : 7 - - // Id - // PK. - // - // Extra : auto_increment - // Null : NO - // Type : int(10) unsigned - Id int `xorm:"id pk autoincr" json:"id"` - - // Status - // 状态位(0:停用,1:启用). - // - // Default : 0 - // Null : NO - // Type : tinyint(3) unsigned - Status int `xorm:"status" json:"status"` - - // TopicId - // 主题ID. - // - // Default : 0 - // Null : NO - // Type : int(10) unsigned - TopicId int `xorm:"topic_id" json:"topic_id"` - - // TopicTag - // 标签名. - // - // Collation : utf8_general_ci - // Null : NO - // Type : varchar(64) - TopicTag string `xorm:"topic_tag" json:"topic_tag"` - - // Title - // 标题. - // - // Collation : utf8_general_ci - // Null : YES - // Type : varchar(80) - Title string `xorm:"title" json:"title"` - - // CreatedAt - // 创建时间. - // - // Default : current_timestamp - // Null : NO - // Type : datetime - CreatedAt db.Datetime `xorm:"created_at" json:"created_at"` - - // UpdatedAt - // 最后更新时间. - // - // Default : current_timestamp - // Extra : on update current_timestamp - // Null : NO - // Type : datetime - UpdatedAt db.Datetime `xorm:"updated_at" json:"updated_at"` -} - -// TableName -// returns a table name. It's an optional function. -func (o *Registry) TableName() string { - return "registry" -} diff --git a/_examples/simple/app/services/registry_service.go b/_examples/simple/app/services/registry_service.go deleted file mode 100755 index 446ea3b..0000000 --- a/_examples/simple/app/services/registry_service.go +++ /dev/null @@ -1,111 +0,0 @@ -// Do not edit this file. -// It's generated by console command at 2024-08-09T17:02:33+08:00. You can -// enter follow script on terminal like follow: -// -// cd /data/sketch -// gen:service --override --export="registry" - -package services - -import ( - "context" - "gitee.com/go-libs/db-xorm/_examples/simple/app/models" - "gitee.com/go-libs/db-xorm/db" -) - -// RegistryService -// is a service used to operate data for model. -type RegistryService struct{ - db.Service -} - -// NewRegistryService -// creates a model operate service. -// -// gen:service --override --export="registry" -func NewRegistryService(sess ... *db.Session) *RegistryService{ - o := &RegistryService{} - o.With(sess...) - return o -} - -// Add -// adds a new record with given param. -func (o *RegistryService) Add(ctx context.Context, req *models.Registry) (model *models.Registry, err error) { - var ( - affects int64 - sess *db.Session - ) - - // Open - // a connect session from master server. - if sess, err = o.Master(ctx); err != nil { - return - } - - // Prepare - // model fields for insert without primary key. Datetime use builtin - // methods. - model = &models.Registry{ - Status: req.Status, - TopicId: req.TopicId, - TopicTag: req.TopicTag, - Title: req.Title, - CreatedAt: db.NewDatetime(), - UpdatedAt: db.NewDatetime(), - } - - // Send data - // to master session and parse result. - if affects, err = sess.Insert(model); err != nil || affects == 0 { - model = nil - } - return -} - -// DelById -// method is generated by console command. It's deletes a record by primary key. -func (o *RegistryService) DelById(ctx context.Context, val int) (affects int64, err error) { - var ( - sess *db.Session - model = &models.Registry{} - ) - - // Open - // a connect session from master server. - if sess, err = o.Master(ctx); err != nil { - return - } - - // Send data - // to master session and return affect count. - affects, err = sess.Where("`id` = ?", val).Delete(model) - return -} - -// GetById -// method is generated by console command. It's return a model struct -// if exists otherwise nil returned. -func (o *RegistryService) GetById(ctx context.Context, val int) (model *models.Registry, err error){ - var ( - has bool - sess *db.Session - ) - - // Open - // a connect session from slave server. - if sess, err = o.Slave(ctx); err != nil { - return - } - - // Prepare - // an empty result model. - model = &models.Registry{} - - // Send data - // to slave session and get one result. - if has, err = sess.Where("`id` = ?", val).Get(model); err != nil || !has { - model = nil - } - return -} diff --git a/_examples/simple/config/console.yaml b/_examples/simple/config/console.yaml new file mode 100644 index 0000000..9954852 --- /dev/null +++ b/_examples/simple/config/console.yaml @@ -0,0 +1,15 @@ +commands: + gen:model: + options: + base-dir: "./" + target-path: app/models + fields: + example.status: + pkg: sketch/app + type: app.Status + types: + gen:service: + options: + base-dir: "./" + model-path: app/models + target-path: app/services diff --git a/_examples/config/db.yaml b/_examples/simple/config/db.yaml similarity index 61% rename from _examples/config/db.yaml rename to _examples/simple/config/db.yaml index f44dbb4..a022ee3 100644 --- a/_examples/config/db.yaml +++ b/_examples/simple/config/db.yaml @@ -1,8 +1,5 @@ # Database configurations databases: db: - enable-logger: true - enable-session: true - driver: mysql dsn: - - root:PassWord@123#MySQL@tcp(127.0.0.1:3306)/test?charset=utf8 \ No newline at end of file + - root:PassWord@123#MySQL@tcp(127.0.0.1:3306)/test?charset=utf8 diff --git a/_examples/config/log.yaml b/_examples/simple/config/log.yaml similarity index 100% rename from _examples/config/log.yaml rename to _examples/simple/config/log.yaml diff --git a/_examples/tem.sh b/_examples/tem.sh deleted file mode 100644 index b8c74ff..0000000 --- a/_examples/tem.sh +++ /dev/null @@ -1,12 +0,0 @@ -echo 'deb https://mirrors.aliyun.com/debian/ bullseye main non-free contrib' > /etc/apt/sources.list -echo 'deb-src https://mirrors.aliyun.com/debian/ bullseye main non-free contrib' >> /etc/apt/sources.list -echo 'deb https://mirrors.aliyun.com/debian-security/ bullseye-security main' >> /etc/apt/sources.list -echo 'deb-src https://mirrors.aliyun.com/debian-security/ bullseye-security main' >> /etc/apt/sources.list -echo 'deb https://mirrors.aliyun.com/debian/ bullseye-updates main non-free contrib' >> /etc/apt/sources.list -echo 'deb-src https://mirrors.aliyun.com/debian/ bullseye-updates main non-free contrib' >> /etc/apt/sources.list -echo 'deb https://mirrors.aliyun.com/debian/ bullseye-backports main non-free contrib' >> /etc/apt/sources.list -echo 'deb-src https://mirrors.aliyun.com/debian/ bullseye-backports main non-free contrib' >> /etc/apt/sources.list - - - -apt install vim \ No newline at end of file -- Gitee