Skip to content

Commit 1f25892

Browse files
authored
Merge pull request #38 from LiUGraphQL/34-edge-creation-operations
Resolves #34
2 parents 61b2d7f + 67d30f0 commit 1f25892

File tree

3 files changed

+96
-16
lines changed

3 files changed

+96
-16
lines changed

graphql-api-generator/generator.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,8 @@ def run(schema: GraphQLSchema, config: dict):
7373
schema = add_reverse_edges(schema)
7474

7575
# add edge types
76-
if config.get('generation').get('edge_types'):
77-
raise UnsupportedOperation('{0} is currently not supported'.format('edgeTypes'))
76+
if config.get('generation').get('edge_types') or config.get('generation').get('create_edge_objects'):
77+
schema = add_edge_objects(schema)
7878
if config.get('generation').get('fields_for_edge_types'):
7979
raise UnsupportedOperation('{0} is currently not supported'.format('fields_for_edge_types'))
8080

@@ -86,9 +86,6 @@ def run(schema: GraphQLSchema, config: dict):
8686
schema = add_scalar_filters(schema)
8787
schema = add_type_filters(schema)
8888

89-
# remove field arguments for edges (should not be in the API schema)
90-
schema = remove_field_arguments_for_types(schema)
91-
9289
if config.get('generation').get('query_type_filter'):
9390
schema = add_object_type_filters(schema)
9491

@@ -108,7 +105,7 @@ def run(schema: GraphQLSchema, config: dict):
108105

109106
# add edge input types
110107
if config.get('generation').get('input_to_create_edge_objects'):
111-
raise UnsupportedOperation('{0} is currently not supported'.format('input_to_create_edge_objects'))
108+
schema = add_input_to_create_edge_objects(schema)
112109
if config.get('generation').get('input_to_update_edge_objects'):
113110
raise UnsupportedOperation('{0} is currently not supported'.format('input_to_update_edge_objects'))
114111

@@ -122,16 +119,19 @@ def run(schema: GraphQLSchema, config: dict):
122119

123120
# add edge mutations
124121
if config.get('generation').get('create_edge_objects'):
125-
raise UnsupportedOperation('{0} is currently not supported'.format('create_edge_objects'))
122+
schema = add_mutation_create_edge_objects(schema)
126123
if config.get('generation').get('update_edge_objects'):
127124
raise UnsupportedOperation('{0} is currently not supported'.format('update_edge_objects'))
128125
if config.get('generation').get('delete_edge_objects'):
129126
raise UnsupportedOperation('{0} is currently not supported'.format('delete_edge_objects'))
130127

128+
# remove field arguments for edges (should not be in the API schema)
129+
schema = remove_field_arguments_for_types(schema)
130+
131131
return schema
132132

133133

134-
def validate_names(schema:GraphQLSchema, validate):
134+
def validate_names(schema: GraphQLSchema, validate):
135135
# types and interfaces
136136
if validate.get('type_names'):
137137
# type names

graphql-api-generator/resources/config.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,14 @@ generation:
2525
# add input types
2626
input_to_create_objects: true
2727
input_to_update_objects: true
28-
# add edge input types (not supported)
29-
input_to_create_edge_objects: false
28+
# add edge input types (update not supported)
29+
input_to_create_edge_objects: true
3030
input_to_update_edge_objects: false
3131
# add mutations
3232
create_objects: true
3333
update_objects: true
34-
delete_objects: true
35-
# add edge mutations (not supported)
36-
create_edge_objects: false
34+
delete_objects: false
35+
# add edge mutations (update and delete not supported)
36+
create_edge_objects: true
3737
update_edge_objects: false
3838
delete_edge_objects: false

graphql-api-generator/utils/utils.py

Lines changed: 83 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,7 @@ def add_reverse_edges(schema: GraphQLSchema):
138138
continue
139139

140140
for field_name, field_type in _type.fields.items():
141-
inner_field_type = get_named_type(field_type.type)
142-
if is_scalar_type(inner_field_type) or is_enum_type(inner_field_type):
141+
if is_enum_or_scalar(get_named_type(field_type.type)):
143142
continue
144143

145144
# Reverse edge
@@ -516,12 +515,93 @@ def add_object_type_filters(schema: GraphQLSchema):
516515
return schema
517516

518517

518+
def get_field_annotations(field: GraphQLField):
519+
annotation_fields = []
520+
for arg, arg_type in field.args.items():
521+
if arg == 'filter':
522+
continue
523+
if not is_enum_or_scalar(get_named_type(arg_type.type)):
524+
raise Exception("Input object fields are not supported.")
525+
annotation_fields.append(f'{arg}: {arg_type.type}')
526+
return " ".join(annotation_fields)
527+
528+
529+
def add_edge_objects(schema: GraphQLSchema):
530+
make = ''
531+
for _type in schema.type_map.values():
532+
if not is_schema_defined_type(_type) or is_interface_type(_type):
533+
continue
534+
connected_types = schema.get_possible_types(_type) if is_interface_type(_type) else [_type]
535+
for field_name, field in _type.fields.items():
536+
inner_field_type = get_named_type(field.type)
537+
if field_name.startswith('_') or is_enum_or_scalar(inner_field_type):
538+
continue
539+
for t in connected_types:
540+
edge_from = f'{capitalize(field_name)}EdgeFrom{t.name}'
541+
annotations = get_field_annotations(field)
542+
make += f'type _{edge_from} {{id:ID! source: {t.name}! target: {inner_field_type}! {annotations}}}\n'
543+
544+
schema = add_to_schema(schema, make)
545+
return schema
546+
547+
548+
def add_input_to_create_edge_objects(schema: GraphQLSchema):
549+
make = ''
550+
for _type in schema.type_map.values():
551+
if not is_schema_defined_type(_type) or is_interface_type(_type):
552+
continue
553+
connected_types = schema.get_possible_types(_type) if is_interface_type(_type) else [_type]
554+
for field_name, field in _type.fields.items():
555+
inner_field_type = get_named_type(field.type)
556+
if field_name.startswith('_') or is_enum_or_scalar(inner_field_type):
557+
continue
558+
for t in connected_types:
559+
edge_from = f'{capitalize(field_name)}EdgeFrom{t.name}'
560+
edge_input = f'_InputToCreate{edge_from}'
561+
annotate_input = f'_InputToAnnotate{edge_from}'
562+
annotations = get_field_annotations(field)
563+
564+
if len(annotations) > 0:
565+
make += f'input {edge_input} {{sourceID: ID! targetID: ID! annotations: {annotate_input} }}\n'
566+
make += f'input {annotate_input}{{{annotations}}}\n'
567+
else:
568+
make += f'input {edge_input} {{sourceID: ID! targetID: ID!}}\n'
569+
570+
schema = add_to_schema(schema, make)
571+
return schema
572+
573+
574+
def add_mutation_create_edge_objects(schema: GraphQLSchema):
575+
make = ''
576+
for _type in schema.type_map.values():
577+
if not is_schema_defined_type(_type) or is_interface_type(_type):
578+
continue
579+
connected_types = schema.get_possible_types(_type) if is_interface_type(_type) else [_type]
580+
for field_name, field in _type.fields.items():
581+
inner_field_type = get_named_type(field.type)
582+
if field_name.startswith('_') or is_enum_or_scalar(inner_field_type):
583+
continue
584+
for t in connected_types:
585+
edge_from = f'{capitalize(field_name)}EdgeFrom{t.name}'
586+
edge_create = f'create{edge_from}'
587+
edge_input = f'_InputToCreate{edge_from}'
588+
make += f'extend type Mutation{{{edge_create}(data: {edge_input}):_{edge_from}}}\n'
589+
590+
schema = add_to_schema(schema, make)
591+
return schema
592+
593+
519594
def remove_field_arguments_for_types(schema: GraphQLSchema):
595+
keep_args = ['filter']
520596
for _type in schema.type_map.values():
521597
if not is_schema_defined_type(_type):
522598
continue
523599
for field_name, field in _type.fields.items():
524-
field.args = {}
600+
args = {}
601+
for arg in field.args:
602+
if arg in keep_args:
603+
args[arg] = field.args[arg]
604+
field.args = args
525605
return schema
526606

527607

0 commit comments

Comments
 (0)