Skip to content

Commit

Permalink
fix: add more tests and various fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
dosco committed Dec 18, 2022
1 parent 2c14240 commit c261e35
Show file tree
Hide file tree
Showing 31 changed files with 338 additions and 256 deletions.
8 changes: 0 additions & 8 deletions .deepsource.toml

This file was deleted.

1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,6 @@ node_modules
bin
./package-lock.json
slim.report.json
examples/nodejs/config/**/*.gql


6 changes: 2 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<!-- [![Run on Google Cloud](./.github/deploy-cloud-run-button.svg)](https://deploy.cloud.run)
-->

GraphJin gives you an instant secure and fast GraphQL API without code. Just use a GraphQL query to define your API and GraphJin automagically converts it into a full featured API. Build your backend APIs **100X** faster. Works with **NodeJS** and **GO**. Supports several databases, **Postgres**, **MySQL**, **YugabyteDB**, **Cockroach**, etc.
GraphJin gives you an instant secure and fast GraphQL API without code. Just use a GraphQL query to define your API and GraphJin automagically converts it into a full featured API. Build your backend APIs **100X** faster. Works with **NodeJS** and **GO**. Supports several databases, **Postgres**, **MySQL**, **YugabyteDB**, etc.

## Secure out of the box

Expand Down Expand Up @@ -83,7 +83,6 @@ console.log("Express server started on port %s", server.address().port);

### Quick install


```
# Mac (Homebrew)
brew install dosco/graphjin/graphjin
Expand All @@ -95,7 +94,6 @@ sudo snap install --classic graphjin
Debian and Redhat ([releases](https://github.com/dosco/graphjin/releases))
Download the .deb or .rpm from the releases page and install with dpkg -i and rpm -i respectively.


### Quickly create and deploy new apps

```bash
Expand Down Expand Up @@ -240,7 +238,7 @@ With GraphJin your web and mobile developers can start building instantly. All t

## Highlevel

- Works with Postgres, MySQL8, YugabyteDB, CockroachDB,
- Works with Postgres, MySQL8, YugabyteDB
- Also works with Amazon Aurora/RDS and Google Cloud SQL
- Supports REST, GraphQL and Websocket APIs

Expand Down
43 changes: 9 additions & 34 deletions core/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ import (
"sync/atomic"
"time"

"github.com/chirino/graphql"
"github.com/dosco/graphjin/core/internal/allow"
"github.com/dosco/graphjin/core/internal/graph"
"github.com/dosco/graphjin/core/internal/psql"
Expand Down Expand Up @@ -107,7 +106,6 @@ type graphjin struct {
abacEnabled bool
qc *qcode.Compiler
pc *psql.Compiler
ge *graphql.Engine
subs sync.Map
scriptMap map[string]plugin.ScriptCompiler
validatorMap map[string]plugin.ValidationCompiler
Expand Down Expand Up @@ -205,10 +203,6 @@ func newGraphJin(conf *Config, db *sql.DB, dbinfo *sdata.DBInfo, options ...Opti
return nil, err
}

if err := gj.initGraphQLEgine(); err != nil {
return nil, err
}

if err := gj.prepareRoleStmt(); err != nil {
return nil, err
}
Expand Down Expand Up @@ -413,13 +407,6 @@ func (gj *graphjin) graphQLWithOpName(
ns = *rc.ns
}

// use the chirino/graphql library for introspection queries
// disabled when allow list is enforced
if !gj.prod && name == "IntrospectionQuery" {
res, err := gj.introspection(query)
return res, err
}

ct := &gcontext{
gj: gj,
rc: rc,
Expand All @@ -434,6 +421,15 @@ func (gj *graphjin) graphQLWithOpName(
name: name,
}

if !gj.prod && name == "IntrospectionQuery" {
v, err := gj.introspection(query)
if err != nil {
return res, err
}
res.Data = v
return res, nil
}

if ct.op == qcode.QTSubscription {
return res, errors.New("use 'core.Subscribe' for subscriptions")
}
Expand Down Expand Up @@ -480,19 +476,6 @@ func (gj *graphjin) graphQLWithOpName(
return res, err
}

func (g *GraphJin) Introspection(query string) (*Result, error) {
gj := g.Load().(*graphjin)
return gj.introspection(query)
}

func (gj *graphjin) introspection(query string) (*Result, error) {
r := gj.ge.ServeGraphQL(&graphql.Request{Query: query})
if err := r.Error(); err != nil {
return errResult("", err), err
}
return &Result{Data: r.Data}, nil
}

// Reload redoes database discover and reinitializes GraphJin.
func (g *GraphJin) Reload() error {
gj := g.Load().(*graphjin)
Expand Down Expand Up @@ -532,11 +515,3 @@ func Operation(query string) (h Header, err error) {
}
return
}

func errResult(name string, err error) *Result {
return &Result{
name: name,
Errors: []Error{{Message: err.Error()}},
}

}
3 changes: 0 additions & 3 deletions core/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,6 @@ type Config struct {
// removed in next major version
EnableInflection bool `mapstructure:"enable_inflection" jsonschema:"-"`

// Customize singular suffix. Default value is "ByID"
SingularSuffix string `mapstructure:"singular_suffix" jsonschema:"title=Singular Suffix,default=ById"`

// Database type name Defaults to 'postgres' (options: mysql, postgres)
DBType string `mapstructure:"db_type" jsonschema:"title=Database Type,enum=postgres,enum=mysql"`

Expand Down
9 changes: 0 additions & 9 deletions core/consts.go

This file was deleted.

7 changes: 1 addition & 6 deletions core/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
)

var decPrefix = []byte(`__gj/enc:`)
var ErrNotFound = errors.New("not found in prepared statements")

type OpType int

Expand Down Expand Up @@ -147,12 +148,6 @@ func (gj *graphjin) _initSchema() error {
return err
}

ssufx := gj.conf.SingularSuffix
if ssufx == "" {
ssufx = "ByID"
}
gj.schema.SingularSuffix = ssufx

return err
}

Expand Down
5 changes: 4 additions & 1 deletion core/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,10 @@ func addTableInfo(c *Config, t Table) error {

for k, ob := range t.OrderBy {
for _, v := range ob {
vals := strings.SplitN(v, " ", 2)
vals := strings.Fields(strings.TrimSpace(v))
if len(vals) != 2 {
return fmt.Errorf("invalid format for order by (column sort_order): %s", v)
}
obm[k] = append(obm[k], [2]string{vals[0], vals[1]})
}
}
Expand Down
7 changes: 5 additions & 2 deletions core/internal/psql/insert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,11 @@ func nestedInsertManyToMany(t *testing.T) {
due_date
customer {
id
full_name
email
vip
user {
id
full_name
}
}
product {
id
Expand Down
2 changes: 1 addition & 1 deletion core/internal/psql/psql_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ func TestMain(m *testing.M) {

err = qcompile.AddRole("user", "public", "customers", qcode.TRConfig{
Query: qcode.QueryConfig{
Columns: []string{"id", "email", "full_name", "products"},
Columns: []string{"id", "vip"},
},
})

Expand Down
19 changes: 12 additions & 7 deletions core/internal/psql/query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ func simpleQuery(t *testing.T) {
func withNestedOrderBy(t *testing.T) {
gql := `query {
products(
where: { and: {customer: { email: { eq: "http" }}, not: { customer: { email: { eq: ".com"} }}}}
order_by: { customer: { email: desc }}
where: { and: {customer: { user: { email: { eq: "http" } } },
not: { customer: { user: { email: { eq: ".com"} }}}}}
order_by: { customer: { vip: desc }}
) {
id
user {
Expand Down Expand Up @@ -246,8 +247,10 @@ func manyToMany(t *testing.T) {
products {
name
customers {
email
full_name
user {
email
full_name
}
}
}
}`
Expand All @@ -258,8 +261,10 @@ func manyToMany(t *testing.T) {
func manyToManyReverse(t *testing.T) {
gql := `query {
customers {
email
full_name
user {
email
full_name
}
products {
name
}
Expand Down Expand Up @@ -357,7 +362,7 @@ func multiRoot(t *testing.T) {
id
name
customer {
email
vip
}
}
users {
Expand Down
6 changes: 4 additions & 2 deletions core/internal/psql/update_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,10 @@ func nestedUpdateManyToMany(t *testing.T) {
due_date
customer {
id
full_name
email
user {
full_name
email
}
}
product {
id
Expand Down
2 changes: 1 addition & 1 deletion core/internal/qcode/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ type trval struct {
func (co *Compiler) AddRole(role, schema, table string, trc TRConfig) error {
var err error

ti, err := co.s.Find(schema, table)
ti, err := co.Find(schema, table)
if err != nil {
return err
}
Expand Down
3 changes: 1 addition & 2 deletions core/internal/qcode/exp.go
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,6 @@ func (ast *aexpst) processNestedTable(av aexp, ex *Exp, node *graph.Node) (bool,
var joins []Join
var err error

s := ast.co.s
ti := av.ti

var prev, curr string
Expand Down Expand Up @@ -484,7 +483,7 @@ func (ast *aexpst) processNestedTable(av aexp, ex *Exp, node *graph.Node) (bool,

var path []sdata.TPath
// TODO: Make this function work with schemas
if path, err = s.FindPath(curr, prev, ""); err != nil {
if path, err = ast.co.FindPath(curr, prev, ""); err != nil {
break
}

Expand Down
2 changes: 1 addition & 1 deletion core/internal/qcode/mutate.go
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ func (co *Compiler) processNestedMutations(ms *mState, m *Mutate, data *graph.No
}

// Get child-to-parent relationship
paths, err := co.s.FindPath(k, m.Key, "")
paths, err := co.FindPath(k, m.Key, "")
// no relationship found must be a keyword
if err != nil {
var ty MType
Expand Down
20 changes: 16 additions & 4 deletions core/internal/qcode/qcode.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ import (
)

const (
maxSelectors = 100
maxSelectors = 100
singularSuffix = "ByID"
)

type QType int8
Expand Down Expand Up @@ -543,7 +544,7 @@ func (co *Compiler) addRelInfo(
if co.c.EnableCamelcase {
parentF.Name = util.ToSnake(parentF.Name)
}
path, err := co.s.FindPath(childF.Name, parentF.Name, sel.through)
path, err := co.FindPath(childF.Name, parentF.Name, sel.through)
if err != nil {
return graphError(err, childF.Name, parentF.Name, sel.through)
}
Expand Down Expand Up @@ -581,7 +582,7 @@ func (co *Compiler) addRelInfo(
if sel.Schema != "" {
schema = sel.Schema
}
if sel.Ti, err = co.s.Find(schema, field.Name); err != nil {
if sel.Ti, err = co.Find(schema, field.Name); err != nil {
return err
}
} else {
Expand Down Expand Up @@ -730,6 +731,17 @@ func (co *Compiler) setRelFilters(qc *QCode, sel *Select) {
}
}

func (co *Compiler) Find(schema, name string) (sdata.DBTable, error) {
name = strings.TrimSuffix(name, singularSuffix)
return co.s.Find(schema, name)
}

func (co *Compiler) FindPath(from, to, through string) ([]sdata.TPath, error) {
from = strings.TrimSuffix(from, singularSuffix)
to = strings.TrimSuffix(to, singularSuffix)
return co.s.FindPath(from, to, through)
}

func buildFilter(rel sdata.DBRel, pid int32) *Exp {
switch rel.Type {
case sdata.RelOneToOne, sdata.RelOneToMany:
Expand Down Expand Up @@ -1583,7 +1595,7 @@ func (co *Compiler) compileArgOrderByObj(sel *Select, parent *graph.Node, cm map

case graph.NodeObj:
var path []sdata.TPath
if path, err = co.s.FindPath(node.Name, sel.Ti.Name, ""); err != nil {
if path, err = co.FindPath(node.Name, sel.Ti.Name, ""); err != nil {
continue
}
ti = path[0].LT
Expand Down
Loading

1 comment on commit c261e35

@vercel
Copy link

@vercel vercel bot commented on c261e35 Dec 18, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.