package serv import ( "context" "encoding/csv" "encoding/json" "fmt" "io" "io/ioutil" "math/rand" "os" "path" "strconv" "strings" "github.com/brianvoe/gofakeit/v5" "github.com/dop251/goja" "github.com/dosco/super-graph/core" "github.com/gosimple/slug" "github.com/jackc/pgx/v4" "github.com/jackc/pgx/v4/stdlib" "github.com/spf13/cobra" ) func cmdDBSeed(cmd *cobra.Command, args []string) { var err error if conf, err = initConf(); err != nil { log.Fatalf("ERR failed to read config: %s", err) } conf.Production = false conf.DefaultBlock = false db, err = initDB(conf, true, false) if err != nil { log.Fatalf("ERR failed to connect to database: %s", err) } sfile := path.Join(conf.cpath, conf.SeedFile) b, err := ioutil.ReadFile(sfile) if err != nil { log.Fatalf("ERR failed to read seed file %s: %s", sfile, err) } sg, err = core.NewSuperGraph(&conf.Core, db) if err != nil { log.Fatalf("ERR failed to initialize Super Graph: %s", err) } graphQLFn := func(query string, data interface{}, opt map[string]string) map[string]interface{} { return graphQLFunc(sg, query, data, opt) } vm := goja.New() vm.Set("graphql", graphQLFn) vm.Set("import_csv", importCSV) console := vm.NewObject() console.Set("log", logFunc) //nolint: errcheck vm.Set("console", console) fake := vm.NewObject() setFakeFuncs(fake) vm.Set("fake", fake) util := vm.NewObject() setUtilFuncs(util) vm.Set("util", util) _, err = vm.RunScript("seed.js", string(b)) if err != nil { log.Fatalf("ERR failed to execute script: %s", err) } log.Println("INF seed script done") } // func runFunc(call goja.FunctionCall) { func graphQLFunc(sg *core.SuperGraph, query string, data interface{}, opt map[string]string) map[string]interface{} { ct := context.Background() if v, ok := opt["user_id"]; ok && v != "" { ct = context.WithValue(ct, core.UserIDKey, v) } // var role string // if v, ok := opt["role"]; ok && len(v) != 0 { // role = v // } else { // role = "user" // } var vars []byte var err error if vars, err = json.Marshal(data); err != nil { log.Fatalf("ERR %s", err) } res, err := sg.GraphQL(ct, query, vars) if err != nil { log.Fatalf("ERR %s", err) } val := make(map[string]interface{}) if err = json.Unmarshal(res.Data, &val); err != nil { log.Fatalf("ERR %s", err) } return val } type csvSource struct { rows [][]string i int } func NewCSVSource(filename string) (*csvSource, error) { f, err := os.Open(filename) if err != nil { return nil, err } defer f.Close() r := csv.NewReader(f) rows, err := r.ReadAll() if err != nil { return nil, err } return &csvSource{rows: rows}, nil } func (c *csvSource) Next() bool { return c.i < len(c.rows) } func (c *csvSource) Values() ([]interface{}, error) { var vals []interface{} var err error for _, v := range c.rows[c.i] { switch { case v == "": vals = append(vals, "") case isDigit(v): var n int if n, err = strconv.Atoi(v); err == nil { vals = append(vals, n) } case strings.EqualFold(v, "true") || strings.EqualFold(v, "false"): var b bool if b, err = strconv.ParseBool(v); err == nil { vals = append(vals, b) } default: vals = append(vals, v) } if err != nil { return nil, fmt.Errorf("%w (line no %d)", err, c.i) } } c.i++ return vals, nil } func isDigit(v string) bool { for i := range v { if v[i] < '0' || v[i] > '9' { return false } } return true } func (c *csvSource) Err() error { return nil } func importCSV(table, filename string) int64 { if filename[0] != '/' { filename = path.Join(confPath, filename) } s, err := NewCSVSource(filename) if err != nil { log.Fatalf("ERR %v", err) } var cols []string colval, _ := s.Values() for _, c := range colval { cols = append(cols, c.(string)) } conn, err := stdlib.AcquireConn(db) if err != nil { log.Fatalf("ERR %v", err) } //nolint: errcheck defer stdlib.ReleaseConn(db, conn) n, err := conn.CopyFrom( context.Background(), pgx.Identifier{table}, cols, s) if err != nil { log.Fatalf("ERR %v", fmt.Errorf("%w (line no %d)", err, s.i)) } return n } //nolint: errcheck func logFunc(args ...interface{}) { for _, arg := range args { if _, ok := arg.(map[string]interface{}); ok { j, err := json.MarshalIndent(arg, "", " ") if err != nil { continue } os.Stdout.Write(j) } else { io.WriteString(os.Stdout, fmt.Sprintf("%v", arg)) } io.WriteString(os.Stdout, "\n") } } func avatarURL(size int) string { if size == 0 { size = 200 } return fmt.Sprintf("https://i.pravatar.cc/%d?%d", size, rand.Intn(5000)) } func imageURL(width, height int) string { return fmt.Sprintf("https://picsum.photos/%d/%d?%d", width, height, rand.Intn(5000)) } func getRandValue(values []string) string { return values[rand.Intn(len(values))] } //nolint: errcheck func setFakeFuncs(f *goja.Object) { gofakeit.Seed(0) // Person f.Set("person", gofakeit.Person) f.Set("name", gofakeit.Name) f.Set("name_prefix", gofakeit.NamePrefix) f.Set("name_suffix", gofakeit.NameSuffix) f.Set("first_name", gofakeit.FirstName) f.Set("last_name", gofakeit.LastName) f.Set("gender", gofakeit.Gender) f.Set("ssn", gofakeit.SSN) f.Set("contact", gofakeit.Contact) f.Set("email", gofakeit.Email) f.Set("phone", gofakeit.Phone) f.Set("phone_formatted", gofakeit.PhoneFormatted) f.Set("username", gofakeit.Username) f.Set("password", gofakeit.Password) // Address f.Set("address", gofakeit.Address) f.Set("city", gofakeit.City) f.Set("country", gofakeit.Country) f.Set("country_abr", gofakeit.CountryAbr) f.Set("state", gofakeit.State) f.Set("state_abr", gofakeit.StateAbr) f.Set("street", gofakeit.Street) f.Set("street_name", gofakeit.StreetName) f.Set("street_number", gofakeit.StreetNumber) f.Set("street_prefix", gofakeit.StreetPrefix) f.Set("street_suffix", gofakeit.StreetSuffix) f.Set("zip", gofakeit.Zip) f.Set("latitude", gofakeit.Latitude) f.Set("latitude_in_range", gofakeit.LatitudeInRange) f.Set("longitude", gofakeit.Longitude) f.Set("longitude_in_range", gofakeit.LongitudeInRange) // Beer f.Set("beer_alcohol", gofakeit.BeerAlcohol) f.Set("beer_hop", gofakeit.BeerHop) f.Set("beer_ibu", gofakeit.BeerIbu) f.Set("beer_blg", gofakeit.BeerBlg) f.Set("beer_malt", gofakeit.BeerMalt) f.Set("beer_name", gofakeit.BeerName) f.Set("beer_style", gofakeit.BeerStyle) f.Set("beer_yeast", gofakeit.BeerYeast) // Cars f.Set("car", gofakeit.Car) f.Set("car_type", gofakeit.CarType) f.Set("car_maker", gofakeit.CarMaker) f.Set("car_model", gofakeit.CarModel) // Text f.Set("word", gofakeit.Word) f.Set("sentence", gofakeit.Sentence) f.Set("paragraph", gofakeit.Paragraph) f.Set("question", gofakeit.Question) f.Set("quote", gofakeit.Quote) // Misc f.Set("generate", gofakeit.Generate) f.Set("boolean", gofakeit.Bool) f.Set("uuid", gofakeit.UUID) // Colors f.Set("color", gofakeit.Color) f.Set("hex_color", gofakeit.HexColor) f.Set("rgb_color", gofakeit.RGBColor) f.Set("safe_color", gofakeit.SafeColor) // Internet f.Set("url", gofakeit.URL) f.Set("image_url", imageURL) f.Set("avatar_url", avatarURL) f.Set("domain_name", gofakeit.DomainName) f.Set("domain_suffix", gofakeit.DomainSuffix) f.Set("ipv4_address", gofakeit.IPv4Address) f.Set("ipv6_address", gofakeit.IPv6Address) f.Set("http_method", gofakeit.HTTPMethod) f.Set("user_agent", gofakeit.UserAgent) f.Set("user_agent_firefox", gofakeit.FirefoxUserAgent) f.Set("user_agent_chrome", gofakeit.ChromeUserAgent) f.Set("user_agent_opera", gofakeit.OperaUserAgent) f.Set("user_agent_safari", gofakeit.SafariUserAgent) // Date / Time f.Set("date", gofakeit.Date) f.Set("date_range", gofakeit.DateRange) f.Set("nano_second", gofakeit.NanoSecond) f.Set("second", gofakeit.Second) f.Set("minute", gofakeit.Minute) f.Set("hour", gofakeit.Hour) f.Set("month", gofakeit.Month) f.Set("day", gofakeit.Day) f.Set("weekday", gofakeit.WeekDay) f.Set("year", gofakeit.Year) f.Set("timezone", gofakeit.TimeZone) f.Set("timezone_abv", gofakeit.TimeZoneAbv) f.Set("timezone_full", gofakeit.TimeZoneFull) f.Set("timezone_offset", gofakeit.TimeZoneOffset) // Payment f.Set("price", gofakeit.Price) f.Set("credit_card", gofakeit.CreditCard) f.Set("credit_card_cvv", gofakeit.CreditCardCvv) f.Set("credit_card_number", gofakeit.CreditCardNumber) f.Set("credit_card_type", gofakeit.CreditCardType) f.Set("currency", gofakeit.Currency) f.Set("currency_long", gofakeit.CurrencyLong) f.Set("currency_short", gofakeit.CurrencyShort) // Company f.Set("bs", gofakeit.BS) f.Set("buzzword", gofakeit.BuzzWord) f.Set("company", gofakeit.Company) f.Set("company_suffix", gofakeit.CompanySuffix) f.Set("job", gofakeit.Job) f.Set("job_description", gofakeit.JobDescriptor) f.Set("job_level", gofakeit.JobLevel) f.Set("job_title", gofakeit.JobTitle) // Hacker f.Set("hacker_abbreviation", gofakeit.HackerAbbreviation) f.Set("hacker_adjective", gofakeit.HackerAdjective) f.Set("hacker_noun", gofakeit.HackerNoun) f.Set("hacker_phrase", gofakeit.HackerPhrase) f.Set("hacker_verb", gofakeit.HackerVerb) //Hipster f.Set("hipster_word", gofakeit.HipsterWord) f.Set("hipster_paragraph", gofakeit.HipsterParagraph) f.Set("hipster_sentence", gofakeit.HipsterSentence) // File f.Set("file_extension", gofakeit.FileExtension) f.Set("file_mine_type", gofakeit.FileMimeType) // Numbers f.Set("number", gofakeit.Number) f.Set("numerify", gofakeit.Numerify) f.Set("int8", gofakeit.Int8) f.Set("int16", gofakeit.Int16) f.Set("int32", gofakeit.Int32) f.Set("int64", gofakeit.Int64) f.Set("uint8", gofakeit.Uint8) f.Set("uint16", gofakeit.Uint16) f.Set("uint32", gofakeit.Uint32) f.Set("uint64", gofakeit.Uint64) f.Set("float32", gofakeit.Float32) f.Set("float32_range", gofakeit.Float32Range) f.Set("float64", gofakeit.Float64) f.Set("float64_range", gofakeit.Float64Range) f.Set("shuffle_ints", gofakeit.ShuffleInts) f.Set("mac_address", gofakeit.MacAddress) // String f.Set("digit", gofakeit.Digit) f.Set("letter", gofakeit.Letter) f.Set("lexify", gofakeit.Lexify) f.Set("rand_string", getRandValue) f.Set("numerify", gofakeit.Numerify) } //nolint: errcheck func setUtilFuncs(f *goja.Object) { // Slugs f.Set("make_slug", slug.Make) f.Set("make_slug_lang", slug.MakeLang) f.Set("shuffle_strings", gofakeit.ShuffleStrings) }