Add database seeding capability

This commit is contained in:
Vikram Rangnekar
2019-09-20 00:19:11 -04:00
parent 1a949859e9
commit 18ce030056
16 changed files with 819 additions and 213 deletions

View File

@ -27,12 +27,14 @@ type allowList struct {
list map[string]*allowItem
filepath string
saveChan chan *allowItem
active bool
}
func initAllowList(path string) {
_allowList = allowList{
list: make(map[string]*allowItem),
saveChan: make(chan *allowItem),
active: true,
}
if len(path) != 0 {
@ -79,7 +81,7 @@ func initAllowList(path string) {
}
func (al *allowList) add(req *gqlReq) {
if len(req.ref) == 0 || len(req.Query) == 0 {
if al.active == false || len(req.ref) == 0 || len(req.Query) == 0 {
return
}
@ -91,6 +93,10 @@ func (al *allowList) add(req *gqlReq) {
}
func (al *allowList) load() {
if al.active == false {
return
}
b, err := ioutil.ReadFile(al.filepath)
if err != nil {
log.Fatal(err)
@ -168,6 +174,9 @@ func (al *allowList) load() {
}
func (al *allowList) save(item *allowItem) {
if al.active == false {
return
}
al.list[gqlHash(item.gql, item.vars)] = item
f, err := os.Create(al.filepath)

204
serv/cmd.go Normal file
View File

@ -0,0 +1,204 @@
package serv
import (
"errors"
"flag"
"fmt"
"os"
"strings"
"github.com/dosco/super-graph/psql"
"github.com/dosco/super-graph/qcode"
"github.com/go-pg/pg"
"github.com/gobuffalo/flect"
"github.com/rs/zerolog"
"github.com/spf13/viper"
)
//go:generate esc -o static.go -ignore \\.DS_Store -prefix ../web/build -private -pkg serv ../web/build
const (
serverName = "Super Graph"
authFailBlockAlways = iota + 1
authFailBlockPerQuery
authFailBlockNever
)
var (
logger *zerolog.Logger
conf *config
db *pg.DB
qcompile *qcode.Compiler
pcompile *psql.Compiler
authFailBlock int
)
func initLog() *zerolog.Logger {
logger := zerolog.New(zerolog.ConsoleWriter{Out: os.Stderr}).
With().
Timestamp().
Caller().
Logger()
return &logger
/*
log := logrus.New()
logger.Formatter = new(logrus.TextFormatter)
logger.Formatter.(*logrus.TextFormatter).DisableColors = false
logger.Formatter.(*logrus.TextFormatter).DisableTimestamp = true
logger.Level = logrus.TraceLevel
logger.Out = os.Stdout
*/
}
func initConf(path string) (*config, error) {
vi := viper.New()
vi.SetEnvPrefix("SG")
vi.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
vi.AutomaticEnv()
vi.AddConfigPath(path)
vi.AddConfigPath("./config")
vi.SetConfigName(getConfigName())
vi.SetDefault("host_port", "0.0.0.0:8080")
vi.SetDefault("web_ui", false)
vi.SetDefault("enable_tracing", false)
vi.SetDefault("auth_fail_block", "always")
vi.SetDefault("seed_file", "seed.js")
vi.SetDefault("database.type", "postgres")
vi.SetDefault("database.host", "localhost")
vi.SetDefault("database.port", 5432)
vi.SetDefault("database.user", "postgres")
vi.SetDefault("env", "development")
vi.BindEnv("env", "GO_ENV")
vi.BindEnv("HOST", "HOST")
vi.BindEnv("PORT", "PORT")
vi.SetDefault("auth.rails.max_idle", 80)
vi.SetDefault("auth.rails.max_active", 12000)
if err := vi.ReadInConfig(); err != nil {
return nil, err
}
c := &config{}
if err := vi.Unmarshal(c); err != nil {
return nil, fmt.Errorf("unable to decode config, %v", err)
}
for k, v := range c.Inflections {
flect.AddPlural(k, v)
}
for i := range c.DB.Tables {
t := c.DB.Tables[i]
t.Name = flect.Pluralize(strings.ToLower(t.Name))
}
authFailBlock = getAuthFailBlock(c)
//fmt.Printf("%#v", c)
return c, nil
}
func initDB(c *config) (*pg.DB, error) {
opt := &pg.Options{
Addr: strings.Join([]string{c.DB.Host, c.DB.Port}, ":"),
User: c.DB.User,
Password: c.DB.Password,
Database: c.DB.DBName,
ApplicationName: c.AppName,
}
if c.DB.PoolSize != 0 {
opt.PoolSize = conf.DB.PoolSize
}
if c.DB.MaxRetries != 0 {
opt.MaxRetries = c.DB.MaxRetries
}
if len(c.DB.Schema) != 0 {
opt.OnConnect = func(conn *pg.Conn) error {
_, err := conn.Exec("set search_path=?", c.DB.Schema)
if err != nil {
return err
}
return nil
}
}
db := pg.Connect(opt)
if db == nil {
return nil, errors.New("failed to connect to postgres db")
}
return db, nil
}
func Init() {
var err error
path := flag.String("path", "./config", "Path to config files")
flag.Parse()
logger = initLog()
conf, err = initConf(*path)
if err != nil {
logger.Fatal().Err(err).Msg("failed to read config")
}
logLevel, err := zerolog.ParseLevel(conf.LogLevel)
if err != nil {
logger.Error().Err(err).Msg("error setting log_level")
}
zerolog.SetGlobalLevel(logLevel)
db, err = initDB(conf)
if err != nil {
logger.Fatal().Err(err).Msg("failed to connect to database")
}
qcompile, pcompile, err = initCompilers(conf)
if err != nil {
logger.Fatal().Err(err).Msg("failed to connect to database")
}
if err := initResolvers(); err != nil {
logger.Fatal().Err(err).Msg("failed to initialized resolvers")
}
args := flag.Args()
if len(args) == 0 {
cmdServ(*path)
}
switch args[0] {
case "seed":
cmdSeed(*path)
case "serv":
fallthrough
default:
logger.Fatal().Msg("options: [serve|seed]")
}
}
func cmdServ(path string) {
initAllowList(path)
initPreparedList()
initWatcher(path)
startHTTP()
}

View File

@ -18,6 +18,7 @@ type config struct {
UseAllowList bool `mapstructure:"use_allow_list"`
WatchAndReload bool `mapstructure:"reload_on_config_change"`
AuthFailBlock string `mapstructure:"auth_fail_block"`
SeedFile string `mapstructure:"seed_file"`
Inflections map[string]string
Auth struct {

View File

@ -31,21 +31,29 @@ type coreContext struct {
}
func (c *coreContext) handleReq(w io.Writer, req *http.Request) error {
c.req.ref = req.Referer()
c.req.hdr = req.Header
b, err := c.execQuery()
if err != nil {
return err
}
return c.render(w, b)
}
func (c *coreContext) execQuery() ([]byte, error) {
var err error
var skipped uint32
var qc *qcode.QCode
var data []byte
c.req.ref = req.Referer()
//conf.UseAllowList = true
if conf.UseAllowList {
var ps *preparedItem
data, ps, err = c.resolvePreparedSQL(c.req.Query)
if err != nil {
return err
return nil, err
}
skipped = ps.skipped
@ -55,17 +63,17 @@ func (c *coreContext) handleReq(w io.Writer, req *http.Request) error {
qc, err = qcompile.Compile([]byte(c.req.Query))
if err != nil {
return err
return nil, err
}
data, skipped, err = c.resolveSQL(qc)
if err != nil {
return err
return nil, err
}
}
if len(data) == 0 || skipped == 0 {
return c.render(w, data)
return data, nil
}
sel := qc.Selects
@ -83,31 +91,31 @@ func (c *coreContext) handleReq(w io.Writer, req *http.Request) error {
var to []jsn.Field
switch {
case len(from) == 1:
to, err = c.resolveRemote(req, h, from[0], sel, sfmap)
to, err = c.resolveRemote(c.req.hdr, h, from[0], sel, sfmap)
case len(from) > 1:
to, err = c.resolveRemotes(req, h, from, sel, sfmap)
to, err = c.resolveRemotes(c.req.hdr, h, from, sel, sfmap)
default:
return errors.New("something wrong no remote ids found in db response")
return nil, errors.New("something wrong no remote ids found in db response")
}
if err != nil {
return err
return nil, err
}
var ob bytes.Buffer
err = jsn.Replace(&ob, data, from, to)
if err != nil {
return err
return nil, err
}
return c.render(w, ob.Bytes())
return ob.Bytes(), nil
}
func (c *coreContext) resolveRemote(
req *http.Request,
hdr http.Header,
h *xxhash.Digest,
field jsn.Field,
sel []qcode.Select,
@ -143,7 +151,7 @@ func (c *coreContext) resolveRemote(
st := time.Now()
b, err := r.Fn(req, id)
b, err := r.Fn(hdr, id)
if err != nil {
return nil, err
}
@ -173,7 +181,7 @@ func (c *coreContext) resolveRemote(
}
func (c *coreContext) resolveRemotes(
req *http.Request,
hdr http.Header,
h *xxhash.Digest,
from []jsn.Field,
sel []qcode.Select,
@ -218,7 +226,7 @@ func (c *coreContext) resolveRemotes(
st := time.Now()
b, err := r.Fn(req, id)
b, err := r.Fn(hdr, id)
if err != nil {
cerr = fmt.Errorf("%s: %s", s.Table, err)
return
@ -324,6 +332,7 @@ func (c *coreContext) resolveSQL(qc *qcode.QCode) (
if conf.LogLevel == "debug" {
os.Stdout.WriteString(finalSQL)
os.Stdout.WriteString("\n\n")
}
var st time.Time
@ -346,7 +355,7 @@ func (c *coreContext) resolveSQL(qc *qcode.QCode) (
}
}
fmt.Printf("RAW: %#v\n", finalSQL)
//fmt.Printf("\nRAW: %#v\n", finalSQL)
var root json.RawMessage
_, err = tx.QueryOne(pg.Scan(&root), finalSQL)

View File

@ -30,6 +30,7 @@ type gqlReq struct {
Query string `json:"query"`
Vars json.RawMessage `json:"variables"`
ref string
hdr http.Header
}
type variables map[string]json.RawMessage

View File

@ -19,7 +19,7 @@ var (
type resolvFn struct {
IDField []byte
Path [][]byte
Fn func(r *http.Request, id []byte) ([]byte, error)
Fn func(h http.Header, id []byte) ([]byte, error)
}
func initResolvers() error {
@ -92,11 +92,11 @@ func initRemotes(t configTable) error {
return nil
}
func buildFn(r configRemote) func(*http.Request, []byte) ([]byte, error) {
func buildFn(r configRemote) func(http.Header, []byte) ([]byte, error) {
reqURL := strings.Replace(r.URL, "$id", "%s", 1)
client := &http.Client{}
fn := func(inReq *http.Request, id []byte) ([]byte, error) {
fn := func(hdr http.Header, id []byte) ([]byte, error) {
uri := fmt.Sprintf(reqURL, id)
req, err := http.NewRequest("GET", uri, nil)
if err != nil {
@ -108,10 +108,10 @@ func buildFn(r configRemote) func(*http.Request, []byte) ([]byte, error) {
}
for _, v := range r.PassHeaders {
req.Header.Set(v, inReq.Header.Get(v))
req.Header.Set(v, hdr.Get(v))
}
if host, ok := req.Header["Host"]; ok {
if host, ok := hdr["Host"]; ok {
req.Host = host[0]
}

260
serv/seed.go Normal file
View File

@ -0,0 +1,260 @@
package serv
import (
"context"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"os"
"path"
"github.com/brianvoe/gofakeit"
"github.com/dop251/goja"
)
func cmdSeed(cpath string) {
conf.UseAllowList = false
b, err := ioutil.ReadFile(path.Join(cpath, conf.SeedFile))
if err != nil {
logger.Fatal().Err(err).Msg("failed to read file")
}
vm := goja.New()
vm.Set("graphql", graphQLFunc)
console := vm.NewObject()
console.Set("log", logFunc)
vm.Set("console", console)
fake := vm.NewObject()
setFakeFuncs(fake)
vm.Set("fake", fake)
_, err = vm.RunScript("seed.js", string(b))
if err != nil {
logger.Fatal().Err(err).Msg("failed to execute script")
}
}
//func runFunc(call goja.FunctionCall) {
func graphQLFunc(query string, data interface{}) map[string]interface{} {
b, err := json.Marshal(data)
if err != nil {
logger.Fatal().Err(err).Msg("failed to json serialize")
}
c := &coreContext{Context: context.Background()}
c.req.Query = query
c.req.Vars = b
res, err := c.execQuery()
if err != nil {
logger.Fatal().Err(err).Msg("graphql query failed")
}
val := make(map[string]interface{})
err = json.Unmarshal(res, &val)
if err != nil {
logger.Fatal().Err(err).Msg("failed to deserialize json")
}
return val
}
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 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("status_code", gofakeit.StatusCode)
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("vehicle", gofakeit.Vehicle)
f.Set("vehicle_type", gofakeit.VehicleType)
f.Set("car_maker", gofakeit.CarMaker)
f.Set("car_model", gofakeit.CarModel)
f.Set("fuel_type", gofakeit.FuelType)
f.Set("transmission_gear_type", gofakeit.TransmissionGearType)
// Text
f.Set("word", gofakeit.Word)
f.Set("sentence", gofakeit.Sentence)
f.Set("paragrph", 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", gofakeit.ImageURL)
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("simple_status_code", gofakeit.SimpleStatusCode)
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_number_luhn", gofakeit.CreditCardNumberLuhn)
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_ingverb", gofakeit.HackerIngverb)
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)
//Languages
//f.Set("language", gofakeit.Language)
//f.Set("language_abbreviation", gofakeit.LanguageAbbreviation)
//f.Set("language_abbreviation", gofakeit.LanguageAbbreviation)
// File
f.Set("extension", gofakeit.Extension)
f.Set("mine_type", gofakeit.MimeType)
// 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", gofakeit.RandString)
f.Set("shuffle_strings", gofakeit.ShuffleStrings)
f.Set("numerify", gofakeit.Numerify)
//f.Set("programming_language", gofakeit.ProgrammingLanguage)
}

View File

@ -2,8 +2,6 @@ package serv
import (
"context"
"errors"
"flag"
"fmt"
"net/http"
"os"
@ -13,139 +11,8 @@ import (
"github.com/dosco/super-graph/psql"
"github.com/dosco/super-graph/qcode"
"github.com/go-pg/pg"
"github.com/gobuffalo/flect"
"github.com/rs/zerolog"
"github.com/spf13/viper"
)
//go:generate esc -o static.go -ignore \\.DS_Store -prefix ../web/build -private -pkg serv ../web/build
const (
serverName = "Super Graph"
authFailBlockAlways = iota + 1
authFailBlockPerQuery
authFailBlockNever
)
var (
logger *zerolog.Logger
conf *config
db *pg.DB
qcompile *qcode.Compiler
pcompile *psql.Compiler
authFailBlock int
)
func initLog() *zerolog.Logger {
logger := zerolog.New(zerolog.ConsoleWriter{Out: os.Stderr}).
With().
Timestamp().
Caller().
Logger()
return &logger
/*
log := logrus.New()
logger.Formatter = new(logrus.TextFormatter)
logger.Formatter.(*logrus.TextFormatter).DisableColors = false
logger.Formatter.(*logrus.TextFormatter).DisableTimestamp = true
logger.Level = logrus.TraceLevel
logger.Out = os.Stdout
*/
}
func initConf(path string) (*config, error) {
vi := viper.New()
vi.SetEnvPrefix("SG")
vi.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
vi.AutomaticEnv()
vi.AddConfigPath(path)
vi.AddConfigPath("./config")
vi.SetConfigName(getConfigName())
vi.SetDefault("host_port", "0.0.0.0:8080")
vi.SetDefault("web_ui", false)
vi.SetDefault("enable_tracing", false)
vi.SetDefault("auth_fail_block", "always")
vi.SetDefault("database.type", "postgres")
vi.SetDefault("database.host", "localhost")
vi.SetDefault("database.port", 5432)
vi.SetDefault("database.user", "postgres")
vi.SetDefault("env", "development")
vi.BindEnv("env", "GO_ENV")
vi.BindEnv("HOST", "HOST")
vi.BindEnv("PORT", "PORT")
vi.SetDefault("auth.rails.max_idle", 80)
vi.SetDefault("auth.rails.max_active", 12000)
if err := vi.ReadInConfig(); err != nil {
return nil, err
}
c := &config{}
if err := vi.Unmarshal(c); err != nil {
return nil, fmt.Errorf("unable to decode config, %v", err)
}
for k, v := range c.Inflections {
flect.AddPlural(k, v)
}
for i := range c.DB.Tables {
t := c.DB.Tables[i]
t.Name = flect.Pluralize(strings.ToLower(t.Name))
}
authFailBlock = getAuthFailBlock(c)
//fmt.Printf("%#v", c)
return c, nil
}
func initDB(c *config) (*pg.DB, error) {
opt := &pg.Options{
Addr: strings.Join([]string{c.DB.Host, c.DB.Port}, ":"),
User: c.DB.User,
Password: c.DB.Password,
Database: c.DB.DBName,
ApplicationName: c.AppName,
}
if c.DB.PoolSize != 0 {
opt.PoolSize = conf.DB.PoolSize
}
if c.DB.MaxRetries != 0 {
opt.MaxRetries = c.DB.MaxRetries
}
if len(c.DB.Schema) != 0 {
opt.OnConnect = func(conn *pg.Conn) error {
_, err := conn.Exec("set search_path=?", c.DB.Schema)
if err != nil {
return err
}
return nil
}
}
db := pg.Connect(opt)
if db == nil {
return nil, errors.New("failed to connect to postgres db")
}
return db, nil
}
func initCompilers(c *config) (*qcode.Compiler, *psql.Compiler, error) {
schema, err := psql.NewDBSchema(db, c.getAliasMap())
if err != nil {
@ -191,46 +58,6 @@ func initWatcher(path string) {
}()
}
func Init() {
var err error
path := flag.String("path", "./", "Path to config files")
flag.Parse()
logger = initLog()
conf, err = initConf(*path)
if err != nil {
logger.Fatal().Err(err).Msg("failed to read config")
}
logLevel, err := zerolog.ParseLevel(conf.LogLevel)
if err != nil {
logger.Error().Err(err).Msg("error setting log_level")
}
zerolog.SetGlobalLevel(logLevel)
db, err = initDB(conf)
if err != nil {
logger.Fatal().Err(err).Msg("failed to connect to database")
}
qcompile, pcompile, err = initCompilers(conf)
if err != nil {
logger.Fatal().Err(err).Msg("failed to connect to database")
}
if err := initResolvers(); err != nil {
logger.Fatal().Err(err).Msg("failed to initialized resolvers")
}
initAllowList(*path)
initPreparedList()
initWatcher(*path)
startHTTP()
}
func startHTTP() {
hp := strings.SplitN(conf.HostPort, ":", 2)