Documentation
¶
Overview ¶
Package core provides an API to include and use the GraphJin compiler with your own code. For detailed documentation visit https://graphjin.com
Example usage:
package main import ( "database/sql" "fmt" "time" "github.com/dosco/graphjin/v2/core" _ "github.com/jackc/pgx/v5/stdlib" ) func main() { db, err := sql.Open("pgx", "postgres://postgrs:@localhost:5432/example_db") if err != nil { log.Fatal(err) } gj, err := core.NewGraphJin(nil, db) if err != nil { log.Fatal(err) } query := ` query { posts { id title } }` ctx = context.WithValue(ctx, core.UserIDKey, 1) res, err := gj.GraphQL(ctx, query, nil) if err != nil { log.Fatal(err) } }
Example (Insert) ¶
Output: {"users":[{"email":"user1001@test.com","id":1001}]}
Example (InsertBulk) ¶
Output: {"users":[{"email":"user1002@test.com","id":1002},{"email":"user1003@test.com","id":1003}]}
Example (InsertInline) ¶
Output: {"users":[{"email":"user1007@test.com","full_name":"User 1007","id":1007}]}
Example (InsertInlineBulk) ¶
Output: {"users":[{"email":"two@test.com","id":1009},{"email":"one@test.com","id":1008}]}
Example (InsertInlineWithValidation) ¶
Output: validation failed: $full_name: failed on 'required_if' validation failed: $email: failed on 'email' validation failed
Example (InsertIntoMultipleRelatedTables) ¶
Output: {"purchases":[{"customer":{"email":"user1004@test.com","full_name":"User 1004","id":1004},"product":{"id":2002,"name":"Product 2002","price":2012.5},"quantity":5}]}
Example (InsertIntoRecursiveRelationship) ¶
Output: {"comments":[{"id":5001,"reply_to_id":null},{"id":5002,"reply_to_id":5001}]}
Example (InsertIntoRecursiveRelationshipAndConnectTable1) ¶
Output: {"comments":[{"id":5003,"reply_to_id":null},{"id":5,"reply_to_id":5003}]}
Example (InsertIntoRecursiveRelationshipAndConnectTable2) ¶
Output: {"comments":{"commenter":{"id":3},"comments":[{"id":6}],"id":5004,"product":{"id":26}}}
Example (InsertIntoTableAndConnectToRelatedTableWithArrayColumn) ¶
Output: {"products":[{"categories":[{"id":1,"name":"Category 1"},{"id":2,"name":"Category 2"},{"id":3,"name":"Category 3"},{"id":4,"name":"Category 4"},{"id":5,"name":"Category 5"}],"id":2006,"name":"Product 2006"}]}
Example (InsertIntoTableAndConnectToRelatedTables) ¶
Output: {"products":[{"id":2005,"name":"Product 2005","owner":{"email":"user6@test.com","full_name":"User 6","id":6}}]}
Example (InsertIntoTableAndRelatedTable1) ¶
Output: {"users":[{"email":"user1005@test.com","full_name":"User 1005","id":1005,"products":[{"id":2003,"name":"Product 2003","price":2013.5}]}]}
Example (InsertIntoTableAndRelatedTable2) ¶
Output: {"products":[{"id":2004,"name":"Product 2004","owner":{"email":"user1006@test.com","full_name":"User 1006","id":1006}}]}
Example (InsertIntoTableBulkInsertIntoRelatedTable) ¶
Output: {"users":[{"email":"user10051@test.com","full_name":"User 10051","id":10051,"products":[{"id":20031,"name":"Product 20031","price":2013.5},{"id":20032,"name":"Product 20032","price":2014.5}]}]}
Example (InsertWithCamelToSnakeCase) ¶
Output: {"products":[{"id":2007,"name":"Product 2007","owner":{"email":"user3@test.com","id":3}}]}
Example (InsertWithPresets) ¶
Output: {"products":[{"id":2001,"name":"Product 2001","owner":{"email":"user3@test.com","id":3}}]}
Example (Query) ¶
Output: {"products":[{"id":1,"owner":{"fullName":"User 1","id":1}},{"id":2,"owner":{"fullName":"User 2","id":2}},{"id":3,"owner":{"fullName":"User 3","id":3}}]}
Example (QueryBlockWithRoles) ¶
Output: {"users":null}
Example (QueryByID) ¶
Output: {"products":{"id":2,"name":"Product 2"}}
Example (QueryBySearch) ¶
Output: {"products":[{"id":3,"name":"Product 3"}]}
Example (QueryChildrenWithParent) ¶
Output: {"products":[{"name":"Product 1","owner":{"email":"user1@test.com"},"price":11.5},{"name":"Product 2","owner":{"email":"user2@test.com"},"price":12.5}]}
Example (QueryManyToManyViaJoinTable1) ¶
Output: {"products":[{"customer":[{"email":"user2@test.com"}],"name":"Product 1","owner":{"email":"user1@test.com"}},{"customer":[{"email":"user3@test.com"}],"name":"Product 2","owner":{"email":"user2@test.com"}}]}
Example (QueryManyToManyViaJoinTable2) ¶
Output: {"users":[{"email":"user1@test.com","full_name":"User 1","products":[{"name":"Product 1"}]},{"email":"user2@test.com","full_name":"User 2","products":[{"name":"Product 2"}]}]}
Example (QueryParentAndChildrenViaArrayColumn) ¶
Output: {"categories":[{"name":"Category 1","products":[{"name":"Product 1"},{"name":"Product 2"}]},{"name":"Category 2","products":[{"name":"Product 1"},{"name":"Product 2"}]}],"products":[{"categories":[{"id":1,"name":"Category 1"},{"id":2,"name":"Category 2"}],"name":"Product 1","price":11.5},{"categories":[{"id":1,"name":"Category 1"},{"id":2,"name":"Category 2"}],"name":"Product 2","price":12.5}]}
Example (QueryParentsWithChildren) ¶
Output: {"users":[{"email":"user1@test.com","products":[{"name":"Product 1","price":11.5}]},{"email":"user2@test.com","products":[{"name":"Product 2","price":12.5}]}]}
Example (QueryWithAggregation) ¶
Output: {"products":[{"count_id":100}]}
Example (QueryWithAggregationBlockedColumn) ¶
Output: db column blocked: price (role: 'anon')
Example (QueryWithAlternateFieldNames) ¶
Output: {"comments":[{"commenter":{"email":"user1@test.com"},"id":1},{"commenter":{"email":"user2@test.com"},"id":2}]}
Example (QueryWithCamelToSnakeCase) ¶
Output: {"hotProducts":[{"countProductID":1,"countryCode":"US","products":{"id":55}}]}
Example (QueryWithCursorPagination1) ¶
Output: [{"name": "Product 100"}, {"name": "Product 99"}, {"name": "Product 98"}]
Example (QueryWithCursorPagination2) ¶
Output: [{"name": "Product 100"}, {"name": "Product 99"}, {"name": "Product 98"}, {"name": "Product 97"}, {"name": "Product 96"}] [{"name": "Product 95"}, {"name": "Product 94"}, {"name": "Product 93"}, {"name": "Product 92"}, {"name": "Product 91"}] [{"name": "Product 90"}, {"name": "Product 89"}, {"name": "Product 88"}, {"name": "Product 87"}, {"name": "Product 86"}] [{"name": "Product 85"}, {"name": "Product 84"}, {"name": "Product 83"}, {"name": "Product 82"}, {"name": "Product 81"}] [{"name": "Product 80"}, {"name": "Product 79"}, {"name": "Product 78"}, {"name": "Product 77"}, {"name": "Product 76"}]
Example (QueryWithDynamicOrderBy) ¶
Output: {"products":[{"id":5,"price":15.5},{"id":4,"price":14.5},{"id":3,"price":13.5},{"id":2,"price":12.5},{"id":1,"price":11.5}]} {"products":[{"id":1,"price":11.5},{"id":2,"price":12.5},{"id":3,"price":13.5},{"id":4,"price":14.5},{"id":5,"price":15.5}]}
Example (QueryWithFragments1) ¶
Output: {"users":[{"email":"user1@test.com","full_name":"User 1","id":1,"stripe_id":"payment_id_1001"},{"email":"user2@test.com","full_name":"User 2","id":2,"stripe_id":"payment_id_1002"}]}
Example (QueryWithFragments2) ¶
Output: {"users":[{"email":"user1@test.com","full_name":"User 1","id":1,"stripe_id":"payment_id_1001"},{"email":"user2@test.com","full_name":"User 2","id":2,"stripe_id":"payment_id_1002"}]}
Example (QueryWithFragments3) ¶
Output: {"users":[{"email":"user1@test.com","full_name":"User 1","id":1,"stripe_id":"payment_id_1001"},{"email":"user2@test.com","full_name":"User 2","id":2,"stripe_id":"payment_id_1002"}]}
Example (QueryWithFunctionFields) ¶
Output: {"products":{"id":51,"is_hot_product":true,"name":"Product 51"}}
Example (QueryWithFunctionFieldsArgList) ¶
Output: {"products":{"id":51,"is_hot_product":true,"name":"Product 51"}}
Example (QueryWithFunctionReturingTables) ¶
Output: {"get_oldest5_products":[{"id":1,"name":"Product 1"},{"id":2,"name":"Product 2"},{"id":3,"name":"Product 3"}]}
Example (QueryWithFunctionReturingTablesWithArgs) ¶
Output: {"get_oldest_users":[{"full_name":"User 1","id":1,"tag_name":"boo"},{"full_name":"User 2","id":2,"tag_name":"boo"}]}
Example (QueryWithFunctionReturingTablesWithNamedArgs) ¶
Output: {"get_oldest_users":[{"full_name":"User 1","id":1,"tag_name":"boo"},{"full_name":"User 2","id":2,"tag_name":"boo"}]}
Example (QueryWithFunctionReturingUserDefinedTypes) ¶
Output: {"get_product":[{"id":1,"name":"Product 1"},{"id":2,"name":"Product 2"}]}
Example (QueryWithFunctionsBlocked) ¶
Output: all db functions blocked: sum (role: 'anon')
Example (QueryWithFunctionsWithWhere) ¶
Output: {"products":[{"max_price":110.5}]}
Example (QueryWithJsonColumn) ¶
Output: {"users":{"category_counts":[{"category":{"name":"Category 1"},"count":400},{"category":{"name":"Category 2"},"count":600}],"id":1}}
Example (QueryWithLimitOffsetOrderByDistinctAndWhere) ¶
Output: {"products":[{"id":99,"name":"Product 99","price":109.5},{"id":98,"name":"Product 98","price":108.5},{"id":97,"name":"Product 97","price":107.5},{"id":96,"name":"Product 96","price":106.5},{"id":95,"name":"Product 95","price":105.5}]}
Example (QueryWithMultipleTopLevelTables) ¶
Output: {"products":{"customer":[{"email":"user2@test.com"}],"id":1,"name":"Product 1"},"purchases":{"id":1},"users":{"email":"user1@test.com","id":1}}
Example (QueryWithNestedOrderBy) ¶
Output: {"products":[{"id":5,"price":15.5},{"id":4,"price":14.5},{"id":3,"price":13.5},{"id":2,"price":12.5},{"id":1,"price":11.5}]}
Example (QueryWithOrderByList) ¶
Output: {"products":[{"id":3,"price":13.5},{"id":2,"price":12.5},{"id":1,"price":11.5},{"id":5,"price":15.5}]}
Example (QueryWithRecursiveRelationship1) ¶
Output: {"reply":{"comments":[{"id":49},{"id":48},{"id":47},{"id":46},{"id":45}],"id":50}}
Example (QueryWithRecursiveRelationship2) ¶
Output: {"comments":{"id":95,"replies":[{"id":96},{"id":97},{"id":98},{"id":99},{"id":100}]}}
Example (QueryWithRecursiveRelationshipAndAggregations) ¶
Output: {"comments":{"id":95,"replies":[{"count_id":5}]}}
Example (QueryWithRemoteAPIJoin) ¶
Output: {"users":[{"email":"user1@test.com","payments":[{"desc":"Payment 1 for payment_id_1001"},{"desc":"Payment 2 for payment_id_1001"}]},{"email":"user2@test.com","payments":[{"desc":"Payment 1 for payment_id_1002"},{"desc":"Payment 2 for payment_id_1002"}]}]}
Example (QueryWithScriptDirective) ¶
Output: {"usersByID":{"email":"u...@test.com","id":2}}
Example (QueryWithScriptDirectiveUsingGraphQL) ¶
Output: {"usersByID":{"email":"user1@test.com","id":2}}
Example (QueryWithScriptDirectiveUsingHttp) ¶
Output: {"hello":"world"}
Example (QueryWithSkipAndIncludeDirectives) ¶
Output: {"products":[{"id":1,"name":"Product 1"},{"id":2,"name":"Product 2"}],"users":[]}
Example (QueryWithSkipAndIncludeFieldDirectives) ¶
Output: {"products":[{"id":1,"name":"Product 1"},{"id":2,"name":"Product 2"}],"users":[{"id":null},{"id":null},{"id":null}]}
Example (QueryWithSkippingAuthRequiredSelectors) ¶
Output: {"products":[{"id":1,"name":"Product 1","owner":null},{"id":2,"name":"Product 2","owner":null}]}
Example (QueryWithSyntheticTables) ¶
Output: {"me":{"email":"user1@test.com"}}
Example (QueryWithTypename) ¶
Output: {"__typename":"getUser","users":{"__typename":"users","email":"user1@test.com","id":1}}
Example (QueryWithUnionForPolymorphicRelationships) ¶
Output: {"notifications":[{"id":1,"subject":{"email":"user1@test.com"},"verb":"Joined"},{"id":2,"subject":{"name":"Product 2"},"verb":"Bought"}]}
Example (QueryWithUser) ¶
Output: {"products":[{"id":31,"owner":{"id":31}}]}
Example (QueryWithVariableLimit) ¶
Output: {"products":[{"id":1},{"id":2},{"id":3},{"id":4},{"id":5},{"id":6},{"id":7},{"id":8},{"id":9},{"id":10}]}
Example (QueryWithVariables) ¶
Output: {"products":{"id":70,"name":"Product 70"}}
Example (QueryWithView) ¶
Output: {"hot_products":[{"product":{"id":51,"name":"Product 51"}},{"product":{"id":52,"name":"Product 52"}},{"product":{"id":53,"name":"Product 53"}}]}
Example (QueryWithWhere1) ¶
Output: {"products":[{"id":3},{"id":34}]}
Example (QueryWithWhereGreaterThanOrLesserThan) ¶
Output: {"products":[{"id":1,"name":"Product 1","price":11.5},{"id":2,"name":"Product 2","price":12.5},{"id":3,"name":"Product 3","price":13.5}]}
Example (QueryWithWhereHasAnyKey) ¶
Output: {"products":[{"id":1},{"id":2},{"id":3}]}
Example (QueryWithWhereIn) ¶
Output: {"products":[{"id":1},{"id":2},{"id":3}]}
Example (QueryWithWhereNotIsNullAndGreaterThan) ¶
Output: {"products":[{"id":1,"name":"Product 1","price":11.5},{"id":2,"name":"Product 2","price":12.5},{"id":3,"name":"Product 3","price":13.5}]}
Example (QueryWithWhereOnRelatedTable) ¶
Output: {"products":[{"id":2,"owner":{"email":"user2@test.com","id":2}},{"id":3,"owner":{"email":"user3@test.com","id":3}}]}
Example (SetArrayColumnToEmpty) ¶
Output: {"products":[{"id":100,"tags":[]}]}
Example (SetArrayColumnToValue) ¶
Output: {"products":[{"id":100,"tags":["super","great","wow"]}]}
Example (Subscription) ¶
Output: {"users":{"email":"user3@test.com","id":3,"phone":null}} {"users":{"email":"user3@test.com","id":3,"phone":"650-447-0000"}} {"users":{"email":"user3@test.com","id":3,"phone":"650-447-0001"}} {"users":{"email":"user3@test.com","id":3,"phone":"650-447-0002"}} {"users":{"email":"user3@test.com","id":3,"phone":"650-447-0003"}} {"users":{"email":"user3@test.com","id":3,"phone":"650-447-0004"}} {"users":{"email":"user3@test.com","id":3,"phone":"650-447-0005"}} {"users":{"email":"user3@test.com","id":3,"phone":"650-447-0006"}} {"users":{"email":"user3@test.com","id":3,"phone":"650-447-0007"}} {"users":{"email":"user3@test.com","id":3,"phone":"650-447-0008"}}
Example (SubscriptionWithCursor) ¶
Output: {"chats":[{"body":"This is chat message number 1","id":1}],"chats_cursor":"cursor_was_here"} {"chats":[{"body":"This is chat message number 2","id":2}],"chats_cursor":"cursor_was_here"} {"chats":[{"body":"This is chat message number 3","id":3}],"chats_cursor":"cursor_was_here"} {"chats":[{"body":"This is chat message number 4","id":4}],"chats_cursor":"cursor_was_here"} {"chats":[{"body":"This is chat message number 5","id":5}],"chats_cursor":"cursor_was_here"} {"chats":[{"body":"New chat message 6","id":6}],"chats_cursor":"cursor_was_here"} {"chats":[{"body":"New chat message 7","id":7}],"chats_cursor":"cursor_was_here"} {"chats":[{"body":"New chat message 8","id":8}],"chats_cursor":"cursor_was_here"} {"chats":[{"body":"New chat message 9","id":9}],"chats_cursor":"cursor_was_here"} {"chats":[{"body":"New chat message 10","id":10}],"chats_cursor":"cursor_was_here"} {"chats":[{"body":"New chat message 11","id":11}],"chats_cursor":"cursor_was_here"} {"chats":[{"body":"New chat message 12","id":12}],"chats_cursor":"cursor_was_here"} {"chats":[{"body":"New chat message 13","id":13}],"chats_cursor":"cursor_was_here"} {"chats":[{"body":"New chat message 14","id":14}],"chats_cursor":"cursor_was_here"} {"chats":[{"body":"New chat message 15","id":15}],"chats_cursor":"cursor_was_here"} {"chats":[{"body":"New chat message 16","id":16}],"chats_cursor":"cursor_was_here"} {"chats":[{"body":"New chat message 17","id":17}],"chats_cursor":"cursor_was_here"} {"chats":[{"body":"New chat message 18","id":18}],"chats_cursor":"cursor_was_here"} {"chats":[{"body":"New chat message 19","id":19}],"chats_cursor":"cursor_was_here"}
Example (Update) ¶
Output: {"products":{"id":100,"name":"Updated Product 100"}}
Example (UpdateMultipleRelatedTables1) ¶
Output: {"purchases":{"customer":{"full_name":"Updated user related to purchase 100"},"product":{"description":"Updated product related to purchase 100"},"quantity":6}}
Example (UpdateTableAndConnectToRelatedTables) ¶
Output: {"users":{"full_name":"Updated user 100","products":[{"id":99}]}}
Example (UpdateTableAndRelatedTable) ¶
Output: {"users":{"full_name":"Updated user 90","products":[{"id":90}]}}
Example (VeryComplexQueryWithArrayColumns) ¶
TODO: Fix: Does not work in MYSQL
Output: {"products":[{"category":[{"id":1,"name":"Category 1"},{"id":2,"name":"Category 2"}],"id":27,"name":"Product 27","owner":{"category_counts":[{"category":{"name":"Category 1"},"count":400},{"category":{"name":"Category 2"},"count":600}],"email":"user27@test.com","full_name":"User 27","picture":null},"price":37.5}]}
Index ¶
- Constants
- Variables
- func Upgrade(configPath string) error
- type Column
- type Config
- type Delete
- type Error
- type GraphJin
- func (g *GraphJin) GraphQL(c context.Context, query string, vars json.RawMessage, rc *ReqConfig) (*Result, error)
- func (g *GraphJin) GraphQLByName(c context.Context, name string, vars json.RawMessage, rc *ReqConfig) (*Result, error)
- func (g *GraphJin) IsProd() bool
- func (g *GraphJin) Reload() error
- func (g *GraphJin) Subscribe(c context.Context, query string, vars json.RawMessage, rc *ReqConfig) (*Member, error)
- func (g *GraphJin) SubscribeByName(c context.Context, name string, vars json.RawMessage, rc *ReqConfig) (*Member, error)
- type Header
- type Insert
- type Member
- type OpType
- type Option
- type Query
- type ReqConfig
- type Resolver
- type ResolverConfig
- type ResolverProps
- type ResolverReq
- type Result
- type Role
- type RoleTable
- type Table
- type Update
- type Upsert
Examples ¶
- Package (Insert)
- Package (InsertBulk)
- Package (InsertInline)
- Package (InsertInlineBulk)
- Package (InsertInlineWithValidation)
- Package (InsertIntoMultipleRelatedTables)
- Package (InsertIntoRecursiveRelationship)
- Package (InsertIntoRecursiveRelationshipAndConnectTable1)
- Package (InsertIntoRecursiveRelationshipAndConnectTable2)
- Package (InsertIntoTableAndConnectToRelatedTableWithArrayColumn)
- Package (InsertIntoTableAndConnectToRelatedTables)
- Package (InsertIntoTableAndRelatedTable1)
- Package (InsertIntoTableAndRelatedTable2)
- Package (InsertIntoTableBulkInsertIntoRelatedTable)
- Package (InsertWithCamelToSnakeCase)
- Package (InsertWithPresets)
- Package (Query)
- Package (QueryBlockWithRoles)
- Package (QueryByID)
- Package (QueryBySearch)
- Package (QueryChildrenWithParent)
- Package (QueryManyToManyViaJoinTable1)
- Package (QueryManyToManyViaJoinTable2)
- Package (QueryParentAndChildrenViaArrayColumn)
- Package (QueryParentsWithChildren)
- Package (QueryWithAggregation)
- Package (QueryWithAggregationBlockedColumn)
- Package (QueryWithAlternateFieldNames)
- Package (QueryWithCamelToSnakeCase)
- Package (QueryWithCursorPagination1)
- Package (QueryWithCursorPagination2)
- Package (QueryWithDynamicOrderBy)
- Package (QueryWithFragments1)
- Package (QueryWithFragments2)
- Package (QueryWithFragments3)
- Package (QueryWithFunctionFields)
- Package (QueryWithFunctionFieldsArgList)
- Package (QueryWithFunctionReturingTables)
- Package (QueryWithFunctionReturingTablesWithArgs)
- Package (QueryWithFunctionReturingTablesWithNamedArgs)
- Package (QueryWithFunctionReturingUserDefinedTypes)
- Package (QueryWithFunctionsBlocked)
- Package (QueryWithFunctionsWithWhere)
- Package (QueryWithJsonColumn)
- Package (QueryWithLimitOffsetOrderByDistinctAndWhere)
- Package (QueryWithMultipleTopLevelTables)
- Package (QueryWithNestedOrderBy)
- Package (QueryWithOrderByList)
- Package (QueryWithRecursiveRelationship1)
- Package (QueryWithRecursiveRelationship2)
- Package (QueryWithRecursiveRelationshipAndAggregations)
- Package (QueryWithRemoteAPIJoin)
- Package (QueryWithScriptDirective)
- Package (QueryWithScriptDirectiveUsingGraphQL)
- Package (QueryWithScriptDirectiveUsingHttp)
- Package (QueryWithSkipAndIncludeDirectives)
- Package (QueryWithSkipAndIncludeFieldDirectives)
- Package (QueryWithSkippingAuthRequiredSelectors)
- Package (QueryWithSyntheticTables)
- Package (QueryWithTypename)
- Package (QueryWithUnionForPolymorphicRelationships)
- Package (QueryWithUser)
- Package (QueryWithVariableLimit)
- Package (QueryWithVariables)
- Package (QueryWithView)
- Package (QueryWithWhere1)
- Package (QueryWithWhereGreaterThanOrLesserThan)
- Package (QueryWithWhereHasAnyKey)
- Package (QueryWithWhereIn)
- Package (QueryWithWhereNotIsNullAndGreaterThan)
- Package (QueryWithWhereOnRelatedTable)
- Package (SetArrayColumnToEmpty)
- Package (SetArrayColumnToValue)
- Package (Subscription)
- Package (SubscriptionWithCursor)
- Package (Update)
- Package (UpdateMultipleRelatedTables1)
- Package (UpdateTableAndConnectToRelatedTables)
- Package (UpdateTableAndRelatedTable)
- Package (VeryComplexQueryWithArrayColumns)
Constants ¶
const ( // Name of the authentication provider. Eg. google, github, etc UserIDProviderKey contextkey = iota // The raw user id (jwt sub) value UserIDRawKey // User ID value for authenticated users UserIDKey // User role if pre-defined UserRoleKey )
Constants to set values on the context passed to the NewGraphJin function
Variables ¶
var ErrNotFound = errors.New("not found in prepared statements")
Functions ¶
Types ¶
type Column ¶
type Column struct { Name string Type string `jsonschema:"example=integer,example=text"` Primary bool Array bool ForeignKey string `` /* 138-byte string literal not displayed */ }
Configuration for a database table column
type Config ¶
type Config struct { // Is used to encrypt opaque values such as the cursor. Auto-generated when not set SecretKey string `mapstructure:"secret_key" json:"secret_key" yaml:"secret_key" jsonschema:"title=Secret Key"` // When set to true it disables the allow list workflow and all queries are // always compiled even in production (Warning possible security concern) DisableAllowList bool `` /* 137-byte string literal not displayed */ // Forces the database session variable 'user.id' to be set to the user id SetUserID bool `mapstructure:"set_user_id" json:"set_user_id" yaml:"set_user_id" jsonschema:"title=Set User ID,default=false"` // This ensures that for anonymous users (role 'anon') all tables are blocked // from queries and mutations. To open access to tables for anonymous users // they have to be added to the 'anon' role config DefaultBlock bool `` /* 135-byte string literal not displayed */ // This is a list of variables that can be leveraged in your queries. // (eg. variable admin_id will be $admin_id in the query) Vars map[string]string `mapstructure:"variables" json:"variables" yaml:"variables" jsonschema:"title=Variables"` // This is a list of variables that map to http header values HeaderVars map[string]string `mapstructure:"header_variables" json:"header_variables" yaml:"header_variables" jsonschema:"title=Header Variables"` // A list of tables and columns that should disallowed in any and all queries Blocklist []string `jsonschema:"title=Block List"` // The configs for custom resolvers. For example the `remote_api` // resolver would join json from a remote API into your query response Resolvers []ResolverConfig `jsonschema:"-"` // All table specific configuration such as aliased tables and relationships // between tables Tables []Table `jsonschema:"title=Tables"` // An SQL query if set enables attribute based access control. This query is // used to fetch the user attribute that then dynamically define the users role RolesQuery string `mapstructure:"roles_query" json:"roles_query" yaml:"roles_query" jsonschema:"title=Roles Query"` // Roles contains the configuration for all the roles you want to support 'user' and // 'anon' are two default roles. The 'user' role is used when a user ID is available // and 'anon' when it's not. Use the 'Roles Query' config to add more custom roles Roles []Role // Inflections is to add additionally singular to plural mappings // to the engine (eg. sheep: sheep) Inflections []string `mapstructure:"inflections" json:"inflections" yaml:"inflections" jsonschema:"-"` // Disable inflections. Inflections are deprecated and will be // removed in next major version EnableInflection bool `mapstructure:"enable_inflection" json:"enable_inflection" yaml:"enable_inflection" jsonschema:"-"` // Database type name Defaults to 'postgres' (options: mysql, postgres) DBType string `mapstructure:"db_type" json:"db_type" yaml:"db_type" jsonschema:"title=Database Type,enum=postgres,enum=mysql"` // Log warnings and other debug information Debug bool `jsonschema:"title=Debug,default=false"` // Database polling duration (in seconds) used by subscriptions to // query for updates. SubsPollDuration time.Duration `` /* 145-byte string literal not displayed */ // The default max limit (number of rows) when a limit is not defined in // the query or the table role config. DefaultLimit int `mapstructure:"default_limit" json:"default_limit" yaml:"default_limit" jsonschema:"title=Default Row Limit,default=20"` // Disable all aggregation functions like count, sum, etc DisableAgg bool `` /* 148-byte string literal not displayed */ // Disable all functions like count, length, etc DisableFuncs bool `` /* 133-byte string literal not displayed */ // Enable automatic coversion of camel case in GraphQL to snake case in SQL EnableCamelcase bool `` /* 130-byte string literal not displayed */ // When enabled GraphJin runs with production level security defaults. // For example allow lists are enforced. Production bool `jsonschema:"title=Production Mode,default=false"` // Duration for polling the database to detect schema changes DBSchemaPollDuration time.Duration `` /* 172-byte string literal not displayed */ // contains filtered or unexported fields }
Configuration for the GraphJin compiler core
func NewConfigWithFS ¶ added in v2.0.9
func (*Config) AddRoleTable ¶
AddRoleTable function is a helper function to make it easy to add per-table row-level config
func (*Config) RemoveRoleTable ¶
func (*Config) SetResolver ¶
type GraphJin ¶
func NewGraphJin ¶
NewGraphJin creates the GraphJin struct, this involves querying the database to learn its schemas and relationships
func NewGraphJinWithFS ¶ added in v2.0.9
func (*GraphJin) GraphQL ¶
func (g *GraphJin) GraphQL( c context.Context, query string, vars json.RawMessage, rc *ReqConfig) (*Result, error)
GraphQL function is called on the GraphJin struct to convert the provided GraphQL query into an SQL query and execute it on the database. In production mode prepared statements are directly used and no query compiling takes places.
In developer mode all named queries are saved into the queries folder and in production mode only queries from these saved queries can be used
func (*GraphJin) GraphQLByName ¶
func (g *GraphJin) GraphQLByName( c context.Context, name string, vars json.RawMessage, rc *ReqConfig) (*Result, error)
GraphQLByName is similar to the GraphQL function except that queries saved in the queries folder can directly be used by their filename.
func (*GraphJin) Subscribe ¶
func (g *GraphJin) Subscribe( c context.Context, query string, vars json.RawMessage, rc *ReqConfig) (*Member, error)
Subscribe function is called on the GraphJin struct to subscribe to query. Any database changes that apply to the query are streamed back in realtime.
In developer mode all named queries are saved into the queries folder and in production mode only queries from these saved queries can be used.
type Member ¶
type Member struct { Result chan *Result // contains filtered or unexported fields }
func (*Member) Unsubscribe ¶
func (m *Member) Unsubscribe()
type Option ¶
type Option func(*graphjin) error
func OptionSetFS ¶
func OptionSetNamespace ¶
func OptionSetScriptCompiler ¶
func OptionSetScriptCompiler(ext []string, se plugin.ScriptCompiler) Option
func OptionSetValidator ¶
func OptionSetValidator(name string, v plugin.ValidationCompiler) Option
type Query ¶
type Query struct { Limit int // Use filters to enforce table wide things like { disabled: false } where you never want disabled users to be shown. Filters []string Columns []string DisableFunctions bool `mapstructure:"disable_functions" json:"disable_functions" yaml:"disable_functions"` Block bool }
Table configuration for querying a table with a role
type ReqConfig ¶
type ReqConfig struct { // APQKey is set when using GraphJin with automatic persisted queries APQKey string // Pass additional variables complex variables such as functions that return string values. Vars map[string]interface{} // contains filtered or unexported fields }
ReqConfig is used to pass request specific config values to the GraphQLEx and SubscribeEx functions. Dynamic variables can be set here.
func (*ReqConfig) GetNamespace ¶
func (*ReqConfig) SetNamespace ¶
SetNamespace is used to set namespace requests within a single instance of GraphJin. For example queries with the same name
type Resolver ¶
type Resolver interface {
Resolve(context.Context, ResolverReq) ([]byte, error)
}
Resolver interface is used to create custom resolvers Custom resolvers must return a JSON value to be merged into the response JSON.
Example Redis Resolver:
type Redis struct { Addr string client redis.Client } func newRedis(v map[string]interface{}) (*Redis, error) { re := &Redis{} if err := mapstructure.Decode(v, re); err != nil { return nil, err } re.client := redis.NewClient(&redis.Options{ Addr: re.Addr, Password: "", // no password set DB: 0, // use default DB }) return re, nil } func (r *remoteAPI) Resolve(req ResolverReq) ([]byte, error) { val, err := rdb.Get(ctx, req.ID).Result() if err != nil { return err } return val, nil } func main() { conf := core.Config{ Resolvers: []Resolver{ Name: "cached_profile", Type: "redis", Table: "users", Column: "id", Props: []ResolverProps{ "addr": "localhost:6379", }, }, } gj.conf.SetResolver("redis", func(v ResolverProps) (Resolver, error) { return newRedis(v) }) gj, err := core.NewGraphJin(conf, db) if err != nil { log.Fatal(err) } }
type ResolverConfig ¶
type ResolverConfig struct { Name string Type string Schema string Table string Column string StripPath string `mapstructure:"strip_path" json:"strip_path" yaml:"strip_path"` Props ResolverProps `mapstructure:",remain"` }
ResolverConfig struct defines a custom resolver
type ResolverProps ¶
type ResolverProps map[string]interface{}
ResolverProps is a map of properties from the resolver config to be passed to the customer resolver's builder (new) function
type ResolverReq ¶
type Result ¶
type Result struct { Errors []Error `json:"errors,omitempty"` Vars json.RawMessage `json:"-"` Data json.RawMessage `json:"data,omitempty"` Hash [sha256.Size]byte `json:"-"` // contains filtered or unexported fields }
Result struct contains the output of the GraphQL function this includes resulting json from the database query and any error information
func (*Result) CacheControl ¶
func (*Result) OperationName ¶
type Role ¶
type Role struct { Name string Match string `jsonschema:"title=Related To,example=other_table.id_column,example=users.id"` Tables []RoleTable `jsonschema:"title=Table Configuration for Role"` // contains filtered or unexported fields }
Configuration for user role
type RoleTable ¶
type RoleTable struct { Name string Schema string ReadOnly bool `mapstructure:"read_only" json:"read_only" yaml:"read_only" jsonschema:"title=Read Only"` Query *Query Insert *Insert Update *Update Upsert *Upsert Delete *Delete }
Table configuration for a specific role (user role)
type Table ¶
type Table struct { Name string Schema string Table string // Inherits Table Type string Blocklist []string Columns []Column // Permitted order by options OrderBy map[string][]string `mapstructure:"order_by" json:"order_by" yaml:"order_by" jsonschema:"title=Order By Options,example=created_at desc"` }
Configuration for a database table