agoo 2.11.7 → 2.12.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of agoo might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 06273c8f4d9d00c382ed4d0abec44bc54b24a1063cb7cc15796137153a169206
4
- data.tar.gz: ba1e9f93e1cbd39e2777ce5a0d9e61498f5718c3742ad001d28490eec848e838
3
+ metadata.gz: ad6f1d492f68755c2012b61062a79fe3351a1b80546838d19eb4315789f4585c
4
+ data.tar.gz: 6a1a949bdf6fb76d1228e9e7e61ded57d76ca414a21529eec46ae1275e624277
5
5
  SHA512:
6
- metadata.gz: ccf05a2fed955f9e44461a6557c7d3232280c0fd316d523bbbb97cfc9942ef8407a4f31e92b4ba888d3d895578d85753d12e2966aeb08d8725a4de6f5c74eb2f
7
- data.tar.gz: 3af05ec64f0af3ab57bbb0c95652d8050ca6c73d0cf39777cfeff8e5c0ac2cc71ddc783b4d0fecc5d675e865616fe8dee7c145268359e51e5bc7864f00428733
6
+ metadata.gz: b43da3e33ef225b675164ad4793b4304bc42db3c0a0803b84584250e58713d4026b10e9a450b3de8bbe18814a3ce102438fd1448658919e5a345fafe8583bc64
7
+ data.tar.gz: fbe407798233527d8ce736bac219224b00714ca8a902b5110a5c15fd2f88a2962d04fdb6945517377c1cebdde623c2d7a0162fd414c2f17dfdb23ac01dc86779
@@ -2,6 +2,20 @@
2
2
 
3
3
  All changes to the Agoo gem are documented here. Releases follow semantic versioning.
4
4
 
5
+ ## [2.12.0] - 2020-01-19
6
+
7
+ Request GraphQL access and GraphiQL support
8
+
9
+ ### Added
10
+
11
+ - Optional addition of request information is now available in GraphQL resolve functions.
12
+
13
+ - Headers for GraphQL responses can now be set.
14
+
15
+ - Fixed incorrect values in introspection responses.
16
+
17
+ - Fixed JSON parser bug with null, true, and false.
18
+
5
19
  ## [2.11.7] - 2020-01-02
6
20
 
7
21
  Ruby 2.7.0 cleanup
@@ -36,8 +36,9 @@ static const char query_str[] = "query";
36
36
  static const char subscription_str[] = "subscription";
37
37
  static const char variables_str[] = "variables";
38
38
 
39
-
40
39
  gqlValue (*gql_doc_eval_func)(agooErr err, gqlDoc doc) = NULL;
40
+ agooText (*gql_build_headers)(agooErr err, agooReq req, agooText headers) = NULL;
41
+ agooText gql_headers = NULL;
41
42
 
42
43
  static void
43
44
  err_resp(agooRes res, agooErr err, int status) {
@@ -93,25 +94,74 @@ value_resp(agooReq req, gqlValue result, int status, int indent) {
93
94
  break;
94
95
  default:
95
96
  agoo_log_cat(&agoo_error_cat, "Did not expect an HTTP status of %d.", status);
96
- return;
97
+ agoo_err_set(&err, AGOO_ERR_EVAL, "Did not expect an HTTP status of %d.", status);
98
+ goto FAILED;
97
99
  }
98
100
  agoo_res_message_push(res, text);
99
101
  return;
100
102
  }
101
103
  if (AGOO_ERR_OK != gql_object_set(&err, msg, "data", result)) {
102
- err_resp(res, &err, 500);
103
- gql_value_destroy(result);
104
- return;
104
+ goto FAILED;
105
105
  }
106
106
  text = gql_value_json(text, msg, indent, 0);
107
107
  gql_value_destroy(msg); // also destroys result
108
+ result = NULL;
108
109
 
109
110
  cnt = snprintf(buf, sizeof(buf), "HTTP/1.1 %d %s\r\nContent-Type: application/json\r\nContent-Length: %ld\r\n\r\n",
110
111
  status, agoo_http_code_message(status), text->len);
111
- if (NULL == (text = agoo_text_prepend(text, buf, cnt))) {
112
- agoo_log_cat(&agoo_error_cat, "Failed to allocate memory for a response.");
112
+ if (NULL != gql_headers || NULL != gql_build_headers) {
113
+ agooText headers = agoo_text_allocate(4094);
114
+
115
+ headers = agoo_text_append(headers, buf, cnt - 2);
116
+ if (NULL == headers) {
117
+ agoo_log_cat(&agoo_error_cat, "Failed to allocate memory for a response.");
118
+ return;
119
+ }
120
+ if (NULL != gql_headers) {
121
+ headers = agoo_text_append(headers, gql_headers->text, (int)gql_headers->len);
122
+ } else {
123
+ headers = gql_build_headers(&err, req, headers);
124
+ }
125
+ headers = agoo_text_append(headers, "\r\n", 2);
126
+ if (NULL == headers) {
127
+ agoo_log_cat(&agoo_error_cat, "Failed to allocate memory for a response.");
128
+ return;
129
+ }
130
+ if (NULL == (text = agoo_text_prepend(text, headers->text, (int)headers->len))) {
131
+ agoo_log_cat(&agoo_error_cat, "Failed to allocate memory for a response.");
132
+ agoo_text_release(headers);
133
+ return;
134
+ }
135
+ agoo_text_release(headers);
136
+ } else {
137
+ if (NULL == (text = agoo_text_prepend(text, buf, cnt))) {
138
+ agoo_log_cat(&agoo_error_cat, "Failed to allocate memory for a response.");
139
+ return;
140
+ }
113
141
  }
114
142
  agoo_res_message_push(res, text);
143
+
144
+ return;
145
+
146
+ FAILED:
147
+ err_resp(res, &err, 500);
148
+ if (NULL != result) {
149
+ gql_value_destroy(result);
150
+ }
151
+ return;
152
+ }
153
+
154
+ agooText
155
+ gql_add_header(agooErr err, agooText headers, const char *key, const char *value) {
156
+ headers = agoo_text_append(headers, key, -1);
157
+ headers = agoo_text_append(headers, ": ", 2);
158
+ headers = agoo_text_append(headers, value, -1);
159
+ headers = agoo_text_append(headers, "\r\n", 2);
160
+
161
+ if (NULL == headers) {
162
+ AGOO_ERR_MEM(err, "headers");
163
+ }
164
+ return headers;
115
165
  }
116
166
 
117
167
  gqlValue
@@ -416,6 +466,7 @@ gql_eval_get_hook(agooReq req) {
416
466
  return;
417
467
  }
418
468
  set_doc_op(doc, op_name, oplen);
469
+ doc->req = req;
419
470
 
420
471
  if (NULL == gql_doc_eval_func) {
421
472
  result = gql_doc_eval(&err, doc);
@@ -488,8 +539,6 @@ eval_post(agooErr err, agooReq req) {
488
539
  gqlValue result = NULL;
489
540
  gqlValue j = NULL;
490
541
 
491
- // TBD handle query parameter and concatenate with JSON body variables if present
492
-
493
542
  op_name = agoo_req_query_value(req, operation_name_str, sizeof(operation_name_str) - 1, &oplen);
494
543
  var_json = agoo_req_query_value(req, variables_str, sizeof(variables_str) - 1, &vlen);
495
544
 
@@ -532,19 +581,24 @@ eval_post(agooErr err, agooReq req) {
532
581
  } else if (0 == strcmp("variables", m->key)) {
533
582
  gqlLink link;
534
583
 
535
- if (GQL_SCALAR_OBJECT != m->value->type->scalar_kind) {
536
- agoo_err_set(err, AGOO_ERR_EVAL, "expected variables to be an object.");
537
- goto DONE;
538
- }
539
- for (link = m->value->members; NULL != link; link = link->next) {
540
- gqlVar v = gql_op_var_create(err, link->key, link->value->type, link->value);
584
+ switch (m->value->type->scalar_kind) {
585
+ case GQL_SCALAR_OBJECT:
586
+ for (link = m->value->members; NULL != link; link = link->next) {
587
+ gqlVar v = gql_op_var_create(err, link->key, link->value->type, link->value);
541
588
 
542
- link->value = NULL;
543
- if (NULL == v) {
544
- goto DONE;
589
+ link->value = NULL;
590
+ if (NULL == v) {
591
+ goto DONE;
592
+ }
593
+ v->next = vars;
594
+ vars = v;
545
595
  }
546
- v->next = vars;
547
- vars = v;
596
+ break;
597
+ case GQL_SCALAR_NULL:
598
+ break;
599
+ default:
600
+ agoo_err_set(err, AGOO_ERR_EVAL, "expected variables to be an object or null.");
601
+ goto DONE;
548
602
  }
549
603
  }
550
604
  }
@@ -559,6 +613,7 @@ eval_post(agooErr err, agooReq req) {
559
613
  return NULL;
560
614
  }
561
615
  set_doc_op(doc, op_name, oplen);
616
+ doc->req = req;
562
617
 
563
618
  if (NULL == gql_doc_eval_func) {
564
619
  result = gql_doc_eval(err, doc);
@@ -569,7 +624,9 @@ eval_post(agooErr err, agooReq req) {
569
624
  result = NULL;
570
625
  }
571
626
  DONE:
572
- gql_doc_destroy(doc);
627
+ if (NULL != doc) {
628
+ gql_doc_destroy(doc);
629
+ }
573
630
  gql_value_destroy(j);
574
631
 
575
632
  return result;
@@ -595,6 +652,13 @@ gql_eval_post_hook(agooReq req) {
595
652
  }
596
653
  }
597
654
 
655
+ void
656
+ gql_eval_options_hook(agooReq req) {
657
+ struct _agooErr err = AGOO_ERR_INIT;
658
+
659
+ value_resp(req, gql_object_create(&err), 200, 0);
660
+ }
661
+
598
662
  gqlValue
599
663
  gql_get_arg_value(gqlKeyVal args, const char *key) {
600
664
  gqlValue value = NULL;
@@ -15,6 +15,8 @@ typedef struct _gqlKeyVal {
15
15
  struct _gqlValue *value;
16
16
  } *gqlKeyVal;
17
17
 
18
+ struct _agooReq;
19
+ struct _agooText;
18
20
  struct _gqlDoc;
19
21
  struct _gqlField;
20
22
  struct _gqlSel;
@@ -48,4 +50,8 @@ extern gqlRef (*gql_root_op)(const char *op);
48
50
 
49
51
  extern struct _gqlValue* (*gql_doc_eval_func)(agooErr err, struct _gqlDoc *doc);
50
52
 
53
+ extern struct _agooText* (*gql_build_headers)(agooErr err, struct _agooReq *req, struct _agooText *headers);
54
+ extern struct _agooText* gql_add_header(agooErr err, struct _agooText *headers, const char *key, const char *value);
55
+ extern struct _agooText* gql_headers;
56
+
51
57
  #endif // AGOO_GQLEVAL_H
@@ -21,22 +21,30 @@ static int
21
21
  create_schema_type(agooErr err) {
22
22
  gqlType type;
23
23
  gqlType type_type;
24
- gqlType type_list;
24
+ gqlType type_nn;
25
+ gqlType type_nn_list;
26
+ gqlType type_nn_list_nn;
25
27
  gqlType dir_type;
26
- gqlType dir_list;
28
+ gqlType dir_nn;
29
+ gqlType dir_nn_list;
30
+ gqlType dir_nn_list_nn;
27
31
 
28
32
  if (NULL == (type = gql_type_create(err, "__Schema", NULL, 0, NULL)) ||
29
33
 
30
34
  NULL == (type_type = gql_assure_type(err, "__Type")) ||
31
- NULL == (type_list = gql_assure_list(err, type_type, true)) ||
35
+ NULL == (type_nn = gql_assure_nonnull(err, type_type)) ||
36
+ NULL == (type_nn_list = gql_assure_list(err, type_nn)) ||
37
+ NULL == (type_nn_list_nn = gql_assure_nonnull(err, type_nn_list)) ||
32
38
  NULL == (dir_type = gql_assure_type(err, "__Directive")) ||
33
- NULL == (dir_list = gql_assure_list(err, dir_type, true)) ||
39
+ NULL == (dir_nn = gql_assure_nonnull(err, dir_type)) ||
40
+ NULL == (dir_nn_list = gql_assure_list(err, dir_nn)) ||
41
+ NULL == (dir_nn_list_nn = gql_assure_nonnull(err, dir_nn_list)) ||
34
42
 
35
- NULL == gql_type_field(err, type, "types", type_list, NULL, NULL, 0, true) ||
36
- NULL == gql_type_field(err, type, "queryType", type_type, NULL, NULL, 0, true) ||
37
- NULL == gql_type_field(err, type, "mutationType", type_type, NULL, NULL, 0, false) ||
38
- NULL == gql_type_field(err, type, "subscriptionType", type_type, NULL, NULL, 0, false) ||
39
- NULL == gql_type_field(err, type, "directives", dir_list, NULL, NULL, 0, true)) {
43
+ NULL == gql_type_field(err, type, "types", type_nn_list_nn, NULL, NULL, 0) ||
44
+ NULL == gql_type_field(err, type, "queryType", type_nn, NULL, NULL, 0) ||
45
+ NULL == gql_type_field(err, type, "mutationType", type_type, NULL, NULL, 0) ||
46
+ NULL == gql_type_field(err, type, "subscriptionType", type_type, NULL, NULL, 0) ||
47
+ NULL == gql_type_field(err, type, "directives", dir_nn_list_nn, NULL, NULL, 0)) {
40
48
 
41
49
  return err->code;
42
50
  }
@@ -63,34 +71,44 @@ create_type_type(agooErr err) {
63
71
  gqlField enum_values = NULL;
64
72
  gqlValue dv;
65
73
  gqlType kind_type;
66
- gqlType type_list;
74
+ gqlType kind_nn;
75
+ gqlType type_nn;
76
+ gqlType type_nn_list;
67
77
  gqlType field_type;
78
+ gqlType field_nn;
68
79
  gqlType field_list;
69
80
  gqlType enum_type;
70
- gqlType enum_list;
81
+ gqlType enum_nn;
82
+ gqlType enum_nn_list;
71
83
  gqlType input_type;
72
- gqlType input_list;
84
+ gqlType input_nn;
85
+ gqlType input_nn_list;
73
86
 
74
87
  if (NULL == (type = gql_type_create(err, "__Type", NULL, 0, NULL)) ||
75
88
 
76
- NULL == (type_list = gql_assure_list(err, type, true)) ||
89
+ NULL == (type_nn = gql_assure_nonnull(err, type)) ||
90
+ NULL == (type_nn_list = gql_assure_list(err, type_nn)) ||
77
91
  NULL == (field_type = gql_assure_type(err, "__Field")) ||
78
- NULL == (field_list = gql_assure_list(err, field_type, true)) ||
92
+ NULL == (field_nn = gql_assure_nonnull(err, field_type)) ||
93
+ NULL == (field_list = gql_assure_list(err, field_nn)) ||
79
94
  NULL == (kind_type = gql_assure_type(err, "__TypeKind")) ||
95
+ NULL == (kind_nn = gql_assure_nonnull(err, kind_type)) ||
80
96
  NULL == (enum_type = gql_assure_type(err, "__EnumValue")) ||
81
- NULL == (enum_list = gql_assure_list(err, enum_type, true)) ||
97
+ NULL == (enum_nn = gql_assure_nonnull(err, enum_type)) ||
98
+ NULL == (enum_nn_list = gql_assure_list(err, enum_nn)) ||
82
99
  NULL == (input_type = gql_assure_type(err, "__InputValue")) ||
83
- NULL == (input_list = gql_assure_list(err, input_type, true)) ||
84
-
85
- NULL == gql_type_field(err, type, "kind", kind_type, NULL, NULL, 0, true) ||
86
- NULL == gql_type_field(err, type, "name", &gql_string_type, NULL, NULL, 0, false) ||
87
- NULL == gql_type_field(err, type, "description", &gql_string_type, NULL, NULL, 0, false) ||
88
- NULL == (fields = gql_type_field(err, type, "fields", field_list, NULL, NULL, 0, false)) ||
89
- NULL == gql_type_field(err, type, "interfaces", type_list, NULL, NULL, 0, false) ||
90
- NULL == gql_type_field(err, type, "possibleTypes", type_list, NULL, NULL, 0, false) ||
91
- NULL == (enum_values = gql_type_field(err, type, "enumValues", enum_list, NULL, NULL, 0, false)) ||
92
- NULL == gql_type_field(err, type, "inputFields", input_list, NULL, NULL, 0, false) ||
93
- NULL == gql_type_field(err, type, "ofType", type, NULL, NULL, 0, false)) {
100
+ NULL == (input_nn = gql_assure_nonnull(err, input_type)) ||
101
+ NULL == (input_nn_list = gql_assure_list(err, input_nn)) ||
102
+
103
+ NULL == gql_type_field(err, type, "kind", kind_nn, NULL, NULL, 0) ||
104
+ NULL == gql_type_field(err, type, "name", &gql_string_type, NULL, NULL, 0) ||
105
+ NULL == gql_type_field(err, type, "description", &gql_string_type, NULL, NULL, 0) ||
106
+ NULL == (fields = gql_type_field(err, type, "fields", field_list, NULL, NULL, 0)) ||
107
+ NULL == gql_type_field(err, type, "interfaces", type_nn_list, NULL, NULL, 0) ||
108
+ NULL == gql_type_field(err, type, "possibleTypes", type_nn_list, NULL, NULL, 0) ||
109
+ NULL == (enum_values = gql_type_field(err, type, "enumValues", enum_nn_list, NULL, NULL, 0)) ||
110
+ NULL == gql_type_field(err, type, "inputFields", input_nn_list, NULL, NULL, 0) ||
111
+ NULL == gql_type_field(err, type, "ofType", type, NULL, NULL, 0)) {
94
112
 
95
113
  return err->code;
96
114
  }
@@ -98,9 +116,9 @@ create_type_type(agooErr err) {
98
116
 
99
117
  if (NULL == (dv = gql_bool_create(err, false)) ||
100
118
 
101
- NULL == gql_field_arg(err, fields, "includeDeprecated", &gql_bool_type, NULL, 0, dv, false) ||
119
+ NULL == gql_field_arg(err, fields, "includeDeprecated", &gql_bool_type, NULL, 0, dv) ||
102
120
  NULL == (dv = gql_bool_create(err, false)) ||
103
- NULL == gql_field_arg(err, enum_values, "includeDeprecated", &gql_bool_type, NULL, 0, dv, false)) {
121
+ NULL == gql_field_arg(err, enum_values, "includeDeprecated", &gql_bool_type, NULL, 0, dv)) {
104
122
 
105
123
  return err->code;
106
124
  }
@@ -148,21 +166,31 @@ static int
148
166
  create_field_type(agooErr err) {
149
167
  gqlType type;
150
168
  gqlType type_type;
169
+ gqlType type_nn;
151
170
  gqlType input_type;
152
- gqlType input_list;
171
+ gqlType input_nn;
172
+ gqlType input_nn_list;
173
+ gqlType input_nn_list_nn;
174
+ gqlType string_nn;
175
+ gqlType boolean_nn;
153
176
 
154
177
  if (NULL == (type = gql_type_create(err, "__Field", NULL, 0, NULL)) ||
155
178
 
179
+ NULL == (string_nn = gql_assure_nonnull(err, &gql_string_type)) ||
180
+ NULL == (boolean_nn = gql_assure_nonnull(err, &gql_bool_type)) ||
156
181
  NULL == (type_type = gql_assure_type(err, "__Type")) ||
182
+ NULL == (type_nn = gql_assure_nonnull(err, type_type)) ||
157
183
  NULL == (input_type = gql_assure_type(err, "__InputValue")) ||
158
- NULL == (input_list = gql_assure_list(err, input_type, true)) ||
184
+ NULL == (input_nn = gql_assure_nonnull(err, input_type)) ||
185
+ NULL == (input_nn_list = gql_assure_list(err, input_nn)) ||
186
+ NULL == (input_nn_list_nn = gql_assure_nonnull(err, input_nn_list)) ||
159
187
 
160
- NULL == gql_type_field(err, type, "name", &gql_string_type, NULL, NULL, 0, true) ||
161
- NULL == gql_type_field(err, type, "description", &gql_string_type, NULL, NULL, 0, false) ||
162
- NULL == gql_type_field(err, type, "args", input_list, NULL, NULL, 0, true) ||
163
- NULL == gql_type_field(err, type, "type", type_type, NULL, NULL, 0, true) ||
164
- NULL == gql_type_field(err, type, "isDeprecated", &gql_bool_type, NULL, NULL, 0, true) ||
165
- NULL == gql_type_field(err, type, "deprecationReason", &gql_string_type, NULL, NULL, 0, false)) {
188
+ NULL == gql_type_field(err, type, "name", string_nn, NULL, NULL, 0) ||
189
+ NULL == gql_type_field(err, type, "description", &gql_string_type, NULL, NULL, 0) ||
190
+ NULL == gql_type_field(err, type, "args", input_nn_list_nn, NULL, NULL, 0) ||
191
+ NULL == gql_type_field(err, type, "type", type_nn, NULL, NULL, 0) ||
192
+ NULL == gql_type_field(err, type, "isDeprecated", boolean_nn, NULL, NULL, 0) ||
193
+ NULL == gql_type_field(err, type, "deprecationReason", &gql_string_type, NULL, NULL, 0)) {
166
194
 
167
195
  return err->code;
168
196
  }
@@ -181,15 +209,19 @@ static int
181
209
  create_input_type(agooErr err) {
182
210
  gqlType type;
183
211
  gqlType type_type;
212
+ gqlType type_nn;
213
+ gqlType string_nn;
184
214
 
185
215
  if (NULL == (type = gql_type_create(err, "__InputValue", NULL, 0, NULL)) ||
186
216
 
217
+ NULL == (string_nn = gql_assure_nonnull(err, &gql_string_type)) ||
187
218
  NULL == (type_type = gql_assure_type(err, "__Type")) ||
219
+ NULL == (type_nn = gql_assure_nonnull(err, type_type)) ||
188
220
 
189
- NULL == gql_type_field(err, type, "name", &gql_string_type, NULL, NULL, 0, true) ||
190
- NULL == gql_type_field(err, type, "description", &gql_string_type, NULL, NULL, 0, false) ||
191
- NULL == gql_type_field(err, type, "type", type_type, NULL, NULL, 0, true) ||
192
- NULL == gql_type_field(err, type, "defaultValue", &gql_string_type, NULL, NULL, 0, false)) {
221
+ NULL == gql_type_field(err, type, "name", string_nn, NULL, NULL, 0) ||
222
+ NULL == gql_type_field(err, type, "description", &gql_string_type, NULL, NULL, 0) ||
223
+ NULL == gql_type_field(err, type, "type", type_nn, NULL, NULL, 0) ||
224
+ NULL == gql_type_field(err, type, "defaultValue", &gql_string_type, NULL, NULL, 0)) {
193
225
 
194
226
  return err->code;
195
227
  }
@@ -207,12 +239,18 @@ create_input_type(agooErr err) {
207
239
  static int
208
240
  create_enum_type(agooErr err) {
209
241
  gqlType type;
242
+ gqlType string_nn;
243
+ gqlType boolean_nn;
210
244
 
211
245
  if (NULL == (type = gql_type_create(err, "__EnumValue", NULL, 0, NULL)) ||
212
- NULL == gql_type_field(err, type, "name", &gql_string_type, NULL, NULL, 0, true) ||
213
- NULL == gql_type_field(err, type, "description", &gql_string_type, NULL, NULL, 0, false) ||
214
- NULL == gql_type_field(err, type, "isDeprecated", &gql_bool_type, NULL, NULL, 0, true) ||
215
- NULL == gql_type_field(err, type, "deprecationReason", &gql_string_type, NULL, NULL, 0, false)) {
246
+
247
+ NULL == (string_nn = gql_assure_nonnull(err, &gql_string_type)) ||
248
+ NULL == (boolean_nn = gql_assure_nonnull(err, &gql_bool_type)) ||
249
+
250
+ NULL == gql_type_field(err, type, "name", string_nn, NULL, NULL, 0) ||
251
+ NULL == gql_type_field(err, type, "description", &gql_string_type, NULL, NULL, 0) ||
252
+ NULL == gql_type_field(err, type, "isDeprecated", boolean_nn, NULL, NULL, 0) ||
253
+ NULL == gql_type_field(err, type, "deprecationReason", &gql_string_type, NULL, NULL, 0)) {
216
254
 
217
255
  return err->code;
218
256
  }
@@ -231,21 +269,31 @@ static int
231
269
  create_directive_type(agooErr err) {
232
270
  gqlType type;
233
271
  gqlType input_type;
234
- gqlType input_list;
272
+ gqlType input_nn;
273
+ gqlType input_nn_list;
274
+ gqlType input_nn_list_nn;
235
275
  gqlType loc_type;
236
- gqlType loc_list;
276
+ gqlType loc_nn;
277
+ gqlType loc_nn_list;
278
+ gqlType loc_nn_list_nn;
279
+ gqlType string_nn;
237
280
 
238
281
  if (NULL == (type = gql_type_create(err, "__Directive", NULL, 0, NULL)) ||
239
282
 
283
+ NULL == (string_nn = gql_assure_nonnull(err, &gql_string_type)) ||
240
284
  NULL == (input_type = gql_assure_type(err, "__InputValue")) ||
241
- NULL == (input_list = gql_assure_list(err, input_type, true)) ||
285
+ NULL == (input_nn = gql_assure_nonnull(err, input_type)) ||
286
+ NULL == (input_nn_list = gql_assure_list(err, input_nn)) ||
287
+ NULL == (input_nn_list_nn = gql_assure_nonnull(err, input_nn_list)) ||
242
288
  NULL == (loc_type = gql_assure_type(err, "__DirectiveLocation")) ||
243
- NULL == (loc_list = gql_assure_list(err, loc_type, true)) ||
289
+ NULL == (loc_nn = gql_assure_nonnull(err, loc_type)) ||
290
+ NULL == (loc_nn_list = gql_assure_list(err, loc_nn)) ||
291
+ NULL == (loc_nn_list_nn = gql_assure_nonnull(err, loc_nn_list)) ||
244
292
 
245
- NULL == gql_type_field(err, type, "name", &gql_string_type, NULL, NULL, 0, true) ||
246
- NULL == gql_type_field(err, type, "description", &gql_string_type, NULL, NULL, 0, false) ||
247
- NULL == gql_type_field(err, type, "locations", loc_list, NULL, NULL, 0, true) ||
248
- NULL == gql_type_field(err, type, "args", input_list, NULL, NULL, 0, true)) {
293
+ NULL == gql_type_field(err, type, "name", string_nn, NULL, NULL, 0) ||
294
+ NULL == gql_type_field(err, type, "description", &gql_string_type, NULL, NULL, 0) ||
295
+ NULL == gql_type_field(err, type, "locations", loc_nn_list_nn, NULL, NULL, 0) ||
296
+ NULL == gql_type_field(err, type, "args", input_nn_list_nn, NULL, NULL, 0)) {
249
297
 
250
298
  return err->code;
251
299
  }
@@ -294,15 +342,18 @@ create_directive_location_type(agooErr err) {
294
342
  static int
295
343
  create_dir_skip(agooErr err) {
296
344
  gqlDir dir = gql_directive_create(err, "skip", NULL, 0);
345
+ gqlType boolean_nn;
297
346
 
298
347
  if (NULL == dir) {
299
348
  return err->code;
300
349
  }
301
350
  dir->core = true;
302
- if (AGOO_ERR_OK != gql_directive_on(err, dir, "FIELD", -1) ||
351
+ if (NULL == (boolean_nn = gql_assure_nonnull(err, &gql_bool_type)) ||
352
+
353
+ AGOO_ERR_OK != gql_directive_on(err, dir, "FIELD", -1) ||
303
354
  AGOO_ERR_OK != gql_directive_on(err, dir, "FRAGMENT_SPREAD", -1) ||
304
355
  AGOO_ERR_OK != gql_directive_on(err, dir, "INLINE_FRAGMENT", -1) ||
305
- NULL == gql_dir_arg(err, dir, "if", &gql_bool_type, NULL, -1, NULL, true)) {
356
+ NULL == gql_dir_arg(err, dir, "if", boolean_nn, NULL, -1, NULL)) {
306
357
 
307
358
  return err->code;
308
359
  }
@@ -312,15 +363,18 @@ create_dir_skip(agooErr err) {
312
363
  static int
313
364
  create_dir_include(agooErr err) {
314
365
  gqlDir dir = gql_directive_create(err, "include", NULL, 0);
366
+ gqlType boolean_nn;
315
367
 
316
368
  if (NULL == dir) {
317
369
  return err->code;
318
370
  }
319
371
  dir->core = true;
320
- if (AGOO_ERR_OK != gql_directive_on(err, dir, "FIELD", -1) ||
372
+ if (NULL == (boolean_nn = gql_assure_nonnull(err, &gql_bool_type)) ||
373
+
374
+ AGOO_ERR_OK != gql_directive_on(err, dir, "FIELD", -1) ||
321
375
  AGOO_ERR_OK != gql_directive_on(err, dir, "FRAGMENT_SPREAD", -1) ||
322
376
  AGOO_ERR_OK != gql_directive_on(err, dir, "INLINE_FRAGMENT", -1) ||
323
- NULL == gql_dir_arg(err, dir, "if", &gql_bool_type, NULL, 0, NULL, true)) {
377
+ NULL == gql_dir_arg(err, dir, "if", boolean_nn, NULL, 0, NULL)) {
324
378
 
325
379
  return err->code;
326
380
  }
@@ -339,7 +393,7 @@ create_dir_deprecated(agooErr err) {
339
393
  if (AGOO_ERR_OK != gql_directive_on(err, dir, "FIELD_DEFINITION", -1) ||
340
394
  AGOO_ERR_OK != gql_directive_on(err, dir, "ENUM_VALUE", -1) ||
341
395
  NULL == (dv = gql_string_create(err, "No longer supported", -1)) ||
342
- NULL == gql_dir_arg(err, dir, "reason", &gql_string_type, NULL, -1, dv, false)) {
396
+ NULL == gql_dir_arg(err, dir, "reason", &gql_string_type, NULL, -1, dv)) {
343
397
 
344
398
  return err->code;
345
399
  }
@@ -356,9 +410,9 @@ gql_intro_init(agooErr err) {
356
410
  AGOO_ERR_OK != create_directive_location_type(err) ||
357
411
  AGOO_ERR_OK != create_directive_type(err) ||
358
412
  AGOO_ERR_OK != create_schema_type(err) ||
359
- AGOO_ERR_OK != create_dir_deprecated(err) ||
413
+ AGOO_ERR_OK != create_dir_skip(err) ||
360
414
  AGOO_ERR_OK != create_dir_include(err) ||
361
- AGOO_ERR_OK != create_dir_skip(err)) {
415
+ AGOO_ERR_OK != create_dir_deprecated(err)) {
362
416
 
363
417
  return err->code;
364
418
  }
@@ -843,6 +897,7 @@ type_kind(agooErr err, gqlDoc doc, gqlCobj obj, gqlField field, gqlSel sel, gqlV
843
897
  case GQL_ENUM: kind = "ENUM"; break;
844
898
  case GQL_SCALAR: kind = "SCALAR"; break;
845
899
  case GQL_LIST: kind = "LIST"; break;
900
+ case GQL_NON_NULL: kind = "NON_NULL"; break;
846
901
  default:
847
902
  return agoo_err_set(err, AGOO_ERR_ARG, "__Type kind (%d) field not valid. %s:%d", ((gqlType)obj->ptr)->kind, __FILE__, __LINE__);
848
903
  }
@@ -888,7 +943,7 @@ type_fields(agooErr err, gqlDoc doc, gqlCobj obj, gqlField field, gqlSel sel, gq
888
943
  gqlType type = (gqlType)obj->ptr;
889
944
  const char *key = sel->name;
890
945
  gqlField f;
891
- gqlValue list = gql_list_create(err, NULL);
946
+ gqlValue list;
892
947
  gqlValue co;
893
948
  struct _gqlField cf;
894
949
  struct _gqlCobj child = { .clas = &field_class };
@@ -896,23 +951,23 @@ type_fields(agooErr err, gqlDoc doc, gqlCobj obj, gqlField field, gqlSel sel, gq
896
951
  gqlValue a = gql_extract_arg(err, field, sel, "includeDeprecated");
897
952
  bool inc_dep = false;
898
953
 
954
+ if (NULL != sel->alias) {
955
+ key = sel->alias;
956
+ }
899
957
  if (GQL_OBJECT != type->kind && GQL_SCHEMA != type->kind && GQL_INTERFACE != type->kind) {
900
- if (NULL == (co = gql_null_create(err)) ||
901
- AGOO_ERR_OK != gql_list_append(err, list, co)) {
958
+ if (NULL == (list = gql_null_create(err)) ||
959
+ AGOO_ERR_OK != gql_object_set(err, result, key, list)) {
902
960
  return err->code;
903
961
  }
904
962
  return AGOO_ERR_OK;
905
963
  }
906
- if (NULL != a && GQL_SCALAR_BOOL == a->type->scalar_kind && a->b) {
907
- inc_dep = true;
908
- }
909
- if (NULL != sel->alias) {
910
- key = sel->alias;
911
- }
912
- if (NULL == list ||
964
+ if (NULL == (list = gql_list_create(err, NULL)) ||
913
965
  AGOO_ERR_OK != gql_object_set(err, result, key, list)) {
914
966
  return err->code;
915
967
  }
968
+ if (NULL != a && GQL_SCALAR_BOOL == a->type->scalar_kind && a->b) {
969
+ inc_dep = true;
970
+ }
916
971
  memset(&cf, 0, sizeof(cf));
917
972
  cf.type = sel->type->base;
918
973
  for (f = type->fields; NULL != f; f = f->next) {
@@ -938,23 +993,23 @@ type_interfaces(agooErr err, gqlDoc doc, gqlCobj obj, gqlField field, gqlSel sel
938
993
  gqlType type = (gqlType)obj->ptr;
939
994
  const char *key = sel->name;
940
995
  gqlTypeLink tl;
941
- gqlValue list = gql_list_create(err, NULL);
996
+ gqlValue list;
942
997
  gqlValue co;
943
998
  struct _gqlField cf;
944
999
  struct _gqlCobj child = { .clas = &type_class };
945
1000
  int d2 = depth + 1;
946
1001
 
1002
+ if (NULL != sel->alias) {
1003
+ key = sel->alias;
1004
+ }
947
1005
  if (GQL_OBJECT != type->kind) {
948
- if (NULL == (co = gql_null_create(err)) ||
949
- AGOO_ERR_OK != gql_list_append(err, list, co)) {
1006
+ if (NULL == (list = gql_null_create(err)) ||
1007
+ AGOO_ERR_OK != gql_object_set(err, result, key, list)) {
950
1008
  return err->code;
951
1009
  }
952
1010
  return AGOO_ERR_OK;
953
1011
  }
954
- if (NULL != sel->alias) {
955
- key = sel->alias;
956
- }
957
- if (NULL == list ||
1012
+ if (NULL == (list = gql_list_create(err, NULL)) ||
958
1013
  AGOO_ERR_OK != gql_object_set(err, result, key, list)) {
959
1014
  return err->code;
960
1015
  }
@@ -970,6 +1025,18 @@ type_interfaces(agooErr err, gqlDoc doc, gqlCobj obj, gqlField field, gqlSel sel
970
1025
  return err->code;
971
1026
  }
972
1027
  }
1028
+ // The spec indicates the type is [__Type!] and makes a comment that is
1029
+ // should be non-null for Objects only. GraphiQL expected an empty list
1030
+ // which contradicts the spec.
1031
+ /*
1032
+ if (NULL == list->members) {
1033
+ gql_value_destroy(list);
1034
+ if (NULL == (list = gql_null_create(err)) ||
1035
+ AGOO_ERR_OK != gql_object_set(err, result, key, list)) {
1036
+ return err->code;
1037
+ }
1038
+ }
1039
+ */
973
1040
  return AGOO_ERR_OK;
974
1041
  }
975
1042
 
@@ -1005,7 +1072,7 @@ possible_cb(gqlType type, void *ctx) {
1005
1072
  if (AGOO_ERR_OK != pc->err->code) {
1006
1073
  return;
1007
1074
  }
1008
- if (GQL_LIST != type->kind && has_interface(type, pc->interface)) {
1075
+ if (GQL_OBJECT == type->kind && has_interface(type, pc->interface)) {
1009
1076
  gqlValue co;
1010
1077
 
1011
1078
  if (NULL == (co = gql_object_create(pc->err)) ||
@@ -1022,8 +1089,8 @@ type_possible_types(agooErr err, gqlDoc doc, gqlCobj obj, gqlField field, gqlSel
1022
1089
  gqlType type = (gqlType)obj->ptr;
1023
1090
  const char *key = sel->name;
1024
1091
  gqlTypeLink tl;
1025
- gqlValue list = gql_list_create(err, NULL);
1026
1092
  gqlValue co;
1093
+ gqlValue list;
1027
1094
  struct _gqlField cf;
1028
1095
  struct _gqlCobj child = { .clas = &type_class };
1029
1096
  int d2 = depth + 1;
@@ -1031,15 +1098,12 @@ type_possible_types(agooErr err, gqlDoc doc, gqlCobj obj, gqlField field, gqlSel
1031
1098
  if (NULL != sel->alias) {
1032
1099
  key = sel->alias;
1033
1100
  }
1034
- if (NULL == list ||
1035
- AGOO_ERR_OK != gql_object_set(err, result, key, list)) {
1036
- return err->code;
1037
- }
1038
1101
  memset(&cf, 0, sizeof(cf));
1039
1102
  cf.type = sel->type->base;
1040
1103
 
1041
1104
  switch (type->kind) {
1042
1105
  case GQL_INTERFACE: {
1106
+ list = gql_list_create(err, NULL);
1043
1107
  struct _posCtx pc = {
1044
1108
  .err = err,
1045
1109
  .doc = doc,
@@ -1050,11 +1114,18 @@ type_possible_types(agooErr err, gqlDoc doc, gqlCobj obj, gqlField field, gqlSel
1050
1114
  .child = &child,
1051
1115
  .cf = &cf,
1052
1116
  };
1053
-
1117
+ if (NULL == list ||
1118
+ AGOO_ERR_OK != gql_object_set(err, result, key, list)) {
1119
+ return err->code;
1120
+ }
1054
1121
  gql_type_iterate(possible_cb, &pc);
1055
1122
  break;
1056
1123
  }
1057
1124
  case GQL_UNION:
1125
+ if (NULL == (list = gql_list_create(err, NULL)) ||
1126
+ AGOO_ERR_OK != gql_object_set(err, result, key, list)) {
1127
+ return err->code;
1128
+ }
1058
1129
  for (tl = type->types; NULL != tl; tl = tl->next) {
1059
1130
  if (NULL == (co = gql_object_create(err)) ||
1060
1131
  AGOO_ERR_OK != gql_list_append(err, list, co)) {
@@ -1067,10 +1138,11 @@ type_possible_types(agooErr err, gqlDoc doc, gqlCobj obj, gqlField field, gqlSel
1067
1138
  }
1068
1139
  break;
1069
1140
  default:
1070
- if (NULL == (co = gql_null_create(err)) ||
1071
- AGOO_ERR_OK != gql_list_append(err, list, co)) {
1141
+ if (NULL == (list = gql_null_create(err)) ||
1142
+ AGOO_ERR_OK != gql_object_set(err, result, key, list)) {
1072
1143
  return err->code;
1073
1144
  }
1145
+ break;
1074
1146
  }
1075
1147
  return AGOO_ERR_OK;
1076
1148
  }
@@ -1082,7 +1154,7 @@ type_enum_values(agooErr err, gqlDoc doc, gqlCobj obj, gqlField field, gqlSel se
1082
1154
  gqlType type = (gqlType)obj->ptr;
1083
1155
  const char *key = sel->name;
1084
1156
  gqlEnumVal c;
1085
- gqlValue list = gql_list_create(err, NULL);
1157
+ gqlValue list;
1086
1158
  gqlValue co;
1087
1159
  struct _gqlField cf;
1088
1160
  struct _gqlCobj child = { .clas = &enum_value_class };
@@ -1090,23 +1162,23 @@ type_enum_values(agooErr err, gqlDoc doc, gqlCobj obj, gqlField field, gqlSel se
1090
1162
  gqlValue a = gql_extract_arg(err, field, sel, "includeDeprecated");
1091
1163
  bool inc_dep = false;
1092
1164
 
1165
+ if (NULL != sel->alias) {
1166
+ key = sel->alias;
1167
+ }
1093
1168
  if (GQL_ENUM != type->kind) {
1094
- if (NULL == (co = gql_null_create(err)) ||
1095
- AGOO_ERR_OK != gql_list_append(err, list, co)) {
1169
+ if (NULL == (list = gql_null_create(err)) ||
1170
+ AGOO_ERR_OK != gql_object_set(err, result, key, list)) {
1096
1171
  return err->code;
1097
1172
  }
1098
1173
  return AGOO_ERR_OK;
1099
1174
  }
1100
- if (NULL != a && GQL_SCALAR_BOOL == a->type->scalar_kind && a->b) {
1101
- inc_dep = true;
1102
- }
1103
- if (NULL != sel->alias) {
1104
- key = sel->alias;
1105
- }
1106
- if (NULL == list ||
1175
+ if (NULL == (list = gql_list_create(err, NULL)) ||
1107
1176
  AGOO_ERR_OK != gql_object_set(err, result, key, list)) {
1108
1177
  return err->code;
1109
1178
  }
1179
+ if (NULL != a && GQL_SCALAR_BOOL == a->type->scalar_kind && a->b) {
1180
+ inc_dep = true;
1181
+ }
1110
1182
  memset(&cf, 0, sizeof(cf));
1111
1183
  cf.type = sel->type->base;
1112
1184
  for (c = type->choices; NULL != c; c = c->next) {
@@ -1132,23 +1204,23 @@ type_input_fields(agooErr err, gqlDoc doc, gqlCobj obj, gqlField field, gqlSel s
1132
1204
  gqlType type = (gqlType)obj->ptr;
1133
1205
  const char *key = sel->name;
1134
1206
  gqlArg a;
1135
- gqlValue list = gql_list_create(err, NULL);
1207
+ gqlValue list;
1136
1208
  gqlValue co;
1137
1209
  struct _gqlField cf;
1138
1210
  struct _gqlCobj child = { .clas = &input_value_class };
1139
1211
  int d2 = depth + 1;
1140
1212
 
1213
+ if (NULL != sel->alias) {
1214
+ key = sel->alias;
1215
+ }
1141
1216
  if (GQL_INPUT != type->kind) {
1142
- if (NULL == (co = gql_null_create(err)) ||
1143
- AGOO_ERR_OK != gql_list_append(err, list, co)) {
1217
+ if (NULL == (list = gql_null_create(err)) ||
1218
+ AGOO_ERR_OK != gql_object_set(err, result, key, list)) {
1144
1219
  return err->code;
1145
1220
  }
1146
1221
  return AGOO_ERR_OK;
1147
1222
  }
1148
- if (NULL != sel->alias) {
1149
- key = sel->alias;
1150
- }
1151
- if (NULL == list ||
1223
+ if (NULL == (list = gql_list_create(err, NULL)) ||
1152
1224
  AGOO_ERR_OK != gql_object_set(err, result, key, list)) {
1153
1225
  return err->code;
1154
1226
  }
@@ -1229,7 +1301,7 @@ schema_types_cb(gqlType type, void *ctx) {
1229
1301
  struct _gqlCobj child = { .clas = &type_class, .ptr = (void*)type };
1230
1302
  struct _gqlField cf;
1231
1303
 
1232
- if (AGOO_ERR_OK != scc->err->code || GQL_LIST == type->kind) {
1304
+ if (AGOO_ERR_OK != scc->err->code || GQL_LIST == type->kind || GQL_NON_NULL == type->kind || GQL_SCHEMA == type->kind) {
1233
1305
  return;
1234
1306
  }
1235
1307
  memset(&cf, 0, sizeof(cf));