Skip to content

Commit 61b2d7f

Browse files
authored
Merge pull request #37 from LiUGraphQL/query-by-key
Support for keys in API schema generation (Issue #33)
2 parents 193af8d + f9d4ff8 commit 61b2d7f

File tree

3 files changed

+70
-0
lines changed

3 files changed

+70
-0
lines changed

graphql-api-generator/generator.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,10 @@ def run(schema: GraphQLSchema, config: dict):
9696
schema = add_list_of_types(schema)
9797
schema = add_list_queries(schema)
9898

99+
if config.get('generation').get('query_by_key'):
100+
schema = add_key_input_types(schema)
101+
schema = add_key_queries(schema)
102+
99103
# add input types
100104
if config.get('generation').get('input_to_create_objects'):
101105
schema = add_input_to_create(schema)

graphql-api-generator/resources/config.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ generation:
2121
query_by_id: true
2222
query_type_filter: true
2323
query_list_of: true
24+
query_by_key: true
2425
# add input types
2526
input_to_create_objects: true
2627
input_to_update_objects: true

graphql-api-generator/utils/utils.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,71 @@ def add_input_to_create(schema: GraphQLSchema):
194194
return schema
195195

196196

197+
def _get_keys_for_type(type_: GraphQLType):
198+
keys = []
199+
if hasattr(type_, 'ast_node') and type_.ast_node is not None:
200+
directives = {directive.name.value: directive for directive in type_.ast_node.directives}
201+
if 'key' in directives:
202+
arguments = {arg.name.value: arg for arg in directives['key'].arguments}
203+
if 'fields' in arguments:
204+
keys.append([val.value for val in arguments['fields'].value.values])
205+
return keys
206+
207+
208+
def add_key_input_types(schema: GraphQLSchema):
209+
"""
210+
Add create and connect types for creating objects.
211+
:param schema:
212+
:return:
213+
"""
214+
# add create types (placeholders)
215+
make_types = ''
216+
extend_fields = ''
217+
for _type in schema.type_map.values():
218+
if not is_schema_defined_type(_type) or is_interface_type(_type):
219+
continue
220+
keys = _get_keys_for_type(_type)
221+
# TODO: Modify this when we need to handle multiple keys.
222+
if len(keys) > 0:
223+
for key in keys[:1]:
224+
make_types += f'input _KeyFor{_type.name} '
225+
extend_fields += f'\nextend input _KeyFor{_type.name} {{ '
226+
for key_field in key:
227+
if key_field not in _type.fields:
228+
raise Exception(f'Field "{key_field}" in @key directive for {_type} is not a field of {_type}!')
229+
for field_name, field in _type.fields.items():
230+
# TODO: Modify this if we need to verify that the key fields are in the object
231+
if field_name not in key:
232+
continue
233+
extend_fields += f'{field_name}: {field.type} '
234+
extend_fields += '} '
235+
schema = add_to_schema(schema, make_types)
236+
schema = add_to_schema(schema, extend_fields)
237+
return schema
238+
239+
240+
def add_key_queries(schema: GraphQLSchema):
241+
"""
242+
Add query to get object based on ID.
243+
:param schema:
244+
:return:
245+
"""
246+
# Create queries for object types
247+
make = ''
248+
for _type in schema.type_map.values():
249+
if not is_schema_defined_type(_type):
250+
continue
251+
keys = _get_keys_for_type(_type)
252+
# TODO: Handle multiple keys here, somehow.
253+
if len(keys) > 0:
254+
# for key in keys[:1]:
255+
query_name = f'{decapitalize(_type.name)}ByKey'
256+
key_type = f'_KeyFor{_type.name}'
257+
make += f'extend type Query {{ {query_name}(key:{key_type}!): {_type.name} }} '
258+
schema = add_to_schema(schema, make)
259+
return schema
260+
261+
197262
def extend_connect(schema: GraphQLSchema, _type: GraphQLType, field_type: GraphQLType, field_name: str):
198263
"""
199264
Add connect type.

0 commit comments

Comments
 (0)