-
Notifications
You must be signed in to change notification settings - Fork 3
GraphiQL server (+ minor usability features) #112
Conversation
graphql/server/server.lua
Outdated
body = json.encode({errors={{message="Body should be a valid JSON"}}}) | ||
} | ||
end | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can check type(parsed) == 'table' here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added.
graphql/server/server.lua
Outdated
if not ok then | ||
return { | ||
status = 200, | ||
body = json.encode({errors={{message=result}}}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
's/=/ = /g' (in other places too)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did not get your point. Did you mean to 'a=b' -> 'a = b' ? If so, fixed. (I made it initially with no whitespaces to keep it one-line)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, that was the point.
@@ -190,7 +191,7 @@ local function gql_argument_type(avro_schema) | |||
|
|||
fields[field.name] = { | |||
name = field.name, | |||
kind = types.nonNull(gql_field_type), | |||
kind = gql_field_type, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You will not remember why this is needed after two months.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure, but it seems that current version does not need a comment, because it's quite straightforward. Previous version needed a comment because there was an additional nonNull wrapping with no obvious reason.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- The field cannot be non-null here (do we need to call nullable(gql_field_type))?
- I would add a comment like 'accept any subset of an input object field as a filter'. Ok?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Do you mean, that the field can't be non-null here because we want arguments (corresponding GraphQL InputObjects) to have all fields nullable? (As we discussed it verbally) If yes, so we need to do something like
nullable(gql_field_type)
But I think this should be done in another branch, related to InputObjects arguments support - Ok. That's what we do :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- I mean that nullability of Object should no affect nullability of InputObject.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did not get your point. Need to discus verbally.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Filed #127 and added comment tarantool/graphql#26 (comment)
assert_gql_query_ast('gql_compile', ast) | ||
local operation_name = ast.definitions[1].name.value | ||
|
||
local operation_name |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How this change related to the graphiql? What a problem you fix here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Before this story with GraphiQL Tarantool GraphQL (as a GraphQL backend) assumed that in all incoming queries there is only one definition (an operation definition describing the query itself).
It's true if the query is simple, but in case of fragments it is not. Each fragment represented as a definition in ast.
We want to support fragments in general. And they are necessary for our GraphiQL to work as it's JS code send an introspection query with fragments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can mention that they are more or less related in a commit message, but leave they open.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, I'll do so.
end | ||
end | ||
|
||
assert(operation_name, "there is no 'operation' in query " .. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is better to have ---
from yaml on its own line.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got your point, fixed.
graphql/tarantool_graphql.lua
Outdated
assert(type(gql) == 'table', | ||
'use :start_server(...) instead of .start_server(...)') | ||
gql.server = server.init(gql) | ||
gql.server:start() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe return true, 'The server started at http://127.0.0.1:8000' or kinda to improve usability from console?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea. Added.
favored resource bundler. | ||
--> | ||
<link rel="stylesheet" href="/static/css/graphiql.css" /> | ||
<script src="/static/js/graphiql.js"></script> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you forget to add these files into the commit?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. Sorry. Added them.
@@ -9,6 +9,10 @@ graphql.accessor_general = accessor_general | |||
graphql.accessor_space = accessor_space | |||
graphql.accessor_shard = accessor_shard | |||
graphql.new = tarantool_graphql.new | |||
graphql.compile = tarantool_graphql.compile | |||
graphql.execute = tarantool_graphql.execute | |||
graphql.start_server = tarantool_graphql.start_server |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No space format at all, got:
{
"errors": [
{
"message": "./graphql/core/validate.lua:223: assign to undeclared variable 'kind'"
}
]
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And with format too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What was the case? I added a test with user-configured tarantool graphql instance + server usage and it passed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I need to try again.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed. The problem was with global variables in grahql/core
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to track such problems: found problem with empty variables (it is converted to box.NULL and box.NULL or {} is not {}).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some comments I forgot to send before.
@@ -9,6 +9,10 @@ graphql.accessor_general = accessor_general | |||
graphql.accessor_space = accessor_space | |||
graphql.accessor_shard = accessor_shard | |||
graphql.new = tarantool_graphql.new | |||
graphql.compile = tarantool_graphql.compile | |||
graphql.execute = tarantool_graphql.execute | |||
graphql.start_server = tarantool_graphql.start_server |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And with format too.
graphql/server/server.lua
Outdated
if not ok then | ||
return { | ||
status = 200, | ||
body = json.encode({errors={{message=result}}}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, that was the point.
f57a9f5
to
3e4b0d2
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bunch of comments.
graphql/utils.lua
Outdated
@@ -213,4 +213,18 @@ function utils.value_in(value, array) | |||
return false | |||
end | |||
|
|||
function utils.deep_copy(orig) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is built-in table.deepcopy fit your needs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it does. Removed.
assert_gql_query_ast('gql_compile', ast) | ||
local operation_name = ast.definitions[1].name.value | ||
|
||
local operation_name |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
local operation_name | ||
for _, definition in pairs(ast.definitions) do | ||
if definition.kind == 'operation' then | ||
operation_name = definition.name.value |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Multiple operation case is okay? Maybe we need to (add and) consider 'operation_name' argument mandatory in the case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Multiple operation case is okay. You define as many as you want, but can execute only one at a time, specifying it with 'operation_name' (Details)
Answering to the second question: according to the spec, we should not make it mandatory. Anyway I should check (and probably re-write) this place to satisfy GraphQL spec.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As we discussed it verbally, it will be done in another branch.
graphql/tarantool_graphql.lua
Outdated
@@ -1223,6 +1210,15 @@ local function gql_execute(qstate, variables) | |||
operation_name) | |||
end | |||
|
|||
local function gql_execute(state, query, variables) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Proposed to use separate work for compile+execute. Maybe 'run'?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean 'separate name'. Don’t have idea why I wrote 'separate work'.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems good enough, can't think of better naming. Fxd.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you want to change external API as well? gql_wrapper:execute() -> gql_wrapper:run()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The idea was to change, but now I think that we can proceed with API like in lrexlib-pcre where match can be called for the module with an expression as a string as well as for compiled expression.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Discussed verbally. Internal functions renamed, external API left as it is.
graphql/tarantool_graphql.lua
Outdated
execute = gql_execute, | ||
start_server = start_server, | ||
stop_server = stop_server, | ||
cfg = cfg, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove it, it is in 'internal'.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed.
test/local/server.test.lua
Outdated
|
||
gql_wrapper:stop_server() | ||
|
||
-- add space formats and try default instance |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you test it in 'no_instance' test already?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In 'no_instance' I test the whole mechanism of require(graphql):do_something_cool()
Here I test the http server itself.
README.md
Outdated
local graphql = require('graphql').new({ | ||
schemas = schemas, | ||
collections = collections, | ||
accessor = accessor |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you sure it will work w/o indexes
and service_fields
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No it will not. Fxd readme.
README.md
Outdated
graphql:stop_server() | ||
|
||
-- as well you may do | ||
require('graphql').start_server() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why period here, but colon for an instance?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did not get your point. In case of require(...) we call just a function. In case of instance we want to pass this instance as a first argument.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Checked shard and http.client modules, they share your approach. So, I discard my proposal.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Discussed verbally, left as it is.
graphql/simple_config.lua
Outdated
@@ -169,6 +170,17 @@ function simple_config.get_spaces_formats() | |||
return spaces_formats | |||
end | |||
|
|||
local function remove_empty_formats(spaces_formats) | |||
local resulting_formats = utils.deep_copy(spaces_formats) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems you don't need deepcopy at all, table.copy will suffer your needs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fxd. (English remark: maybe 'serve', not 'suffer'? :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe I did went to say 'suit'… Don’t know what was with my wording in Tue.
@@ -190,7 +191,7 @@ local function gql_argument_type(avro_schema) | |||
|
|||
fields[field.name] = { | |||
name = field.name, | |||
kind = types.nonNull(gql_field_type), | |||
kind = gql_field_type, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- The field cannot be non-null here (do we need to call nullable(gql_field_type))?
- I would add a comment like 'accept any subset of an input object field as a filter'. Ok?
d2dc8ed
to
ef2b1ac
Compare
f435327
to
e33a8ef
Compare
No description provided.