Add model generator based on AST
All checks were successful
CI / build-docker (push) Successful in 13s
CI / build-docker-bootstrap (push) Has been skipped
CI / release-test (push) Successful in 40s

This commit is contained in:
2025-11-09 16:34:46 -08:00
parent 2146e1de77
commit 208c1eb26c
8 changed files with 634 additions and 3 deletions

View File

@@ -21,10 +21,9 @@ func main() {
}
root_cmd.AddCommand(sqlite_lint)
root_cmd.AddCommand(cmd_init)
root_cmd.AddCommand(generate_model)
if err := root_cmd.Execute(); err != nil {
fmt.Println(RED + err.Error() + RESET)
os.Exit(1)
}
}
// Subcommand "generate_models"

View File

@@ -0,0 +1,81 @@
package main
import (
"errors"
"fmt"
"go/ast"
"go/printer"
"go/token"
"os"
"github.com/spf13/cobra"
"git.offline-twitter.com/offline-labs/gas-stack/pkg/codegen/modelgenerate"
. "git.offline-twitter.com/offline-labs/gas-stack/pkg/flowutils"
"git.offline-twitter.com/offline-labs/gas-stack/pkg/schema"
)
var ErrNoSuchTable = errors.New("no such table")
var generate_model = &cobra.Command{
Use: "generate <model_name>",
Short: "Generate a model type",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
path := Must(cmd.Flags().GetString("schema"))
modname := Must(cmd.Flags().GetString("modname"))
schema_sql, err := os.ReadFile(path)
if err != nil {
return fmt.Errorf("reading path %s: %w", path, err)
}
db := schema.InitDB(string(schema_sql))
tables := schema.SchemaFromDB(db).Tables
table, isOk := tables[args[0]]
if !isOk {
return ErrNoSuchTable
}
fset := token.NewFileSet()
if Must(cmd.Flags().GetBool("test")) {
file2 := modelgenerate.GenerateModelTestAST(table, modname)
PanicIf(printer.Fprint(os.Stdout, fset, file2))
} else {
file := &ast.File{
Name: ast.NewIdent("db"), // TODO: parameterize
Decls: []ast.Decl{
&ast.GenDecl{
Tok: token.IMPORT,
Specs: []ast.Spec{
&ast.ImportSpec{Path: &ast.BasicLit{Kind: token.STRING, Value: `"database/sql"`}},
&ast.ImportSpec{Path: &ast.BasicLit{Kind: token.STRING, Value: `"errors"`}},
&ast.ImportSpec{Path: &ast.BasicLit{Kind: token.STRING, Value: `"fmt"`}},
&ast.ImportSpec{
Name: ast.NewIdent("."),
Path: &ast.BasicLit{Kind: token.STRING, Value: `"git.offline-twitter.com/offline-labs/gas-stack/pkg/db"`},
},
},
},
modelgenerate.GenerateIDType(table),
modelgenerate.GenerateModelAST(table),
modelgenerate.GenerateSaveItemFunc(table),
modelgenerate.GenerateGetItemByIDFunc(table),
modelgenerate.GenerateDeleteItemFunc(table),
},
}
PanicIf(printer.Fprint(os.Stdout, fset, file))
}
return nil
},
}
func init() {
generate_model.Flags().String("schema", "pkg/db/schema.sql", "Path to SQL schema file")
generate_model.Flags().String("modname", "mymodule", "Name of project's Go module (TODO: detect automatically)")
generate_model.Flags().Bool("test", false, "Generate test file instead of regular file")
}