Skip to content

Commit 3333210

Browse files
authored
Merge pull request #42 from LiUGraphQL/Date-and-DateTime-filters
DateTime (and Date) filters
2 parents 3fc96b4 + b10efa1 commit 3333210

File tree

4 files changed

+83
-48
lines changed

4 files changed

+83
-48
lines changed

graphql-api-generator/generator.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,6 @@ def cmd(args):
4949

5050

5151
def run(schema: GraphQLSchema, config: dict):
52-
# check if DateTime exists, or should be added
53-
if config.get('generation').get('generate_datetime') or config.get('generation').get('field_for_creation_date') or config.get('generation').get('field_for_last_update_date'):
54-
datetime_control(schema)
55-
5652
# validate
5753
if config.get('validate'):
5854
validate_names(schema, config.get('validate'))
@@ -72,30 +68,34 @@ def run(schema: GraphQLSchema, config: dict):
7268
if config.get('generation').get('field_for_id'):
7369
schema = add_id_to_types(schema)
7470

75-
# add creationDate
76-
if config.get('generation').get('field_for_creation_date'):
77-
schema = add_creation_date_to_types(schema)
78-
79-
# add lastUpdateDate
80-
if config.get('generation').get('field_for_last_update_date'):
81-
schema = add_last_update_date_to_types(schema)
71+
# check if DateTime exists, or should be added
72+
if config.get('generation').get('generate_datetime'):
73+
datetime_control(schema)
8274

8375
# add reverse edges for traversal
8476
if config.get('generation').get('reverse_edges'):
8577
schema = add_reverse_edges(schema)
8678

8779
# add edge types
8880
if config.get('generation').get('edge_types') or config.get('generation').get('create_edge_objects'):
89-
schema = add_edge_objects(schema, config.get('generation').get('field_for_creation_date'), config.get('generation').get('field_for_last_update_date'))
81+
schema = add_edge_objects(schema)
9082
if config.get('generation').get('fields_for_edge_types'):
9183
raise UnsupportedOperation('{0} is currently not supported'.format('fields_for_edge_types'))
9284

85+
# add creation date
86+
if config.get('generation').get('field_for_creation_date'):
87+
schema = add_creation_date_to_types(schema)
88+
89+
# add last update date
90+
if config.get('generation').get('field_for_last_update_date'):
91+
schema = add_last_update_date_to_types(schema)
92+
9393
# add queries
9494
if config.get('generation').get('query_by_id'):
9595
schema = add_get_queries(schema)
9696
if config.get('generation').get('query_type_filter') or config.get('generation').get('query_list_of'):
9797
schema = add_enum_filters(schema)
98-
schema = add_scalar_filters(schema)
98+
schema = add_scalar_filters(schema, config)
9999
schema = add_type_filters(schema)
100100

101101
if config.get('generation').get('query_type_filter'):
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
GraphQL-core-next==1.0.5
1+
graphql-core>=3
22
PyYAML

graphql-api-generator/resources/config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ generation:
1313
# add id field to all schema types
1414
field_for_id: true
1515
# add creation date and last update date field(s) to all schema types
16-
generate_datetime: false
16+
generate_datetime: true
1717
field_for_creation_date: true
1818
field_for_last_update_date: true
1919
# add reverse edges for traversal

graphql-api-generator/utils/utils.py

Lines changed: 68 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,16 @@ def uppercase(string: str):
1818
return string.upper()
1919

2020

21+
def is_meta_field(field):
22+
"""
23+
Returns true if a field should be recognized as a system defined meta data field.
24+
:param field:
25+
:return:
26+
"""
27+
meta_fields = ['_creationDate', '_lastUpdateDate']
28+
return field in meta_fields
29+
30+
2131
def capitalize(string: str):
2232
"""
2333
Make the first letter of string upper case.
@@ -36,14 +46,27 @@ def decapitalize(string: str):
3646
return string[0].lower() + string[1:]
3747

3848

39-
def is_schema_defined_type(_type: GraphQLType):
49+
def is_db_schema_defined_type(_type: GraphQLType):
4050
"""
41-
Returns true if a type is a schema-defined GraphQL type.
51+
Returns true if _type is a GraphQL type defined in the DB schema.
4252
:param _type:
4353
:return:
4454
"""
4555
if is_input_type(_type) or _type.name.startswith('_') or _type.name == 'Mutation' or _type.name == 'Query':
4656
return False
57+
58+
return True
59+
60+
61+
def is_schema_defined_type(_type: GraphQLType):
62+
"""
63+
Returns true if _type is a schema-defined GraphQL type.
64+
:param _type:
65+
:return:
66+
"""
67+
if is_input_type(_type) or _type.name.startswith('__') or _type.name == 'Mutation' or _type.name == 'Query':
68+
return False
69+
4770
return True
4871

4972

@@ -89,7 +112,7 @@ def add_id_to_types(schema: GraphQLSchema):
89112
"""
90113
make = ''
91114
for _type in schema.type_map.values():
92-
if not is_schema_defined_type(_type):
115+
if not is_db_schema_defined_type(_type):
93116
continue
94117
if is_interface_type(_type):
95118
make += f'extend interface {_type.name} {{ id: ID! }} '
@@ -108,6 +131,7 @@ def add_creation_date_to_types(schema: GraphQLSchema):
108131
for _type in schema.type_map.values():
109132
if not is_schema_defined_type(_type):
110133
continue
134+
111135
if is_interface_type(_type):
112136
make += f'extend interface {_type.name} {{ _creationDate: DateTime! }} '
113137
else:
@@ -168,7 +192,7 @@ def add_reverse_edges(schema: GraphQLSchema):
168192
"""
169193
make = ''
170194
for _type in schema.type_map.values():
171-
if not is_schema_defined_type(_type):
195+
if not is_db_schema_defined_type(_type):
172196
continue
173197

174198
for field_name, field_type in _type.fields.items():
@@ -200,15 +224,15 @@ def add_input_to_create(schema: GraphQLSchema):
200224
# add create types (placeholders)
201225
make = ''
202226
for _type in schema.type_map.values():
203-
if not is_schema_defined_type(_type) or is_interface_type(_type):
227+
if not is_db_schema_defined_type(_type) or is_interface_type(_type):
204228
continue
205229
make += f'input _InputToCreate{_type.name} '
206230
schema = add_to_schema(schema, make)
207231

208232
# add fields to create types
209233
make = ''
210234
for _type in schema.type_map.values():
211-
if not is_schema_defined_type(_type) or is_interface_type(_type):
235+
if not is_db_schema_defined_type(_type) or is_interface_type(_type):
212236
continue
213237
make += f'\nextend input _InputToCreate{_type.name} {{ '
214238
for field_name, field in _type.fields.items():
@@ -248,7 +272,7 @@ def add_key_input_types(schema: GraphQLSchema):
248272
make_types = ''
249273
extend_fields = ''
250274
for _type in schema.type_map.values():
251-
if not is_schema_defined_type(_type) or is_interface_type(_type):
275+
if not is_db_schema_defined_type(_type) or is_interface_type(_type):
252276
continue
253277
keys = _get_keys_for_type(_type)
254278
# TODO: Modify this when we need to handle multiple keys.
@@ -279,7 +303,7 @@ def add_key_queries(schema: GraphQLSchema):
279303
# Create queries for object types
280304
make = ''
281305
for _type in schema.type_map.values():
282-
if not is_schema_defined_type(_type):
306+
if not is_db_schema_defined_type(_type):
283307
continue
284308
keys = _get_keys_for_type(_type)
285309
# TODO: Handle multiple keys here, somehow.
@@ -329,7 +353,7 @@ def add_input_update(schema: GraphQLSchema):
329353
# Create update inputs
330354
make = ''
331355
for _type in schema.type_map.values():
332-
if not is_schema_defined_type(_type) or is_interface_type(_type):
356+
if not is_db_schema_defined_type(_type) or is_interface_type(_type):
333357
continue
334358
update_name = f'_InputToUpdate{_type.name}'
335359
make += f'input {update_name} '
@@ -338,7 +362,7 @@ def add_input_update(schema: GraphQLSchema):
338362
# Add fields to update type
339363
make = ''
340364
for _type in schema.type_map.values():
341-
if not is_schema_defined_type(_type) or is_interface_type(_type):
365+
if not is_db_schema_defined_type(_type) or is_interface_type(_type):
342366
continue
343367
for field_name, field in _type.fields.items():
344368
if field_name == 'id' or field_name[0] == '_':
@@ -368,7 +392,7 @@ def add_get_queries(schema: GraphQLSchema):
368392
# Create queries for object types
369393
make = ''
370394
for _type in schema.type_map.values():
371-
if not is_schema_defined_type(_type):
395+
if not is_db_schema_defined_type(_type):
372396
continue
373397
make += f'extend type Query {{ {decapitalize(_type.name)}(id:ID!): {_type.name} }} '
374398
schema = add_to_schema(schema, make)
@@ -383,7 +407,7 @@ def add_list_of_types(schema: GraphQLSchema):
383407
"""
384408
make = ''
385409
for _type in schema.type_map.values():
386-
if not is_schema_defined_type(_type):
410+
if not is_db_schema_defined_type(_type):
387411
continue
388412

389413
make += f'type _ListOf{_type.name}s {{ ' \
@@ -403,7 +427,7 @@ def add_list_queries(schema: GraphQLSchema):
403427
"""
404428
make = ''
405429
for _type in schema.type_map.values():
406-
if not is_schema_defined_type(_type):
430+
if not is_db_schema_defined_type(_type):
407431
continue
408432
make += f'extend type Query {{ ' \
409433
f' listOf{_type.name}s(first:Int=10, after:ID="", filter:_FilterFor{_type.name}): _ListOf{_type.name}s ' \
@@ -412,13 +436,15 @@ def add_list_queries(schema: GraphQLSchema):
412436
return schema
413437

414438

415-
def add_scalar_filters(schema: GraphQLSchema):
439+
def add_scalar_filters(schema: GraphQLSchema, config: dict):
416440
"""
417441
Add filter inputs for GrahpQL types (Hasura-style).
418442
:param schema:
419443
:return:
420444
"""
421445
make = ''
446+
manually_handled_scalars = ['Int', 'Float', 'String', 'Boolean', 'ID']
447+
422448
# Numeric
423449
scalars = ['Int', 'Float']
424450
for scalar in scalars:
@@ -471,9 +497,24 @@ def add_scalar_filters(schema: GraphQLSchema):
471497
' _neq: Boolean ' \
472498
'} '
473499

500+
# If DateTime is defined as a scalar then create filter (behaves like an integer)
501+
date_time = schema.type_map.get("DateTime")
502+
if is_scalar_type(date_time):
503+
manually_handled_scalars.append('DateTime')
504+
make += 'input _DateTimeFilter {' \
505+
' _eq: DateTime ' \
506+
' _neq: DateTime ' \
507+
' _in: [DateTime] ' \
508+
' _nin: [DateTime] ' \
509+
' _gt: DateTime ' \
510+
' _egt: DateTime ' \
511+
' _lt: DateTime ' \
512+
' _elt: DateTime ' \
513+
'} '
514+
474515
# Schema-defined scalars
475516
for scalar_name, scalar in schema.type_map.items():
476-
if not is_scalar_type(scalar) or scalar_name in ['Int', 'Float', 'String', 'Boolean', 'ID']:
517+
if not is_scalar_type(scalar) or scalar_name in manually_handled_scalars:
477518
continue
478519

479520
make += f'input _{scalar_name}Filter {{' \
@@ -496,7 +537,7 @@ def add_type_filters(schema: GraphQLSchema):
496537
"""
497538
make = ''
498539
for _type in schema.type_map.values():
499-
if not is_schema_defined_type(_type):
540+
if not is_db_schema_defined_type(_type):
500541
continue
501542

502543
make += f'input _FilterFor{_type.name} {{ ' \
@@ -505,7 +546,7 @@ def add_type_filters(schema: GraphQLSchema):
505546
f' _not: _FilterFor{_type.name} '
506547

507548
for field_name, field in _type.fields.items():
508-
if field_name[0] == '_':
549+
if field_name[0] == '_' and not is_meta_field(field_name):
509550
continue
510551

511552
# remove outer required
@@ -532,7 +573,7 @@ def add_object_type_filters(schema: GraphQLSchema):
532573
:return:
533574
"""
534575
for _type in schema.type_map.values():
535-
if not is_schema_defined_type(_type):
576+
if not is_db_schema_defined_type(_type):
536577
continue
537578

538579
for field_name, field in _type.fields.items():
@@ -560,16 +601,10 @@ def get_field_annotations(field: GraphQLField):
560601
return " ".join(annotation_fields)
561602

562603

563-
def add_edge_objects(schema: GraphQLSchema, field_for_creation_date, field_for_last_update_date):
604+
def add_edge_objects(schema: GraphQLSchema):
564605
make = ''
565-
creation_date_string = ''
566-
last_update_date_string = ''
567-
if field_for_creation_date:
568-
creation_date_string = '_creationDate: Date!'
569-
if field_for_last_update_date:
570-
last_update_date_string = '_lastUpdateDate: Date'
571606
for _type in schema.type_map.values():
572-
if not is_schema_defined_type(_type) or is_interface_type(_type):
607+
if not is_db_schema_defined_type(_type) or is_interface_type(_type):
573608
continue
574609
connected_types = schema.get_possible_types(_type) if is_interface_type(_type) else [_type]
575610
for field_name, field in _type.fields.items():
@@ -579,7 +614,7 @@ def add_edge_objects(schema: GraphQLSchema, field_for_creation_date, field_for_l
579614
for t in connected_types:
580615
edge_from = f'{capitalize(field_name)}EdgeFrom{t.name}'
581616
annotations = get_field_annotations(field)
582-
make += f'type _{edge_from} {{id:ID! source: {t.name}! target: {inner_field_type}! {creation_date_string} {last_update_date_string} {annotations}}}\n'
617+
make += f'type _{edge_from} {{id:ID! source: {t.name}! target: {inner_field_type}! {annotations}}}\n'
583618

584619
schema = add_to_schema(schema, make)
585620
return schema
@@ -588,7 +623,7 @@ def add_edge_objects(schema: GraphQLSchema, field_for_creation_date, field_for_l
588623
def add_input_to_create_edge_objects(schema: GraphQLSchema):
589624
make = ''
590625
for _type in schema.type_map.values():
591-
if not is_schema_defined_type(_type) or is_interface_type(_type):
626+
if not is_db_schema_defined_type(_type) or is_interface_type(_type):
592627
continue
593628
connected_types = schema.get_possible_types(_type) if is_interface_type(_type) else [_type]
594629
for field_name, field in _type.fields.items():
@@ -614,7 +649,7 @@ def add_input_to_create_edge_objects(schema: GraphQLSchema):
614649
def add_mutation_create_edge_objects(schema: GraphQLSchema):
615650
make = ''
616651
for _type in schema.type_map.values():
617-
if not is_schema_defined_type(_type) or is_interface_type(_type):
652+
if not is_db_schema_defined_type(_type) or is_interface_type(_type):
618653
continue
619654
connected_types = schema.get_possible_types(_type) if is_interface_type(_type) else [_type]
620655
for field_name, field in _type.fields.items():
@@ -634,7 +669,7 @@ def add_mutation_create_edge_objects(schema: GraphQLSchema):
634669
def remove_field_arguments_for_types(schema: GraphQLSchema):
635670
keep_args = ['filter']
636671
for _type in schema.type_map.values():
637-
if not is_schema_defined_type(_type):
672+
if not is_db_schema_defined_type(_type):
638673
continue
639674
for field_name, field in _type.fields.items():
640675
args = {}
@@ -674,7 +709,7 @@ def add_create_mutations(schema: GraphQLSchema):
674709
"""
675710
make = ''
676711
for _type in schema.type_map.values():
677-
if not is_schema_defined_type(_type) or is_interface_type(_type):
712+
if not is_db_schema_defined_type(_type) or is_interface_type(_type):
678713
continue
679714
create = f'create{_type.name}'
680715
input_type = f'_InputToCreate{_type.name}'
@@ -692,7 +727,7 @@ def add_update_mutations(schema: GraphQLSchema):
692727
"""
693728
make = ''
694729
for _type in schema.type_map.values():
695-
if not is_schema_defined_type(_type) or is_interface_type(_type):
730+
if not is_db_schema_defined_type(_type) or is_interface_type(_type):
696731
continue
697732
update = f'update{capitalize(_type.name)} '
698733
input_type = f'_InputToUpdate{_type.name}'
@@ -710,7 +745,7 @@ def add_delete_mutations(schema: GraphQLSchema):
710745
"""
711746
make = ''
712747
for _type in schema.type_map.values():
713-
if not is_schema_defined_type(_type):
748+
if not is_db_schema_defined_type(_type):
714749
continue
715750
delete = f'delete{_type.name}'
716751
make += f'extend type Mutation {{ {delete}(id: ID!): {_type.name} }} '

0 commit comments

Comments
 (0)